]> git.lyx.org Git - features.git/blob - src/frontends/xforms/FormForks.C
non-templated tostr in separate files
[features.git] / src / frontends / xforms / FormForks.C
1 /**
2  * \file FormForks.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming
7  *
8  * Full author contact details are available in file CREDITS
9  * \date 2001-10-22
10  */
11
12 #include <config.h>
13
14 #include "xformsBC.h"
15 #include "ButtonController.h"
16 #include "FormForks.h"
17 #include "ControlForks.h"
18 #include "forms/form_forks.h"
19 #include "Tooltips.h"
20 #include "helper_funcs.h"
21 #include "xforms_helpers.h"
22 #include "gettext.h"
23 #include "support/lstrings.h"
24 #include "support/tostr.h"
25 #include FORMS_H_LOCATION
26
27 using std::vector;
28 using std::find;
29 using std::find_if;
30
31 typedef FormCB<ControlForks, FormDB<FD_forks> > base_class;
32
33 FormForks::FormForks()
34         : base_class(_("Child Processes"))
35 {}
36
37
38 void FormForks::build() {
39         dialog_.reset(build_forks(this));
40
41         // It appears that the browsers aren't initialised properly.
42         // This fudge fixes tings.
43         fl_add_browser_line(dialog_->browser_children, " ");
44         fl_add_browser_line(dialog_->browser_kill, " ");
45         fl_clear_browser(dialog_->browser_children);
46         fl_clear_browser(dialog_->browser_kill);
47
48         // Manage the ok, apply, restore and cancel/close buttons
49         bcview().setOK(dialog_->button_ok);
50         bcview().setApply(dialog_->button_apply);
51         bcview().setCancel(dialog_->button_close);
52         bc().valid(false);
53
54         // Set up the tooltip mechanism
55         string str = _("All currently running child processes forked by LyX.");
56         tooltips().init(dialog_->browser_children, str);
57 #if FL_VERSION == 0 || (FL_REVISION == 0 && FL_FIXLEVEL == 0)
58         // Work-around xforms' bug; enable tooltips for browser widgets.
59         setPrehandler(dialog_->browser_children);
60 #endif
61
62         str = _("A list of all child processes to kill.");
63         tooltips().init(dialog_->browser_kill, str);
64 #if FL_VERSION == 0 || (FL_REVISION == 0 && FL_FIXLEVEL == 0)
65         // Work-around xforms' bug; enable tooltips for browser widgets.
66         setPrehandler(dialog_->browser_kill);
67 #endif
68
69         str = _("Add all processes to the list of processes to kill.");
70         tooltips().init(dialog_->button_all, str);
71
72         str = _("Add the currently selected child process to the list of processes to kill.");
73         tooltips().init(dialog_->button_add, str);
74
75         str = _("Remove the currently selected item from the list of processes to kill.");
76         tooltips().init(dialog_->button_remove, str);
77 }
78
79
80 void FormForks::update()
81 {
82         if (!form())
83                 return;
84
85         string const current_pid_str =
86                 getString(dialog_->browser_kill);
87         pid_t const current_pid = strToInt(current_pid_str);
88
89         vector<pid_t> pids = controller().getPIDs();
90
91         // No child processes.
92         if (pids.empty()) {
93                 if (fl_get_browser_maxline(dialog_->browser_kill) > 0)
94                         fl_clear_browser(dialog_->browser_kill);
95                 if (fl_get_browser_maxline(dialog_->browser_children) > 0)
96                         fl_clear_browser(dialog_->browser_children);
97
98                 setEnabled(dialog_->browser_children, false);
99                 setEnabled(dialog_->browser_kill,     false);
100                 setEnabled(dialog_->button_all,       false);
101                 setEnabled(dialog_->button_add,       false);
102                 setEnabled(dialog_->button_remove,    false);
103
104                 return;
105         }
106
107         // Remove any processes from the kill browser that aren't in the
108         // vector of existing PIDs.
109         for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_kill);
110              ++i) {
111                 string const pid_str =
112                         getString(dialog_->browser_kill, i);
113                 pid_t const pid = strToInt(pid_str);
114                 vector<pid_t>::const_iterator it =
115                         find(pids.begin(), pids.end(), pid);
116                 if (it == pids.end())
117                         fl_delete_browser_line(dialog_->browser_kill, i);
118         }
119
120         // Build the children browser from scratch.
121         if (fl_get_browser_maxline(dialog_->browser_children) > 0)
122                 fl_clear_browser(dialog_->browser_children);
123         int i = 1;
124         for (vector<pid_t>::const_iterator it = pids.begin();
125              it != pids.end(); ++it) {
126                 string const pid_str = tostr(*it);
127                 string const command = controller().getCommand(*it);
128                 string const line = pid_str + '\t' + command;
129
130                 fl_add_browser_line(dialog_->browser_children, line.c_str());
131
132                 if (*it == current_pid)
133                         fl_select_browser_line(dialog_->browser_children, i);
134                 ++i;
135         }
136
137         setEnabled(dialog_->browser_children, true);
138         setEnabled(dialog_->button_all,       true);
139         setEnabled(dialog_->button_add,       true);
140 }
141
142
143 void FormForks::apply()
144 {
145         // Get the list of all processes to kill.
146         vector<string> const kill_vec =
147                 getVector(dialog_->browser_kill);
148
149         if (kill_vec.empty())
150                 return;
151
152         // Remove these items from the vector of child processes.
153         for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_children);
154              ++i) {
155                 string const selection =
156                         getString(dialog_->browser_children, i);
157                 string pid_str;
158                 split(selection, pid_str, '\t');
159
160                 vector<string>::const_iterator it =
161                         find(kill_vec.begin(), kill_vec.end(), pid_str);
162
163                 if (it != kill_vec.end())
164                         fl_delete_browser_line(dialog_->browser_children, i);
165         }
166
167         // Clear the kill browser and deactivate appropriately.
168         fl_clear_browser(dialog_->browser_kill);
169         setEnabled(dialog_->browser_kill,  false);
170         setEnabled(dialog_->button_remove, false);
171
172         // Pass these pids to the controller for destruction.
173         for (vector<string>::const_iterator it = kill_vec.begin();
174              it != kill_vec.end(); ++it) {
175                 pid_t const pid = strToInt(*it);
176                 controller().kill(pid);
177         }
178
179 }
180
181
182 ButtonPolicy::SMInput FormForks::input(FL_OBJECT * ob, long)
183 {
184         ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
185
186         if (ob == dialog_->browser_children) {
187                 activate = input_browser_children();
188
189         } else if (ob == dialog_->browser_kill) {
190                 activate = input_browser_kill();
191
192         } else if (ob == dialog_->button_all) {
193                 activate = input_button_all();
194
195         } else if (ob == dialog_->button_add) {
196                 activate = input_button_add();
197
198         } else if (ob == dialog_->button_remove) {
199                 activate = input_button_remove();
200         }
201
202         return activate;
203 }
204
205 ButtonPolicy::SMInput FormForks::input_browser_children()
206 {
207         // Selected an item in the browser containing a list of all child
208         // processes.
209
210         // 1. Highlight this item in the browser of processes to kill
211         //    if it is already there.
212
213         // 2. If it is there, enable the remove button so that it can
214         //    be removed from this list, if so desired.
215
216         // 3. If it isn't there, activate the add button so that it can
217         //    be added to this list if so desired.
218
219         string const selection =
220                 getString(dialog_->browser_children);
221         string pid_str;
222         split(selection, pid_str, '\t');
223
224         vector<string> const kill_vec =
225                 getVector(dialog_->browser_kill);
226
227         vector<string>::const_iterator it =
228                 find(kill_vec.begin(), kill_vec.end(), pid_str);
229
230         fl_deselect_browser(dialog_->browser_kill);
231         if (it != kill_vec.end()) {
232                 int const n = int(it - kill_vec.begin());
233                 fl_select_browser_line(dialog_->browser_kill, n+1);
234                 fl_set_browser_topline(dialog_->browser_kill, n+1);
235         }
236
237         setEnabled(dialog_->button_remove, it != kill_vec.end());
238         setEnabled(dialog_->button_add,    it == kill_vec.end());
239
240         return ButtonPolicy::SMI_NOOP;
241 }
242
243
244 namespace {
245
246 class FindPID {
247 public:
248         FindPID(string const & pid) : pid_(pid) {}
249         bool operator()(string const & line)
250         {
251                 if (line.empty())
252                         return false;
253
254                 string pid_str;
255                 split(line, pid_str, '\t');
256                 return pid_str == pid_;
257         }
258
259 private:
260         string pid_;
261 };
262
263 } // namespace anon
264
265
266 ButtonPolicy::SMInput FormForks::input_browser_kill()
267 {
268         // Selected an item in the browser containing a list of processes
269         // to kill.
270
271         // 1. Highlight this item in the browser of all child processes.
272
273         // 2. Enable the remove button so that it can removed from this list,
274         //    if so desired.
275
276         // 3. Disable the add button.
277
278         string const pid_str =
279                 getString(dialog_->browser_kill);
280
281         // Find this string in the list of all child processes
282         vector<string> const child_vec =
283                 getVector(dialog_->browser_children);
284
285         vector<string>::const_iterator it =
286                 find_if(child_vec.begin(), child_vec.end(), FindPID(pid_str));
287
288         fl_deselect_browser(dialog_->browser_children);
289         if (it != child_vec.end()) {
290                 int const n = int(it - child_vec.begin());
291                 fl_select_browser_line(dialog_->browser_children, n+1);
292                 fl_set_browser_topline(dialog_->browser_children, n+1);
293         }
294
295         setEnabled(dialog_->button_remove, true);
296         setEnabled(dialog_->button_add,    false);
297
298         return ButtonPolicy::SMI_NOOP;
299 }
300
301
302 namespace {
303
304 vector<string> const getPIDvector(FL_OBJECT * ob)
305 {
306         vector<string> vec = getVector(ob);
307         if (vec.empty())
308                 return vec;
309
310         for (vector<string>::iterator it = vec.begin(); it != vec.end(); ++it) {
311                 string pid_str;
312                 split(*it, pid_str, '\t');
313                 *it = pid_str;
314         }
315
316         return vec;
317 }
318
319 } // namespace anon
320
321
322 ButtonPolicy::SMInput FormForks::input_button_all()
323 {
324         // Pressed the "All" button.
325
326         // 1. Check that the browser of processes to kill doesn't already
327         //    contain the entire list.
328
329         // 2. If it doesn't, copy the PIDs of all child processes into the
330         //    browser of processes to kill.
331
332         // 3. Deactivate the "children" browser and the "add" and "all" buttons
333
334         // 4. Activate the "kill" browser and the "remove" button"
335
336         ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
337
338         vector<string> const pid_vec = getPIDvector(dialog_->browser_children);
339
340         // to resolve a warning about comparison between signed and unsigned.
341         int const pid_vec_size = int(pid_vec.size());
342
343         if (fl_get_browser_maxline(dialog_->browser_kill) != pid_vec_size) {
344                 activate = ButtonPolicy::SMI_VALID;
345
346                 fl_clear_browser(dialog_->browser_kill);
347                 for (vector<string>::const_iterator it = pid_vec.begin();
348                      it != pid_vec.end(); ++it) {
349                         fl_add_browser_line(dialog_->browser_kill, it->c_str());
350                 }
351
352                 if (fl_get_browser_maxline(dialog_->browser_kill) >= 1)
353                         fl_set_browser_topline(dialog_->browser_kill, 1);
354         }
355
356         setEnabled(dialog_->browser_children, false);
357         setEnabled(dialog_->button_add,       false);
358         setEnabled(dialog_->button_all,       false);
359         setEnabled(dialog_->browser_kill,     true);
360         setEnabled(dialog_->button_remove,    true);
361
362         return activate;
363 }
364
365
366 ButtonPolicy::SMInput FormForks::input_button_add()
367 {
368         // Pressed the "Add" button.
369
370         // 1. Copy the PID of the selected item in the browser of all child
371         //    processes over into the browser of processes to kill.
372
373         // 2. Activate the "kill" browser and the "remove" button.
374
375         // 3. Deactivate the "add" button.
376
377         string const selection = getString(dialog_->browser_children);
378         string pid_str;
379         split(selection, pid_str, '\t');
380
381         vector<string> const kill_vec =
382                 getVector(dialog_->browser_kill);
383
384         vector<string>::const_iterator it =
385                 find(kill_vec.begin(), kill_vec.end(), pid_str);
386
387         if (it == kill_vec.end()) {
388                 fl_add_browser_line(dialog_->browser_kill, pid_str.c_str());
389                 int const n = fl_get_browser_maxline(dialog_->browser_kill);
390                 fl_select_browser_line(dialog_->browser_kill, n);
391         }
392
393         setEnabled(dialog_->browser_kill,  true);
394         setEnabled(dialog_->button_remove, true);
395         setEnabled(dialog_->button_add,    false);
396
397         return ButtonPolicy::SMI_VALID;
398 }
399
400
401 ButtonPolicy::SMInput FormForks::input_button_remove()
402 {
403         // Pressed the "Remove" button.
404
405         // 1. Remove the selected item in the browser of processes to kill.
406
407         // 2. Activate the "add" button and "all" buttons.
408
409         // 3. Deactivate the "remove" button.
410
411         int const sel = fl_get_browser(dialog_->browser_kill);
412         fl_delete_browser_line(dialog_->browser_kill, sel);
413
414         setEnabled(dialog_->button_add,    true);
415         setEnabled(dialog_->button_all,    true);
416         setEnabled(dialog_->button_remove, false);
417
418         return ButtonPolicy::SMI_VALID;
419 }