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