1 /*
2  * hold.c: handles buffering of display output.
3  *
4  * Written By Michael Sandrof
5  *
6  * Copyright (c) 1990 Michael Sandrof.
7  * Copyright (c) 1991, 1992 Troy Rollo.
8  * Copyright (c) 1992-2014 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 #include "irc.h"
36 IRCII_RCSID("@(#)$eterna: hold.c,v 1.30 2014/02/21 11:04:36 mrg Exp $");
37 
38 #include "ircaux.h"
39 #include "window.h"
40 #include "screen.h"
41 #include "vars.h"
42 #include "input.h"
43 
44 /* Hold: your general doubly-linked list type structure */
45 struct hold_stru
46 {
47 	u_char	*str;
48 	Hold	*next;
49 	Hold	*prev;
50 	int	logged;
51 };
52 
53 /* HoldInfo: stuff specific to this module. */
54 struct hold_info_stru
55 {
56 	int	held;		/* true, the window is currently being held */
57 	int	last_held;	/* Previous value of hold flag.
58 				   Used for various updating needs */
59 	Hold	*hold_head,	/* Pointer to first entry in hold list */
60 		*hold_tail;	/* Pointer to last entry in hold list */
61 	int	held_lines;	/* number of lines being held */
62 };
63 
64 /* reset_hold: Make hold_mode behave like VM CHAT, hold only
65  * when there is no user interaction, this should be called
66  * whenever the user does something in a window.  -lynx
67  */
68 void
reset_hold(Window * win)69 reset_hold(Window *win)
70 {
71 	if (!win)
72 		win = curr_scr_win;
73 	if (!window_get_scrolled_lines(win))
74 		window_set_line_cnt(win, 0);
75 }
76 
77 /* add_to_hold_list: adds str to the hold list queue */
78 void
add_to_hold_list(Window * window,HoldInfo * info,u_char * str,int logged)79 add_to_hold_list(Window *window, HoldInfo *info, u_char *str, int logged)
80 {
81 	Hold	*new;
82 	unsigned int	max;
83 
84 	new = new_malloc(sizeof *new);
85 	new->str = NULL;
86 	malloc_strcpy(&(new->str), str);
87 	new->logged = logged;
88 	info->held_lines++;
89 	if ((max = get_int_var(HOLD_MODE_MAX_VAR)) != 0)
90 	{
91 		if (info->held_lines > max)
92 			hold_mode(window, info, OFF, 1);
93 	}
94 	new->next = info->hold_head;
95 	new->prev = NULL;
96 	if (info->hold_tail == NULL)
97 		info->hold_tail = new;
98 	if (info->hold_head)
99 		info->hold_head->prev = new;
100 	info->hold_head = new;
101 	update_all_status();
102 }
103 
104 /* remove_from_hold_list: pops the next element off the hold list queue. */
105 void
remove_from_hold_list(HoldInfo * info)106 remove_from_hold_list(HoldInfo *info)
107 {
108 	Hold	*crap;
109 
110 	if (info->hold_tail)
111 	{
112 		info->held_lines--;
113 		new_free(&info->hold_tail->str);
114 		crap = info->hold_tail;
115 		info->hold_tail = info->hold_tail->prev;
116 		if (info->hold_tail == NULL)
117 			info->hold_head = info->hold_tail;
118 		else
119 			info->hold_tail->next = NULL;
120 		new_free(&crap);
121 		update_all_status();
122 	}
123 }
124 
125 /*
126  * hold_mode: sets the "hold mode".  Really.  If the update flag is true,
127  * this will also update the status line, if needed, to display the hold mode
128  * state.  If update is false, only the internal flag is set.
129  */
130 void
hold_mode(Window * window,HoldInfo * info,int flag,int update)131 hold_mode(Window *window, HoldInfo *info, int flag, int update)
132 {
133 	if (flag != ON && window_get_scrolled_lines(window))
134 		return;
135 	if (flag == TOGGLE)
136 	{
137 		if (info->held == OFF)
138 			info->held = ON;
139 		else
140 			info->held = OFF;
141 	}
142 	else
143 		info->held = flag;
144 	if (update)
145 	{
146 		if (info->held != info->last_held)
147 		{
148 			info->last_held = info->held;
149 					/* This shouldn't be done
150 					 * this way */
151 			update_window_status(window, 0);
152 			window_set_update(window, 0, UPDATE_STATUS);
153 			cursor_in_display();
154 			update_input(NO_UPDATE);
155 		}
156 	}
157 	else
158 		info->last_held = -1;
159 }
160 
161 /*
162  * hold_output: returns the state of the window->held, which is set in the
163  * hold_mode() routine.
164  */
165 int
hold_output(Window * window,HoldInfo * info)166 hold_output(Window *window, HoldInfo *info)
167 {
168 	return info->held == ON || window_get_scrolled_lines(window) != 0;
169 }
170 
171 /*
172  * hold_queue: returns the string value of the next element on the hold
173  * quere.  This does not change the hold queue
174  */
175 u_char	*
hold_queue(HoldInfo * info)176 hold_queue(HoldInfo *info)
177 {
178 	if (info->hold_tail)
179 		return info->hold_tail->str;
180 	else
181 		return NULL;
182 }
183 
184 int
hold_queue_logged(HoldInfo * info)185 hold_queue_logged(HoldInfo *info)
186 {
187 	if (info->hold_tail)
188 		return info->hold_tail->logged;
189 	else
190 		return 0;
191 }
192 
193 /* toggle_stop_screen: the BIND function TOGGLE_STOP_SCREEN */
194 void
toggle_stop_screen(u_int key,u_char * ptr)195 toggle_stop_screen(u_int key, u_char *ptr)
196 {
197 	window_hold_mode(NULL, TOGGLE, 1);
198 	update_all_windows();
199 }
200 
201 HoldInfo *
alloc_hold_info(void)202 alloc_hold_info(void)
203 {
204 	HoldInfo *new;
205 
206 	new = new_malloc(sizeof *new);
207 	new->held = OFF;
208 	new->last_held = OFF;
209 	new->hold_head = new->hold_tail = NULL;
210 	new->held_lines = 0;
211 
212 	return new;
213 }
214 
215 /*
216  * free_hold: This frees all the data and structures associated with the hold
217  * list for the given window
218  */
219 void
free_hold_info(HoldInfo ** hold_info)220 free_hold_info(HoldInfo **hold_info)
221 {
222 	Hold *tmp, *next;
223 
224 	for (tmp = (*hold_info)->hold_head; tmp; tmp = next)
225 	{
226 		next = tmp->next;
227 		new_free(&tmp->str);
228 		new_free(&tmp);
229 	}
230 	new_free(hold_info);
231 }
232 
233 int
held_lines(HoldInfo * info)234 held_lines(HoldInfo *info)
235 {
236 	return info->held_lines;
237 }
238 
239 int
hold_is_held(HoldInfo * info)240 hold_is_held(HoldInfo *info)
241 {
242 	return info->held;
243 }
244