3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Angus Leeming
8 * Full author contact details are available in file CREDITS
15 #include "ButtonController.h"
16 #include "FormForks.h"
17 #include "ControlForks.h"
18 #include "forms/form_forks.h"
20 #include "helper_funcs.h"
21 #include "xforms_helpers.h"
23 #include "support/lstrings.h"
24 #include "lyx_forms.h"
25 #include "support/tostr.h"
31 typedef FormCB<ControlForks, FormDB<FD_forks> > base_class;
33 FormForks::FormForks()
34 : base_class(_("Child Processes"))
38 void FormForks::build() {
39 dialog_.reset(build_forks(this));
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);
48 // Manage the ok, apply, restore and cancel/close buttons
49 bcview().setOK(dialog_->button_ok);
50 bcview().setApply(dialog_->button_apply);
51 bcview().setCancel(dialog_->button_close);
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 #if FL_VERSION == 0 || (FL_REVISION == 0 && FL_FIXLEVEL == 0)
58 // Work-around xforms' bug; enable tooltips for browser widgets.
59 setPrehandler(dialog_->browser_children);
62 str = _("A list of all child processes to kill.");
63 tooltips().init(dialog_->browser_kill, 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_kill);
69 str = _("Add all processes to the list of processes to kill.");
70 tooltips().init(dialog_->button_all, str);
72 str = _("Add the currently selected child process to the list of processes to kill.");
73 tooltips().init(dialog_->button_add, str);
75 str = _("Remove the currently selected item from the list of processes to kill.");
76 tooltips().init(dialog_->button_remove, str);
80 void FormForks::update()
85 string const current_pid_str =
86 getString(dialog_->browser_kill);
87 pid_t const current_pid = strToInt(current_pid_str);
89 vector<pid_t> pids = controller().getPIDs();
91 // No child processes.
93 if (fl_get_browser_maxline(dialog_->browser_kill) > 0)
94 fl_clear_browser(dialog_->browser_kill);
95 if (fl_get_browser_maxline(dialog_->browser_children) > 0)
96 fl_clear_browser(dialog_->browser_children);
98 setEnabled(dialog_->browser_children, false);
99 setEnabled(dialog_->browser_kill, false);
100 setEnabled(dialog_->button_all, false);
101 setEnabled(dialog_->button_add, false);
102 setEnabled(dialog_->button_remove, false);
107 // Remove any processes from the kill browser that aren't in the
108 // vector of existing PIDs.
109 for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_kill);
111 string const pid_str =
112 getString(dialog_->browser_kill, i);
113 pid_t const pid = strToInt(pid_str);
114 vector<pid_t>::const_iterator it =
115 find(pids.begin(), pids.end(), pid);
116 if (it == pids.end())
117 fl_delete_browser_line(dialog_->browser_kill, i);
120 // Build the children browser from scratch.
121 if (fl_get_browser_maxline(dialog_->browser_children) > 0)
122 fl_clear_browser(dialog_->browser_children);
124 for (vector<pid_t>::const_iterator it = pids.begin();
125 it != pids.end(); ++it) {
126 string const pid_str = tostr(*it);
127 string const command = controller().getCommand(*it);
128 string const line = pid_str + '\t' + command;
130 fl_add_browser_line(dialog_->browser_children, line.c_str());
132 if (*it == current_pid)
133 fl_select_browser_line(dialog_->browser_children, i);
137 setEnabled(dialog_->browser_children, true);
138 setEnabled(dialog_->button_all, true);
139 setEnabled(dialog_->button_add, true);
143 void FormForks::apply()
145 // Get the list of all processes to kill.
146 vector<string> const kill_vec =
147 getVector(dialog_->browser_kill);
149 if (kill_vec.empty())
152 // Remove these items from the vector of child processes.
153 for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_children);
155 string const selection =
156 getString(dialog_->browser_children, i);
158 split(selection, pid_str, '\t');
160 vector<string>::const_iterator it =
161 find(kill_vec.begin(), kill_vec.end(), pid_str);
163 if (it != kill_vec.end())
164 fl_delete_browser_line(dialog_->browser_children, i);
167 // Clear the kill browser and deactivate appropriately.
168 fl_clear_browser(dialog_->browser_kill);
169 setEnabled(dialog_->browser_kill, false);
170 setEnabled(dialog_->button_remove, false);
172 // Pass these pids to the controller for destruction.
173 for (vector<string>::const_iterator it = kill_vec.begin();
174 it != kill_vec.end(); ++it) {
175 pid_t const pid = strToInt(*it);
176 controller().kill(pid);
182 ButtonPolicy::SMInput FormForks::input(FL_OBJECT * ob, long)
184 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
186 if (ob == dialog_->browser_children) {
187 activate = input_browser_children();
189 } else if (ob == dialog_->browser_kill) {
190 activate = input_browser_kill();
192 } else if (ob == dialog_->button_all) {
193 activate = input_button_all();
195 } else if (ob == dialog_->button_add) {
196 activate = input_button_add();
198 } else if (ob == dialog_->button_remove) {
199 activate = input_button_remove();
205 ButtonPolicy::SMInput FormForks::input_browser_children()
207 // Selected an item in the browser containing a list of all child
210 // 1. Highlight this item in the browser of processes to kill
211 // if it is already there.
213 // 2. If it is there, enable the remove button so that it can
214 // be removed from this list, if so desired.
216 // 3. If it isn't there, activate the add button so that it can
217 // be added to this list if so desired.
219 string const selection =
220 getString(dialog_->browser_children);
222 split(selection, pid_str, '\t');
224 vector<string> const kill_vec =
225 getVector(dialog_->browser_kill);
227 vector<string>::const_iterator it =
228 find(kill_vec.begin(), kill_vec.end(), pid_str);
230 fl_deselect_browser(dialog_->browser_kill);
231 if (it != kill_vec.end()) {
232 int const n = int(it - kill_vec.begin());
233 fl_select_browser_line(dialog_->browser_kill, n+1);
234 fl_set_browser_topline(dialog_->browser_kill, n+1);
237 setEnabled(dialog_->button_remove, it != kill_vec.end());
238 setEnabled(dialog_->button_add, it == kill_vec.end());
240 return ButtonPolicy::SMI_NOOP;
248 FindPID(string const & pid) : pid_(pid) {}
249 bool operator()(string const & line)
255 split(line, pid_str, '\t');
256 return pid_str == pid_;
266 ButtonPolicy::SMInput FormForks::input_browser_kill()
268 // Selected an item in the browser containing a list of processes
271 // 1. Highlight this item in the browser of all child processes.
273 // 2. Enable the remove button so that it can removed from this list,
276 // 3. Disable the add button.
278 string const pid_str =
279 getString(dialog_->browser_kill);
281 // Find this string in the list of all child processes
282 vector<string> const child_vec =
283 getVector(dialog_->browser_children);
285 vector<string>::const_iterator it =
286 find_if(child_vec.begin(), child_vec.end(), FindPID(pid_str));
288 fl_deselect_browser(dialog_->browser_children);
289 if (it != child_vec.end()) {
290 int const n = int(it - child_vec.begin());
291 fl_select_browser_line(dialog_->browser_children, n+1);
292 fl_set_browser_topline(dialog_->browser_children, n+1);
295 setEnabled(dialog_->button_remove, true);
296 setEnabled(dialog_->button_add, false);
298 return ButtonPolicy::SMI_NOOP;
304 vector<string> const getPIDvector(FL_OBJECT * ob)
306 vector<string> vec = getVector(ob);
310 for (vector<string>::iterator it = vec.begin(); it != vec.end(); ++it) {
312 split(*it, pid_str, '\t');
322 ButtonPolicy::SMInput FormForks::input_button_all()
324 // Pressed the "All" button.
326 // 1. Check that the browser of processes to kill doesn't already
327 // contain the entire list.
329 // 2. If it doesn't, copy the PIDs of all child processes into the
330 // browser of processes to kill.
332 // 3. Deactivate the "children" browser and the "add" and "all" buttons
334 // 4. Activate the "kill" browser and the "remove" button"
336 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
338 vector<string> const pid_vec = getPIDvector(dialog_->browser_children);
340 // to resolve a warning about comparison between signed and unsigned.
341 int const pid_vec_size = int(pid_vec.size());
343 if (fl_get_browser_maxline(dialog_->browser_kill) != pid_vec_size) {
344 activate = ButtonPolicy::SMI_VALID;
346 fl_clear_browser(dialog_->browser_kill);
347 for (vector<string>::const_iterator it = pid_vec.begin();
348 it != pid_vec.end(); ++it) {
349 fl_add_browser_line(dialog_->browser_kill, it->c_str());
352 if (fl_get_browser_maxline(dialog_->browser_kill) >= 1)
353 fl_set_browser_topline(dialog_->browser_kill, 1);
356 setEnabled(dialog_->browser_children, false);
357 setEnabled(dialog_->button_add, false);
358 setEnabled(dialog_->button_all, false);
359 setEnabled(dialog_->browser_kill, true);
360 setEnabled(dialog_->button_remove, true);
366 ButtonPolicy::SMInput FormForks::input_button_add()
368 // Pressed the "Add" button.
370 // 1. Copy the PID of the selected item in the browser of all child
371 // processes over into the browser of processes to kill.
373 // 2. Activate the "kill" browser and the "remove" button.
375 // 3. Deactivate the "add" button.
377 string const selection = getString(dialog_->browser_children);
379 split(selection, pid_str, '\t');
381 vector<string> const kill_vec =
382 getVector(dialog_->browser_kill);
384 vector<string>::const_iterator it =
385 find(kill_vec.begin(), kill_vec.end(), pid_str);
387 if (it == kill_vec.end()) {
388 fl_add_browser_line(dialog_->browser_kill, pid_str.c_str());
389 int const n = fl_get_browser_maxline(dialog_->browser_kill);
390 fl_select_browser_line(dialog_->browser_kill, n);
393 setEnabled(dialog_->browser_kill, true);
394 setEnabled(dialog_->button_remove, true);
395 setEnabled(dialog_->button_add, false);
397 return ButtonPolicy::SMI_VALID;
401 ButtonPolicy::SMInput FormForks::input_button_remove()
403 // Pressed the "Remove" button.
405 // 1. Remove the selected item in the browser of processes to kill.
407 // 2. Activate the "add" button and "all" buttons.
409 // 3. Deactivate the "remove" button.
411 int const sel = fl_get_browser(dialog_->browser_kill);
412 fl_delete_browser_line(dialog_->browser_kill, sel);
414 setEnabled(dialog_->button_add, true);
415 setEnabled(dialog_->button_all, true);
416 setEnabled(dialog_->button_remove, false);
418 return ButtonPolicy::SMI_VALID;