1 /*
2  * status.c: handles the status line updating, etc for IRCII
3  *
4  * Written By Michael Sandrof
5  *
6  * Copyright (c) 1990 Michael Sandrof.
7  * Copyright (c) 1991, 1992 Troy Rollo.
8  * Copyright (c) 1992-2020 Matthew R. Green.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 /*
36  * WARNING!  THIS CODE HAS DRAGONS.  BE *VERY* CAREFUL WHEN CHANGING
37  * ANYTHING IN HERE.  TEST IT EXTENSIVELY.
38  */
39 
40 #include "irc.h"
41 IRCII_RCSID("@(#)$eterna: status.c,v 1.132 2020/11/17 08:12:34 mrg Exp $");
42 
43 #include "ircterm.h"
44 #include "status.h"
45 #include "server.h"
46 #include "vars.h"
47 #include "hook.h"
48 #include "input.h"
49 #include "edit.h"
50 #include "window.h"
51 #include "screen.h"
52 #include "mail.h"
53 #include "output.h"
54 #include "names.h"
55 #include "ircaux.h"
56 #include "translat.h"
57 #include "debug.h"
58 
59 static	u_char	*convert_format(u_char *, int);
60 static	u_char	*status_nickname(Window *);
61 static	u_char	*status_query_nick(Window *);
62 static	u_char	*status_right_justify(Window *);
63 static	u_char	*status_chanop(Window *);
64 static	u_char	*status_channel(Window *);
65 static	u_char	*status_server(Window *);
66 static	u_char	*status_mode(Window *);
67 static	u_char	*status_umode(Window *);
68 static	u_char	*status_insert_mode(Window *);
69 static	u_char	*status_overwrite_mode(Window *);
70 static	u_char	*status_away(Window *);
71 static	u_char	*status_oper(Window *);
72 static	u_char	*status_voice(Window *);
73 static	u_char	*status_user0(Window *);
74 static	u_char	*status_user1(Window *);
75 static	u_char	*status_user2(Window *);
76 static	u_char	*status_user3(Window *);
77 static	u_char	*status_hold(Window *);
78 static	u_char	*status_version(Window *);
79 static	u_char	*status_clock(Window *);
80 static	u_char	*status_hold_lines(Window *);
81 static	u_char	*status_window(Window *);
82 static	u_char	*status_mail(Window *);
83 static	u_char	*status_refnum(Window *);
84 static	u_char	*status_null_function(Window *);
85 static	u_char	*status_notify_windows(Window *);
86 static	u_char	*status_group(Window *);
87 static	u_char	*status_scrolled(Window *);
88 static	u_char	*status_scrolled_lines(Window *);
89 static	void	alarm_switch(int);
90 static	u_char	*convert_sub_format(u_char *, int);
91 static	void	make_status_one(Window *, int, int);
92 
93 /*
94  * Maximum number of "%" expressions in a status line format. If you change
95  * this number, you must manually change the snprintf() in make_status
96  */
97 #define MAX_FUNCTIONS 45
98 
99 /* The format statements to build each portion of the status line */
100 static	u_char	*mode_format = NULL;
101 static	u_char	*umode_format = NULL;
102 static	u_char	*status_format[3] = {NULL, NULL, NULL,};
103 static	u_char	*query_format = NULL;
104 static	u_char	*clock_format = NULL;
105 static	u_char	*hold_lines_format = NULL;
106 static	u_char	*scrolled_lines_format = NULL;
107 static	u_char	*channel_format = NULL;
108 static	u_char	*mail_format = NULL;
109 static	u_char	*server_format = NULL;
110 static	u_char	*notify_format = NULL;
111 static	u_char	*group_format = NULL;
112 
113 /*
114  * status_func: The list of status line function in the proper order for
115  * display. This list is set in convert_format()
116  */
117 static	u_char	*(*status_func[3][MAX_FUNCTIONS])(Window *);
118 
119 /* func_cnt: the number of status line functions assigned */
120 static	int	func_cnt[3];
121 
122 static	int	alarm_hours,	/* hour setting for alarm in 24 hour time */
123 		alarm_minutes;	/* minute setting for alarm */
124 
125 /* Stuff for the alarm */
126 static	struct itimerval clock_timer = { { 10L, 0L }, { 1L, 0L } };
127 static	struct itimerval off_timer = { { 0L, 0L }, { 0L, 0L } };
128 
129 static	void	alarmed(int);
130 static	int	do_status_alarmed;
131 
132 /* alarmed: This is called whenever a SIGALRM is received and the alarm is on */
133 static	void
alarmed(int signo)134 alarmed(int signo)
135 {
136 	do_status_alarmed = 1;
137 }
138 
139 void
check_status_alarmed(void)140 check_status_alarmed(void)
141 {
142 	if (do_status_alarmed) {
143 		u_char	time_str[16];
144 
145 		say("The time is %s", update_clock(time_str, 16, GET_TIME));
146 		term_beep();
147 		term_beep();
148 		term_beep();
149 		do_status_alarmed = 0;
150 	}
151 }
152 
153 /*
154  * alarm_switch: turns on and off the alarm display. Sets the system timer
155  * and sets up a signal to trap SIGALRMs. If flag is 1, the alarmed()
156  * routine will be activated every 10 seconds or so. If flag is 0, the timer
157  * and signal stuff are reset
158  */
159 static	void
alarm_switch(int flag)160 alarm_switch(int flag)
161 {
162 	static	int	alarm_on = 0;
163 
164 	if (flag)
165 	{
166 		if (!alarm_on)
167 		{
168 			(void) MY_SIGNAL(SIGALRM, alarmed, 0);
169 			setitimer(ITIMER_REAL, &clock_timer,
170 				NULL);
171 			alarm_on = 1;
172 		}
173 	}
174 	else if (alarm_on)
175 	{
176 		setitimer(ITIMER_REAL, &off_timer, NULL);
177 		(void) MY_SIGNAL(SIGALRM, (sigfunc *)SIG_IGN, 0);
178 		alarm_on = 0;
179 	}
180 }
181 
182 /*
183  * set_alarm: given an input string, this checks its validity as a clock
184  * type time thingy. It accepts two time formats. The first is the HH:MM:XM
185  * format where HH is between 1 and 12, MM is between 0 and 59, and XM is
186  * either AM or PM. The second is the HH:MM format where HH is between 0 and
187  * 23 and MM is between 0 and 59. This routine also looks for one special
188  * case, "OFF", which sets the alarm string to null
189  */
190 void
set_alarm(u_char * str)191 set_alarm(u_char *str)
192 {
193 	u_char	hours[10],
194 		minutes[10],
195 		merid[3];
196 	u_char	time_str[10];
197 	int	c,
198 		h,
199 		m,
200 		min_hours,
201 		max_hours;
202 
203 	if (str == NULL)
204 	{
205 		alarm_switch(0);
206 		return;
207 	}
208 	if (!my_stricmp(str, UP(var_settings(OFF))))
209 	{
210 		set_string_var(CLOCK_ALARM_VAR, NULL);
211 		alarm_switch(0);
212 		return;
213 	}
214 
215 	c = sscanf(CP(str), " %2[^:]:%2[^paPA]%2s ", hours, minutes, merid);
216 	switch (c)
217 	{
218 	case 2:
219 		min_hours = 0;
220 		max_hours = 23;
221 		break;
222 	case 3:
223 		min_hours = 1;
224 		max_hours = 12;
225 		upper(UP(merid));
226 		break;
227 	default:
228 		say("CLOCK_ALARM: Bad time format.");
229 		set_string_var(CLOCK_ALARM_VAR, NULL);
230 		return;
231 	}
232 
233 	h = my_atoi(hours);
234 	if (h < 0)
235 		h = 0;
236 	m = my_atoi(minutes);
237 	if (m < 0)
238 		m = 0;
239 	if (h >= min_hours && h <= max_hours && isdigit(hours[0]) &&
240 		(isdigit(hours[1]) || hours[1] == '\0'))
241 	{
242 		if (m >= 0 && m <= 59 && isdigit(minutes[0]) &&
243 				isdigit(minutes[1]))
244 		{
245 			alarm_minutes = m;
246 			alarm_hours = h;
247 			if (max_hours == 12)
248 			{
249 				if (merid[0] != 'A')
250 				{
251 					if (merid[0] == 'P')
252 					{
253 						if (h != 12)
254 							alarm_hours += 12;
255 					}
256 					else
257 					{
258 	say("CLOCK_ALARM: alarm time must end with either \"AM\" or \"PM\"");
259 	set_string_var(CLOCK_ALARM_VAR, NULL);
260 					}
261 				}
262 				else
263 				{
264 					if (h == 12)
265 						alarm_hours = 0;
266 				}
267 				if (merid[1] == 'M')
268 				{
269 					snprintf(CP(time_str), sizeof time_str,
270 					    "%02d:%02d%s", h, m, merid);
271 					set_string_var(CLOCK_ALARM_VAR,
272 						time_str);
273 				}
274 				else
275 				{
276 	say("CLOCK_ALARM: alarm time must end with either \"AM\" or \"PM\"");
277 	set_string_var(CLOCK_ALARM_VAR, NULL);
278 				}
279 			}
280 			else
281 			{
282 				snprintf(CP(time_str), sizeof time_str,
283 				    "%02d:%02d", h, m);
284 				set_string_var(CLOCK_ALARM_VAR, time_str);
285 			}
286 		}
287 		else
288 		{
289 	say("CLOCK_ALARM: alarm minutes value must be between 0 and 59.");
290 	set_string_var(CLOCK_ALARM_VAR, NULL);
291 		}
292 	}
293 	else
294 	{
295 		say("CLOCK_ALARM: alarm hour value must be between %d and %d.",
296 			min_hours, max_hours);
297 		set_string_var(CLOCK_ALARM_VAR, NULL);
298 	}
299 }
300 
301 u_char	*
format_clock(u_char * buf,size_t len,int hour,int min)302 format_clock(u_char *buf, size_t len, int hour, int min)
303 {
304 	char	*merid;
305 
306 	if (get_int_var(CLOCK_24HOUR_VAR))
307 		merid = CP(empty_string());
308 	else
309 	{
310 		if (hour < 12)
311 			merid = "AM";
312 		else
313 			merid = "PM";
314 		if (hour > 12)
315 			hour -= 12;
316 		else if (hour == 0)
317 			hour = 12;
318 	}
319 	snprintf(CP(buf), len, "%02d:%02d%s", hour, min, merid);
320 
321 	return buf;
322 }
323 
324 
325 /* update_clock: figures out the current time and returns it in a nice format */
326 u_char	*
update_clock(u_char * buf,size_t len,int flag)327 update_clock(u_char *buf, size_t len, int flag)
328 {
329 	struct tm	*time_val;
330 	static	u_char	time_str[10];
331 	static	int	min = -1, hour = -1;
332 	time_t	t;
333 	int	tmp_hour, tmp_min;
334 
335 	t = time(0);
336 	time_val = localtime(&t);
337 	tmp_hour = time_val->tm_hour;
338 	tmp_min = time_val->tm_min;
339 
340 	Debug(DB_STATUS, "update_clock (%s): time %lu (%02d:%02d) [old %02d:%02d]",
341 	     flag == RESET_TIME ? "reset" :
342 	     flag == GET_TIME ? "get" :
343 	     flag == UPDATE_TIME ? "update" : "unknown",
344 	     (long unsigned) t, tmp_hour, tmp_min, hour, min);
345 
346 	if (get_string_var(CLOCK_ALARM_VAR))
347 	{
348 		if ((tmp_hour == alarm_hours) && (tmp_min == alarm_minutes))
349 			alarm_switch(1);
350 		else
351 			alarm_switch(0);
352 	}
353 
354 	if (flag == RESET_TIME ||
355 	    (flag == UPDATE_TIME && (tmp_min != min || tmp_hour != hour)))
356 	{
357 		int server;
358 
359 		format_clock(time_str, sizeof time_str, tmp_hour, tmp_min);
360 		server = set_from_server(get_primary_server());
361 		Debug(DB_STATUS, "update_clock: in reset_time block, time_str: %s",
362 		      time_str);
363 		if (flag == UPDATE_TIME && (tmp_min != min || tmp_hour != hour))
364 		{
365 			hour = tmp_hour;
366 			min = tmp_min;
367 			do_hook(TIMER_LIST, "%s", time_str);
368 		}
369 		do_hook(IDLE_LIST, "%lld", (long long)(t - idle_time()) / 60L);
370 		set_from_server(server);
371 		flag = GET_TIME;
372 	}
373 	if (buf)
374 	{
375 		my_strncpy(buf, time_str, len - 1);
376 		buf[len - 1] = '\0';
377 	}
378 	if (flag == GET_TIME)
379 		return(buf ? buf : time_str);
380 	else
381 		return (NULL);
382 }
383 
384 void
reset_clock(int unused)385 reset_clock(int unused)
386 {
387 	update_clock(0, 0, RESET_TIME);
388 	update_all_status();
389 }
390 
391 /*
392  * convert_sub_format: This is used to convert the formats of the
393  * sub-portions of the status line to a format statement specially designed
394  * for that sub-portions. convert_sub_format looks for a single occurence of
395  * %c (where c is passed to the function). When found, it is replaced by "%s"
396  * for use is a snprintf. All other occurences of % followed by any other
397  * character are left unchanged. Only the first occurence of %c is
398  * converted, all subsequence occurences are left unchanged. This routine
399  * mallocs the returned string.
400  */
401 static	u_char	*
convert_sub_format(u_char * format,int c)402 convert_sub_format(u_char *format, int c)
403 {
404 	u_char	lbuf[BIG_BUFFER_SIZE];
405 	static	u_char	bletch[] = "%% ";
406 	u_char	*ptr = NULL;
407 	int	dont_got_it = 1;
408 
409 	if (format == NULL)
410 		return (NULL);
411 	*lbuf = '\0';
412 	while (format)
413 	{
414 		if ((ptr = my_index(format, '%')) != NULL)
415 		{
416 			*ptr = '\0';
417 			my_strmcat(lbuf, format, sizeof lbuf);
418 			*(ptr++) = '%';
419 			if ((*ptr == c) && dont_got_it)
420 			{
421 				dont_got_it = 0;
422 				my_strmcat(lbuf, "%s", sizeof lbuf);
423 			}
424 			else
425 			{
426 				bletch[2] = *ptr;
427 				my_strmcat(lbuf, bletch, sizeof lbuf);
428 			}
429 			ptr++;
430 		}
431 		else
432 			my_strmcat(lbuf, format, sizeof lbuf);
433 		format = ptr;
434 	}
435 	malloc_strcpy(&ptr, lbuf);
436 	return ptr;
437 }
438 
439 static	u_char	*
convert_format(u_char * format,int k)440 convert_format(u_char *format, int k)
441 {
442 	u_char	lbuf[BIG_BUFFER_SIZE];
443 	u_char	*ptr,
444 		*malloc_ptr = NULL;
445 	int	*cp;
446 
447 	*lbuf = '\0';
448 	while (format)
449 	{
450 		if ((ptr = my_index(format, '%')) != NULL)
451 		{
452 			*ptr = '\0';
453 			my_strmcat(lbuf, format, sizeof lbuf);
454 			*(ptr++) = '%';
455 			cp = &func_cnt[k];
456 			if (*cp < MAX_FUNCTIONS)
457 			{
458 				switch (*(ptr++))
459 				{
460 				case '%':
461 					/*
462 					 * %% instead of %, because this will
463 					 * be passed to snprintf
464 					 */
465 					my_strmcat(lbuf, "%%", sizeof lbuf);
466 					break;
467 				case 'N':
468 					my_strmcat(lbuf, "%s", sizeof lbuf);
469 					status_func[k][(*cp)++] =
470 						status_nickname;
471 					break;
472 				case '>':
473 					my_strmcat(lbuf, "%s", sizeof lbuf);
474 					status_func[k][(*cp)++] =
475 						status_right_justify;
476 					break;
477 				case 'G':
478 					new_free(&group_format);
479 					group_format =
480 		convert_sub_format(get_string_var(STATUS_GROUP_VAR), 'G');
481 					my_strmcat(lbuf, "%s", sizeof lbuf);
482 					status_func[k][(*cp)++] =
483 						status_group;
484 					break;
485 				case 'Q':
486 					new_free(&query_format);
487 					query_format =
488 		convert_sub_format(get_string_var(STATUS_QUERY_VAR), 'Q');
489 					my_strmcat(lbuf, "%s", sizeof lbuf);
490 					status_func[k][(*cp)++] =
491 						status_query_nick;
492 					break;
493 				case 'F':
494 					new_free(&notify_format);
495 					notify_format =
496 		convert_sub_format(get_string_var(STATUS_NOTIFY_VAR), 'F');
497 					my_strmcat(lbuf, "%s", sizeof lbuf);
498 					status_func[k][(*cp)++] =
499 						status_notify_windows;
500 					break;
501 				case '@':
502 					my_strmcat(lbuf, "%s", sizeof lbuf);
503 					status_func[k][(*cp)++] =
504 						status_chanop;
505 					break;
506 				case 'C':
507 					new_free(&channel_format);
508 					channel_format =
509 		convert_sub_format(get_string_var(STATUS_CHANNEL_VAR), 'C');
510 					my_strmcat(lbuf, "%s", sizeof lbuf);
511 					status_func[k][(*cp)++] =
512 						status_channel;
513 					break;
514 				case 'S':
515 					new_free(&server_format);
516 					server_format =
517 		convert_sub_format(get_string_var(STATUS_SERVER_VAR), 'S');
518 					my_strmcat(lbuf,"%s",sizeof lbuf);
519 					status_func[k][(*cp)++] =
520 						status_server;
521 					break;
522 				case '+':
523 					new_free(&mode_format);
524 					mode_format =
525 		convert_sub_format(get_string_var(STATUS_MODE_VAR), '+');
526 					my_strmcat(lbuf, "%s", sizeof lbuf);
527 					status_func[k][(*cp)++] =
528 						status_mode;
529 					break;
530 				case '#':
531 					new_free(&umode_format);
532 					umode_format =
533 		convert_sub_format(get_string_var(STATUS_UMODE_VAR), '#');
534 					my_strmcat(lbuf, "%s", sizeof lbuf);
535 					status_func[k][(*cp)++] =
536 						status_umode;
537 					break;
538 				case 'M':
539 					new_free(&mail_format);
540 					mail_format =
541 		convert_sub_format(get_string_var(STATUS_MAIL_VAR), 'M');
542 					my_strmcat(lbuf, "%s", sizeof lbuf);
543 					status_func[k][(*cp)++] =
544 						status_mail;
545 					break;
546 				case 'I':
547 					my_strmcat(lbuf, "%s", sizeof lbuf);
548 					status_func[k][(*cp)++] =
549 						status_insert_mode;
550 					break;
551 				case 'O':
552 					my_strmcat(lbuf, "%s", sizeof lbuf);
553 					status_func[k][(*cp)++] =
554 						status_overwrite_mode;
555 					break;
556 				case 'A':
557 					my_strmcat(lbuf, "%s", sizeof lbuf);
558 					status_func[k][(*cp)++] =
559 						status_away;
560 					break;
561 				case 'V':
562 					my_strmcat(lbuf, "%s", sizeof lbuf);
563 					status_func[k][(*cp)++] =
564 						status_version;
565 					break;
566 				case 'R':
567 					my_strmcat(lbuf, "%s", sizeof lbuf);
568 					status_func[k][(*cp)++] =
569 						status_refnum;
570 					break;
571 				case 'T':
572 					new_free(&clock_format);
573 					clock_format =
574 		convert_sub_format(get_string_var(STATUS_CLOCK_VAR), 'T');
575 					my_strmcat(lbuf, "%s", sizeof lbuf);
576 					status_func[k][(*cp)++] =
577 						status_clock;
578 					break;
579 				case 'U':
580 					my_strmcat(lbuf, "%s", sizeof lbuf);
581 					status_func[k][(*cp)++] =
582 						status_user0;
583 					break;
584 				case 'H':
585 					my_strmcat(lbuf, "%s", sizeof lbuf);
586 					status_func[k][(*cp)++] =
587 						status_hold;
588 					break;
589 				case 'B':
590 					new_free(&hold_lines_format);
591 					hold_lines_format =
592 		convert_sub_format(get_string_var(STATUS_HOLD_LINES_VAR), 'B');
593 					my_strmcat(lbuf, "%s", sizeof lbuf);
594 					status_func[k][(*cp)++] =
595 						status_hold_lines;
596 					break;
597 				case 'P':
598 					my_strmcat(lbuf, "%s", sizeof lbuf);
599 					status_func[k][(*cp)++] =
600 						status_scrolled;
601 					Debug(DB_STATUS, "got P in status");
602 					break;
603 				case 's':
604 					new_free(&scrolled_lines_format);
605 					scrolled_lines_format =
606 		convert_sub_format(get_string_var(STATUS_SCROLLED_LINES_VAR), 's');
607 					my_strmcat(lbuf, "%s", sizeof lbuf);
608 					status_func[k][(*cp)++] =
609 						status_scrolled_lines;
610 					Debug(DB_STATUS, "got s status: slformat '%s'",
611 					      scrolled_lines_format);
612 					break;
613 				case '*':
614 					my_strmcat(lbuf, "%s", sizeof lbuf);
615 					status_func[k][(*cp)++] =
616 						status_oper;
617 					break;
618 				case 'v':
619 					my_strmcat(lbuf, "%s", sizeof lbuf);
620 					status_func[k][(*cp)++] =
621 						status_voice;
622 					break;
623 				case 'W':
624 					my_strmcat(lbuf, "%s", sizeof lbuf);
625 					status_func[k][(*cp)++] =
626 						status_window;
627 					break;
628 				case 'X':
629 					my_strmcat(lbuf, "%s", sizeof lbuf);
630 					status_func[k][(*cp)++] =
631 						status_user1;
632 					break;
633 				case 'Y':
634 					my_strmcat(lbuf, "%s", sizeof lbuf);
635 					status_func[k][(*cp)++] =
636 						status_user2;
637 					break;
638 				case 'Z':
639 					my_strmcat(lbuf, "%s", sizeof lbuf);
640 					status_func[k][(*cp)++] =
641 						status_user3;
642 					break;
643 		/* no default..?? - phone, jan 1993 */
644 		/* empty is a good default -lynx, mar 93 */
645 				}
646 			}
647 			else
648 				ptr++;
649 		}
650 		else
651 			my_strmcat(lbuf, format, sizeof lbuf);
652 		format = ptr;
653 	}
654 	/* this frees the old str first */
655 	malloc_strcpy(&malloc_ptr, lbuf);
656 	return (malloc_ptr);
657 }
658 
659 void
build_status(u_char * format)660 build_status(u_char *format)
661 {
662 	int	i, k;
663 
664 	for (k = 0; k < 3; k++)
665 	{
666 		new_free(&status_format[k]);
667 		func_cnt[k] = 0;
668 		switch (k)
669 		{
670 		case 0 :
671 			format = get_string_var(STATUS_FORMAT_VAR);
672 			break;
673 
674 		case 1 :
675 			format = get_string_var(STATUS_FORMAT1_VAR);
676 			break;
677 
678 		case 2 :
679 			format = get_string_var(STATUS_FORMAT2_VAR);
680 			break;
681 		}
682 		if (format != NULL)	/* convert_format mallocs for us */
683 			status_format[k] = convert_format(format, k);
684 		for (i = func_cnt[k]; i < MAX_FUNCTIONS; i++)
685 			status_func[k][i] = status_null_function;
686 	}
687 	update_all_status();
688 }
689 
690 void
make_status(Window * window)691 make_status(Window *window)
692 {
693 	int	k, l, final;
694 
695 	switch (window_get_double_status(window)) {
696 	case -1:
697 		window_set_status_line(window, 0, NULL);
698 		window_set_status_line(window, 1, NULL);
699 		goto out;
700 	case 0:
701 		window_set_status_line(window, 1, NULL);
702 		final = 1;
703 		break;
704 	case 1:
705 		final = 2;
706 		break;
707 	default:
708 		yell("--- make_status: unknown window->double value %d",
709 		     window_get_double_status(window));
710 		final = 1;
711 	}
712 	for (k = 0 ; k < final; k++)
713 	{
714 		if (k)
715 			l = 2;
716 		else if (window_get_double_status(window))
717 			l = 1;
718 		else
719 			l = 0;
720 
721 		if (!term_basic() && status_format[l])
722 			make_status_one(window, k, l);
723 	}
724 out:
725 	cursor_to_input();
726 }
727 
728 static	void
make_status_one(Window * window,int k,int l)729 make_status_one(Window *window, int k, int l)
730 {
731 	Screen	*old_current_screen;
732 	u_char	lbuf[BIG_BUFFER_SIZE]; /* XXX */
733 	u_char	rbuf[BIG_BUFFER_SIZE]; /* XXX */
734 	u_char	*func_value[MAX_FUNCTIONS];
735 	size_t	len;
736 	int	i;
737 	int rjustifypos;
738 	int justifypadlen;
739 	int RealPosition;
740 
741 	/*
742 	 * XXX: note that this code below depends on the definition
743 	 * of MAX_FUNCTIONS (currently 45), and the snprintf must
744 	 * be updated if MAX_FUNCTIONS is changed.
745 	 */
746 	for (i = 0; i < MAX_FUNCTIONS; i++)
747 		func_value[i] = (status_func[l][i]) (window);
748 	lbuf[0] = REV_TOG;
749 	snprintf(CP(lbuf+1),
750 	        sizeof(lbuf) - 1,
751 	        CP(status_format[l]),
752 		func_value[0], func_value[1], func_value[2],
753 		func_value[3], func_value[4], func_value[5],
754 		func_value[6], func_value[7], func_value[8],
755 		func_value[9], func_value[10], func_value[11],
756 		func_value[12], func_value[13], func_value[14],
757 		func_value[15], func_value[16], func_value[17],
758 		func_value[18], func_value[19], func_value[20],
759 		func_value[21], func_value[22], func_value[23],
760 		func_value[24], func_value[25], func_value[26],
761 		func_value[27], func_value[28], func_value[29],
762 		func_value[30], func_value[31], func_value[32],
763 		func_value[33], func_value[34], func_value[35],
764 		func_value[36], func_value[37], func_value[38],
765 		func_value[39], func_value[40], func_value[41],
766 		func_value[42], func_value[43], func_value[44]);
767 	for (i = 0; i < MAX_FUNCTIONS; i++)
768 		new_free(&(func_value[i]));
769 
770 	/* Patched 26-Mar-93 by Aiken
771 	 * make_window now right-justifies everything after a %>
772 	 */
773 
774 	rjustifypos   = -1;
775 	justifypadlen = 0;
776 	for (i = 0; lbuf[i]; i++)
777 	{
778 		/* formfeed is a marker for left/right border*/
779 		if (lbuf[i] == '\f')
780 		{
781 			int len_left;
782 			int len_right;
783 
784 			/* Split the line to left and right part */
785 			lbuf[i] = '\0';
786 
787 			/*
788 			 * Get lengths of left and right part in number of
789 			 * columns
790 			 */
791 			len_right = my_strlen_c(lbuf);
792 			len_left  = my_strlen_c(lbuf+i+1);
793 
794 			justifypadlen = get_co() - len_right - len_left;
795 
796 			if (justifypadlen < 0)
797 				justifypadlen = 0;
798 
799 			/* Delete the marker.  */
800 			my_strcpy(lbuf+i, lbuf+i+1);
801 
802 			rjustifypos = i;
803 		}
804 	}
805 
806 	if (get_int_var(FULL_STATUS_LINE_VAR))
807 	{
808 		if (rjustifypos == -1)
809 		{
810 			int length = my_strlen_c(lbuf);
811 
812 			justifypadlen = get_co() - length;
813 			if (justifypadlen < 0)
814 				justifypadlen = 0;
815 			rjustifypos = my_strlen(lbuf);
816 		}
817 		if (justifypadlen > 0)
818 		{
819 			/* Move a part of the data out of way */
820 			memmove(lbuf + rjustifypos + justifypadlen,
821 				lbuf + rjustifypos,
822 				my_strlen(lbuf) - rjustifypos + 1);
823 					// +1 = zero terminator
824 
825 			/* Then fill the part with spaces */
826 			memset(lbuf + rjustifypos, ' ', justifypadlen);
827 		}
828 	}
829 
830 	len = my_strlen(lbuf);
831 	if (len > (sizeof(lbuf) - 2))
832 		len = sizeof(lbuf) - 2;
833 	lbuf[len] = ALL_OFF;
834 	lbuf[len+1] = '\0';
835 
836 	my_strcpy_ci(rbuf, sizeof rbuf, lbuf);
837 
838 	RealPosition = 0;
839 	i = 0;
840 
841 	old_current_screen = get_current_screen();
842 	set_current_screen(window_get_screen(window));
843 	term_move_cursor(RealPosition, window_get_bottom(window) + k);
844 	len = output_line(rbuf, i);
845 	cursor_in_display();
846 #ifdef TERM_USE_LAST_COLUMN
847 	/*
848 	 * If ignoring the last column, always erase it, but
849 	 * if it is in use, only do so if we haven't writtten
850 	 * there.
851 	 */
852 	if (len < get_co() && term_clear_to_eol())
853 #else
854 	if (term_clear_to_eol() && len < get_co())
855 #endif
856 		term_space_erase(get_co() - len);
857 	window_set_status_line(window, k, rbuf);
858 	set_current_screen(old_current_screen);
859 }
860 
861 static	u_char	*
status_nickname(Window * window)862 status_nickname(Window *window)
863 {
864 	u_char	*ptr = NULL;
865 
866 	if (connected_to_server() == 1 && !get_int_var(SHOW_STATUS_ALL_VAR) &&
867 	    !window_get_current_channel(window) && !window_is_current(window))
868 		malloc_strcpy(&ptr, empty_string());
869 	else
870 		malloc_strcpy(&ptr,
871 			server_get_nickname(window_get_server(window)));
872 	return ptr;
873 }
874 
875 static	u_char	*
status_server(Window * window)876 status_server(Window *window)
877 {
878 	u_char	*ptr = NULL,
879 		*rest,
880 		*name;
881 
882 	if (connected_to_server() != 1)
883 	{
884 		int	server = window_get_server(window);
885 
886 		if (server != -1)
887 		{
888 			if (server_format)
889 			{
890 				name = server_get_name(server);
891 				rest = my_index(name, '.');
892 				if (rest != NULL &&
893 				    my_strnicmp(name, UP("irc"), 3) != 0 &&
894 				    my_strnicmp(name, UP("icb"), 3) != 0 &&
895 				    !is_number(name))
896 				{
897 					*rest = '\0';
898 					malloc_snprintf(&ptr, CP(server_format), name);
899 					*rest = '.';
900 				}
901 				else
902 					malloc_snprintf(&ptr, CP(server_format), name);
903 			}
904 		}
905 		else
906 			malloc_strcpy(&ptr, UP(" No Server"));
907 	}
908 	if (ptr == NULL)
909 		malloc_strcpy(&ptr, empty_string());
910 	return ptr;
911 }
912 
913 static	u_char	*
status_group(Window * window)914 status_group(Window *window)
915 {
916 	u_char	*ptr = NULL;
917 	int	group;
918 
919 	group = window_get_server_group(window);
920 	if (group && group_format)
921 		malloc_snprintf(&ptr, CP(group_format), find_server_group_name(group));
922 	else
923 		malloc_strcpy(&ptr, empty_string());
924 	return ptr;
925 }
926 
927 static	u_char	*
status_query_nick(Window * window)928 status_query_nick(Window *window)
929 {
930 	u_char	*ptr = NULL;
931 
932 	if (window_get_query_nick(window) && query_format)
933 		malloc_snprintf(&ptr, CP(query_format), window_get_query_nick(window));
934 	else
935 		malloc_strcpy(&ptr, empty_string());
936 	return ptr;
937 }
938 
939 static	u_char	*
status_right_justify(Window * window)940 status_right_justify(Window *window)
941 {
942 	u_char	*ptr = NULL;
943 
944 	malloc_strcpy(&ptr, UP("\f"));
945 	return ptr;
946 }
947 
948 static	u_char	*
status_notify_windows(Window * window)949 status_notify_windows(Window *window)
950 {
951 	u_char	refnum[10];
952 	int	doneone = 0;
953 	u_char	*ptr = NULL;
954 	u_char	buf2[81];
955 
956 	if (get_int_var(SHOW_STATUS_ALL_VAR) || window_is_current(window))
957 	{
958 		Win_Trav wt;
959 
960 		buf2[0] = '\0';
961 		wt.init = 1;
962 		while ((window = window_traverse(&wt)) != NULL)
963 		{
964 			if (window_get_miscflags(window) & WINDOW_NOTIFIED)
965 			{
966 				if (!doneone)
967 				{
968 					doneone++;
969 					snprintf(CP(refnum), sizeof refnum,
970 						"%d", window_get_refnum(window));
971 				}
972 				else
973 					snprintf(CP(refnum), sizeof refnum,
974 						",%d", window_get_refnum(window));
975 				my_strmcat(buf2, refnum, sizeof buf2);
976 			}
977 		}
978 	}
979 	if (doneone && notify_format)
980 		malloc_snprintf(&ptr, CP(notify_format), buf2);
981 	else
982 		malloc_strcpy(&ptr, empty_string());
983 	return ptr;
984 }
985 
986 static	u_char	*
status_clock(Window * window)987 status_clock(Window *window)
988 {
989 	u_char	*ptr = NULL;
990 
991 	if (get_int_var(CLOCK_VAR) && clock_format &&
992 	    (get_int_var(SHOW_STATUS_ALL_VAR) || window_is_current(window)))
993 	{
994 		u_char	time_str[16];
995 
996 		malloc_snprintf(&ptr, CP(clock_format),
997 			update_clock(time_str, sizeof time_str, GET_TIME));
998 	}
999 	else
1000 		malloc_strcpy(&ptr, empty_string());
1001 	return ptr;
1002 }
1003 
1004 static	u_char	*
status_mode(Window * window)1005 status_mode(Window *window)
1006 {
1007 	u_char	*ptr = NULL;
1008 	u_char	*channel = window_get_current_channel(window);
1009 	int	server = window_get_server(window);
1010 
1011 	if (channel && chan_is_connected(channel, server))
1012 	{
1013 		u_char	*mode;
1014 
1015 		mode = get_channel_mode(channel, server);
1016 		if (mode && *mode && mode_format)
1017 		{
1018 			malloc_snprintf(&ptr, CP(mode_format), mode);
1019 			return ptr;
1020 		}
1021 	}
1022 	malloc_strcpy(&ptr, empty_string());
1023 	return ptr;
1024 }
1025 
1026 
1027 static	u_char	*
status_umode(Window * window)1028 status_umode(Window *window)
1029 {
1030 	u_char	*ptr = NULL;
1031 	u_char	localbuf[10];
1032 	u_char	*c;
1033 	int	server = window_get_server(window);
1034 
1035 	if (connected_to_server() == 0)
1036 		malloc_strcpy(&ptr, empty_string());
1037 	else if (connected_to_server() == 1 &&
1038 		 !get_int_var(SHOW_STATUS_ALL_VAR) &&
1039 		 !window_is_current(window))
1040 		malloc_strcpy(&ptr, empty_string());
1041 	else
1042 	{
1043 		c = localbuf;
1044 		if (server_get_flag(server, USER_MODE_I))
1045 			*c++ = 'i';
1046 		if (server_get_operator(server))
1047 			*c++ = 'o';
1048 		if (server_get_flag(server, USER_MODE_R))
1049 			*c++ = 'r';
1050 		if (server_get_flag(server, USER_MODE_S))
1051 			*c++ = 's';
1052 		if (server_get_flag(server, USER_MODE_W))
1053 			*c++ = 'w';
1054 		if (server_get_flag(server, USER_MODE_Z))
1055 			*c++ = 'z';
1056 		*c++ = '\0';
1057 		if (*localbuf != '\0' && umode_format)
1058 			malloc_snprintf(&ptr, CP(umode_format), localbuf);
1059 		else
1060 			malloc_strcpy(&ptr, empty_string());
1061 	}
1062 	return ptr;
1063 }
1064 
1065 static	u_char	*
status_chanop(Window * window)1066 status_chanop(Window *window)
1067 {
1068 	u_char	*ptr = NULL,
1069 		*text;
1070 	u_char	*channel = window_get_current_channel(window);
1071 	int	server = window_get_server(window);
1072 
1073 	if (channel &&
1074 	    chan_is_connected(channel, server) &&
1075 	    get_channel_oper(channel, server) &&
1076 	    (text = get_string_var(STATUS_CHANOP_VAR)))
1077 		malloc_strcpy(&ptr, text);
1078 	else
1079 		malloc_strcpy(&ptr, empty_string());
1080 	return ptr;
1081 }
1082 
1083 
1084 static	u_char	*
status_hold_lines(Window * window)1085 status_hold_lines(Window *window)
1086 {
1087 	u_char	*ptr = NULL;
1088 	int	num;
1089 	int	lines = window_held_lines(window);
1090 
1091 	num = lines - lines % 10;
1092 	if (num)
1093 	{
1094 		u_char	localbuf[40];
1095 
1096 		snprintf(CP(localbuf), sizeof localbuf, "%d", num);
1097 		malloc_snprintf(&ptr, CP(hold_lines_format), localbuf);
1098 	}
1099 	else
1100 		malloc_strcpy(&ptr, empty_string());
1101 	return ptr;
1102 }
1103 
1104 static	u_char	*
status_scrolled(Window * window)1105 status_scrolled(Window *window)
1106 {
1107 	u_char	*ptr = NULL,
1108 		*text;
1109 	int	lines = window_get_all_scrolled_lines(window);
1110 
1111 	Debug(DB_STATUS, "status_scrolled: lines = %d", lines);
1112 	if (lines && (text = get_string_var(STATUS_SCROLLED_VAR)))
1113 		malloc_strcpy(&ptr, text);
1114 	else
1115 		malloc_strcpy(&ptr, empty_string());
1116 	return ptr;
1117 }
1118 
1119 static	u_char	*
status_scrolled_lines(Window * window)1120 status_scrolled_lines(Window *window)
1121 {
1122 	u_char	*ptr = NULL;
1123 	int	lines = window_get_all_scrolled_lines(window);
1124 
1125 	if (lines)
1126 	{
1127 		u_char	localbuf[40];
1128 
1129 		snprintf(CP(localbuf), sizeof localbuf, "%d", lines);
1130 		malloc_snprintf(&ptr, CP(hold_lines_format), localbuf);
1131 	}
1132 	else
1133 		malloc_strcpy(&ptr, empty_string());
1134 	Debug(DB_STATUS, "status_scrolled_lines: lines = %d, str = '%s'", lines, ptr);
1135 	return ptr;
1136 }
1137 
1138 static	u_char	*
status_channel(Window * window)1139 status_channel(Window *window)
1140 {
1141 	int	num;
1142 	u_char	*s, *ptr;
1143 	int	server = window_get_server(window);
1144 
1145 	s = window_get_current_channel(window);
1146 	if (s && chan_is_connected(s, server))
1147 	{
1148 		u_char	channel[IRCD_BUFFER_SIZE + 1];
1149 
1150 		if (get_int_var(HIDE_PRIVATE_CHANNELS_VAR) &&
1151 		    is_channel_mode(window_get_current_channel(window),
1152 				MODE_PRIVATE | MODE_SECRET, server))
1153 			ptr = UP("*private*");
1154 		else
1155 			ptr = window_get_current_channel(window);
1156 		strmcpy(channel, ptr, IRCD_BUFFER_SIZE);
1157 		if ((num = get_int_var(CHANNEL_NAME_WIDTH_VAR)) &&
1158 		    ((int) my_strlen(channel) > num))
1159 			channel[num] = '\0';
1160 		ptr = NULL;
1161 		malloc_snprintf(&ptr, CP(channel_format), channel);
1162 	}
1163 	else
1164 	{
1165 		ptr = NULL;
1166 		malloc_strcpy(&ptr, empty_string());
1167 	}
1168 	return ptr;
1169 }
1170 
1171 static	u_char	*
status_mail(Window * window)1172 status_mail(Window *window)
1173 {
1174 	u_char	*ptr = NULL,
1175 		*number;
1176 
1177 	if (get_int_var(MAIL_VAR) && (number = check_mail()) && mail_format &&
1178 	    (get_int_var(SHOW_STATUS_ALL_VAR) || window_is_current(window)))
1179 		malloc_snprintf(&ptr, CP(mail_format), number);
1180 	else
1181 		malloc_strcpy(&ptr, empty_string());
1182 	return ptr;
1183 }
1184 
1185 static	u_char	*
status_insert_mode(Window * window)1186 status_insert_mode(Window *window)
1187 {
1188 	u_char	*ptr = NULL,
1189 		*text;
1190 
1191 	text = empty_string();
1192 	if (get_int_var(INSERT_MODE_VAR) &&
1193 	    (get_int_var(SHOW_STATUS_ALL_VAR) || window_is_current(window)))
1194 	{
1195 		if ((text = get_string_var(STATUS_INSERT_VAR)) == NULL)
1196 			text = empty_string();
1197 	}
1198 	malloc_strcpy(&ptr, text);
1199 	return ptr;
1200 }
1201 
1202 static	u_char	*
status_overwrite_mode(Window * window)1203 status_overwrite_mode(Window *window)
1204 {
1205 	u_char	*ptr = NULL,
1206 		*text;
1207 
1208 	text = empty_string();
1209 	if (!get_int_var(INSERT_MODE_VAR) &&
1210 	    (get_int_var(SHOW_STATUS_ALL_VAR) || window_is_current(window)))
1211 	{
1212 	    if ((text = get_string_var(STATUS_OVERWRITE_VAR)) == NULL)
1213 		text = empty_string();
1214 	}
1215 	malloc_strcpy(&ptr, text);
1216 	return ptr;
1217 }
1218 
1219 static	u_char	*
status_away(Window * window)1220 status_away(Window *window)
1221 {
1222 	u_char	*ptr = NULL,
1223 		*text;
1224 
1225 	if (connected_to_server() == 0)
1226 		malloc_strcpy(&ptr, empty_string());
1227 	else if (connected_to_server() == 1 &&
1228 		 !get_int_var(SHOW_STATUS_ALL_VAR) &&
1229 		 !window_is_current(window))
1230 		malloc_strcpy(&ptr, empty_string());
1231 	else
1232 	{
1233 		if (server_get_away(window_get_server(window)) &&
1234 				(text = get_string_var(STATUS_AWAY_VAR)))
1235 			malloc_strcpy(&ptr, text);
1236 		else
1237 			malloc_strcpy(&ptr, empty_string());
1238 	}
1239 	return ptr;
1240 }
1241 
1242 static	u_char *
status_user0(Window * window)1243 status_user0(Window *window)
1244 {
1245 	u_char	*ptr = NULL,
1246 		*text;
1247 
1248 	if ((text = get_string_var(STATUS_USER_VAR)) &&
1249 	    (get_int_var(SHOW_STATUS_ALL_VAR) || window_is_current(window)))
1250 		malloc_strcpy(&ptr, text);
1251 	else
1252 		malloc_strcpy(&ptr, empty_string());
1253 	return ptr;
1254 }
1255 
1256 static  u_char *
status_user1(Window * window)1257 status_user1(Window *window)
1258 {
1259 	u_char	*ptr = NULL,
1260 		*text;
1261 
1262 	if ((text = get_string_var(STATUS_USER1_VAR)) &&
1263 	    (get_int_var(SHOW_STATUS_ALL_VAR) || window_is_current(window)))
1264 		malloc_strcpy(&ptr, text);
1265 	else
1266 		malloc_strcpy(&ptr, empty_string());
1267 	return ptr;
1268 }
1269 
1270 static  u_char *
status_user2(Window * window)1271 status_user2(Window *window)
1272 {
1273 	u_char	*ptr = NULL,
1274 		*text;
1275 
1276 	if ((text = get_string_var(STATUS_USER2_VAR)) &&
1277 	    (get_int_var(SHOW_STATUS_ALL_VAR) || window_is_current(window)))
1278 		malloc_strcpy(&ptr, text);
1279 	else
1280 		malloc_strcpy(&ptr, empty_string());
1281 	return ptr;
1282 }
1283 
1284 static  u_char    *
status_user3(Window * window)1285 status_user3(Window *window)
1286 {
1287 	u_char	*ptr = NULL,
1288 		*text;
1289 
1290 	if ((text = get_string_var(STATUS_USER3_VAR)) &&
1291 	    (get_int_var(SHOW_STATUS_ALL_VAR) || window_is_current(window)))
1292 		malloc_strcpy(&ptr, text);
1293 	else
1294 		malloc_strcpy(&ptr, empty_string());
1295 	return ptr;
1296 }
1297 
1298 static	u_char	*
status_hold(Window * window)1299 status_hold(Window *window)
1300 {
1301 	u_char	*ptr = NULL,
1302 		*text;
1303 
1304 	if (window_held(window) && (text = get_string_var(STATUS_HOLD_VAR)))
1305 		malloc_strcpy(&ptr, text);
1306 	else
1307 		malloc_strcpy(&ptr, empty_string());
1308 	return ptr;
1309 }
1310 
1311 static	u_char	*
status_oper(Window * window)1312 status_oper(Window *window)
1313 {
1314 	u_char	*ptr = NULL,
1315 		*text;
1316 
1317 	if (!connected_to_server())
1318 		malloc_strcpy(&ptr, empty_string());
1319 	else if (server_get_operator(window_get_server(window)) &&
1320 		 (text = get_string_var(STATUS_OPER_VAR)) &&
1321 		 (get_int_var(SHOW_STATUS_ALL_VAR) ||
1322 		  connected_to_server() != 1 ||
1323 		  window_is_current(window)))
1324 		malloc_strcpy(&ptr, text);
1325 	else
1326 		malloc_strcpy(&ptr, empty_string());
1327 	return ptr;
1328 }
1329 
1330 static	u_char	*
status_voice(Window * window)1331 status_voice(Window *window)
1332 {
1333 	u_char	*ptr = NULL,
1334 		*text;
1335 	int	server = window_get_server(window);
1336 
1337 	if (!connected_to_server())
1338 		malloc_strcpy(&ptr, empty_string());
1339 	else if (has_voice(window_get_current_channel(window),
1340 			   server_get_nickname(server),
1341 			   server) &&
1342 		 (text = get_string_var(STATUS_VOICE_VAR)) &&
1343 		 (get_int_var(SHOW_STATUS_ALL_VAR) ||
1344 		  connected_to_server() != 1 || window_is_current(window)))
1345 		malloc_strcpy(&ptr, text);
1346 	else
1347 		malloc_strcpy(&ptr, empty_string());
1348 	return ptr;
1349 }
1350 
1351 static	u_char	*
status_window(Window * window)1352 status_window(Window *window)
1353 {
1354 	u_char	*ptr = NULL,
1355 		*text;
1356 
1357 	if ((text = get_string_var(STATUS_WINDOW_VAR)) &&
1358 	    number_of_windows() > 1 && window_is_current(window))
1359 		malloc_strcpy(&ptr, text);
1360 	else
1361 		malloc_strcpy(&ptr, empty_string());
1362 	return ptr;
1363 }
1364 
1365 static	u_char	*
status_refnum(Window * window)1366 status_refnum(Window *window)
1367 {
1368 	u_char	*ptr = NULL;
1369 	u_char	*name = window_get_name(window);
1370 
1371 	if (name)
1372 		malloc_strcpy(&ptr, name);
1373 	else
1374 		malloc_snprintf(&ptr, "%u", window_get_refnum(window));
1375 	return ptr;
1376 }
1377 
1378 static	u_char	*
status_version(Window * window)1379 status_version(Window *window)
1380 {
1381 	u_char	*ptr = NULL;
1382 
1383 	if (connected_to_server() == 1 && !get_int_var(SHOW_STATUS_ALL_VAR) &&
1384 	    !window_is_current(window))
1385 		malloc_strcpy(&ptr, empty_string());
1386 	else
1387 		malloc_strcpy(&ptr, irc_version());
1388 	return ptr;
1389 }
1390 
1391 static	u_char	*
status_null_function(Window * window)1392 status_null_function(Window *window)
1393 {
1394 	u_char	*ptr = NULL;
1395 
1396 	malloc_strcpy(&ptr, empty_string());
1397 	return ptr;
1398 }
1399