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