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