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