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