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