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.
14 #include "FormForks.h"
15 #include "ControlForks.h"
16 #include "forms/form_forks.h"
19 #include "xforms_helpers.h"
22 #include "controllers/ButtonController.h"
24 #include "support/lstrings.h"
25 #include "support/tostr.h"
27 #include "lyx_forms.h"
29 using namespace lyx::support;
36 typedef FormCB<ControlForks, FormDB<FD_forks> > base_class;
38 FormForks::FormForks()
39 : base_class(_("Child Processes"))
43 void FormForks::build() {
44 dialog_.reset(build_forks(this));
46 // It appears that the browsers aren't initialised properly.
47 // This fudge fixes tings.
48 fl_add_browser_line(dialog_->browser_children, " ");
49 fl_add_browser_line(dialog_->browser_kill, " ");
50 fl_clear_browser(dialog_->browser_children);
51 fl_clear_browser(dialog_->browser_kill);
53 // Manage the ok, apply, restore and cancel/close buttons
54 bcview().setOK(dialog_->button_ok);
55 bcview().setApply(dialog_->button_apply);
56 bcview().setCancel(dialog_->button_close);
59 // Set up the tooltip mechanism
60 string str = _("All currently running child processes forked by LyX.");
61 tooltips().init(dialog_->browser_children, str);
62 #if FL_VERSION == 0 || (FL_REVISION == 0 && FL_FIXLEVEL == 0)
63 // Work-around xforms' bug; enable tooltips for browser widgets.
64 setPrehandler(dialog_->browser_children);
67 str = _("A list of all child processes to kill.");
68 tooltips().init(dialog_->browser_kill, str);
69 #if FL_VERSION == 0 || (FL_REVISION == 0 && FL_FIXLEVEL == 0)
70 // Work-around xforms' bug; enable tooltips for browser widgets.
71 setPrehandler(dialog_->browser_kill);
74 str = _("Add all processes to the list of processes to kill.");
75 tooltips().init(dialog_->button_all, str);
77 str = _("Add the currently selected child process to the list of processes to kill.");
78 tooltips().init(dialog_->button_add, str);
80 str = _("Remove the currently selected item from the list of processes to kill.");
81 tooltips().init(dialog_->button_remove, str);
85 void FormForks::update()
90 string const current_pid_str =
91 getString(dialog_->browser_kill);
92 pid_t const current_pid = strToInt(current_pid_str);
94 vector<pid_t> pids = controller().getPIDs();
96 // No child processes.
98 if (fl_get_browser_maxline(dialog_->browser_kill) > 0)
99 fl_clear_browser(dialog_->browser_kill);
100 if (fl_get_browser_maxline(dialog_->browser_children) > 0)
101 fl_clear_browser(dialog_->browser_children);
103 setEnabled(dialog_->browser_children, false);
104 setEnabled(dialog_->browser_kill, false);
105 setEnabled(dialog_->button_all, false);
106 setEnabled(dialog_->button_add, false);
107 setEnabled(dialog_->button_remove, false);
112 // Remove any processes from the kill browser that aren't in the
113 // vector of existing PIDs.
114 for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_kill);
116 string const pid_str =
117 getString(dialog_->browser_kill, i);
118 pid_t const pid = strToInt(pid_str);
119 vector<pid_t>::const_iterator it =
120 find(pids.begin(), pids.end(), pid);
121 if (it == pids.end())
122 fl_delete_browser_line(dialog_->browser_kill, i);
125 // Build the children browser from scratch.
126 if (fl_get_browser_maxline(dialog_->browser_children) > 0)
127 fl_clear_browser(dialog_->browser_children);
129 for (vector<pid_t>::const_iterator it = pids.begin();
130 it != pids.end(); ++it) {
131 string const pid_str = tostr(*it);
132 string const command = controller().getCommand(*it);
133 string const line = pid_str + '\t' + command;
135 fl_add_browser_line(dialog_->browser_children, line.c_str());
137 if (*it == current_pid)
138 fl_select_browser_line(dialog_->browser_children, i);
142 setEnabled(dialog_->browser_children, true);
143 setEnabled(dialog_->button_all, true);
144 setEnabled(dialog_->button_add, true);
148 void FormForks::apply()
150 // Get the list of all processes to kill.
151 vector<string> const kill_vec =
152 getVector(dialog_->browser_kill);
154 if (kill_vec.empty())
157 // Remove these items from the vector of child processes.
158 for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_children);
160 string const selection =
161 getString(dialog_->browser_children, i);
163 split(selection, pid_str, '\t');
165 vector<string>::const_iterator it =
166 find(kill_vec.begin(), kill_vec.end(), pid_str);
168 if (it != kill_vec.end())
169 fl_delete_browser_line(dialog_->browser_children, i);
172 // Clear the kill browser and deactivate appropriately.
173 fl_clear_browser(dialog_->browser_kill);
174 setEnabled(dialog_->browser_kill, false);
175 setEnabled(dialog_->button_remove, false);
177 // Pass these pids to the controller for destruction.
178 for (vector<string>::const_iterator it = kill_vec.begin();
179 it != kill_vec.end(); ++it) {
180 pid_t const pid = strToInt(*it);
181 controller().kill(pid);
187 ButtonPolicy::SMInput FormForks::input(FL_OBJECT * ob, long)
189 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
191 if (ob == dialog_->browser_children) {
192 activate = input_browser_children();
194 } else if (ob == dialog_->browser_kill) {
195 activate = input_browser_kill();
197 } else if (ob == dialog_->button_all) {
198 activate = input_button_all();
200 } else if (ob == dialog_->button_add) {
201 activate = input_button_add();
203 } else if (ob == dialog_->button_remove) {
204 activate = input_button_remove();
210 ButtonPolicy::SMInput FormForks::input_browser_children()
212 // Selected an item in the browser containing a list of all child
215 // 1. Highlight this item in the browser of processes to kill
216 // if it is already there.
218 // 2. If it is there, enable the remove button so that it can
219 // be removed from this list, if so desired.
221 // 3. If it isn't there, activate the add button so that it can
222 // be added to this list if so desired.
224 string const selection =
225 getString(dialog_->browser_children);
227 split(selection, pid_str, '\t');
229 vector<string> const kill_vec =
230 getVector(dialog_->browser_kill);
232 vector<string>::const_iterator it =
233 find(kill_vec.begin(), kill_vec.end(), pid_str);
235 fl_deselect_browser(dialog_->browser_kill);
236 if (it != kill_vec.end()) {
237 int const n = int(it - kill_vec.begin());
238 fl_select_browser_line(dialog_->browser_kill, n+1);
239 fl_set_browser_topline(dialog_->browser_kill, n+1);
242 setEnabled(dialog_->button_remove, it != kill_vec.end());
243 setEnabled(dialog_->button_add, it == kill_vec.end());
245 return ButtonPolicy::SMI_NOOP;
253 FindPID(string const & pid) : pid_(pid) {}
254 bool operator()(string const & line)
260 split(line, pid_str, '\t');
261 return pid_str == pid_;
271 ButtonPolicy::SMInput FormForks::input_browser_kill()
273 // Selected an item in the browser containing a list of processes
276 // 1. Highlight this item in the browser of all child processes.
278 // 2. Enable the remove button so that it can removed from this list,
281 // 3. Disable the add button.
283 string const pid_str =
284 getString(dialog_->browser_kill);
286 // Find this string in the list of all child processes
287 vector<string> const child_vec =
288 getVector(dialog_->browser_children);
290 vector<string>::const_iterator it =
291 find_if(child_vec.begin(), child_vec.end(), FindPID(pid_str));
293 fl_deselect_browser(dialog_->browser_children);
294 if (it != child_vec.end()) {
295 int const n = int(it - child_vec.begin());
296 fl_select_browser_line(dialog_->browser_children, n+1);
297 fl_set_browser_topline(dialog_->browser_children, n+1);
300 setEnabled(dialog_->button_remove, true);
301 setEnabled(dialog_->button_add, false);
303 return ButtonPolicy::SMI_NOOP;
309 vector<string> const getPIDvector(FL_OBJECT * ob)
311 vector<string> vec = getVector(ob);
315 for (vector<string>::iterator it = vec.begin(); it != vec.end(); ++it) {
317 split(*it, pid_str, '\t');
327 ButtonPolicy::SMInput FormForks::input_button_all()
329 // Pressed the "All" button.
331 // 1. Check that the browser of processes to kill doesn't already
332 // contain the entire list.
334 // 2. If it doesn't, copy the PIDs of all child processes into the
335 // browser of processes to kill.
337 // 3. Deactivate the "children" browser and the "add" and "all" buttons
339 // 4. Activate the "kill" browser and the "remove" button"
341 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
343 vector<string> const pid_vec = getPIDvector(dialog_->browser_children);
345 // to resolve a warning about comparison between signed and unsigned.
346 int const pid_vec_size = int(pid_vec.size());
348 if (fl_get_browser_maxline(dialog_->browser_kill) != pid_vec_size) {
349 activate = ButtonPolicy::SMI_VALID;
351 fl_clear_browser(dialog_->browser_kill);
352 for (vector<string>::const_iterator it = pid_vec.begin();
353 it != pid_vec.end(); ++it) {
354 fl_add_browser_line(dialog_->browser_kill, it->c_str());
357 if (fl_get_browser_maxline(dialog_->browser_kill) >= 1)
358 fl_set_browser_topline(dialog_->browser_kill, 1);
361 setEnabled(dialog_->browser_children, false);
362 setEnabled(dialog_->button_add, false);
363 setEnabled(dialog_->button_all, false);
364 setEnabled(dialog_->browser_kill, true);
365 setEnabled(dialog_->button_remove, true);
371 ButtonPolicy::SMInput FormForks::input_button_add()
373 // Pressed the "Add" button.
375 // 1. Copy the PID of the selected item in the browser of all child
376 // processes over into the browser of processes to kill.
378 // 2. Activate the "kill" browser and the "remove" button.
380 // 3. Deactivate the "add" button.
382 string const selection = getString(dialog_->browser_children);
384 split(selection, pid_str, '\t');
386 vector<string> const kill_vec =
387 getVector(dialog_->browser_kill);
389 vector<string>::const_iterator it =
390 find(kill_vec.begin(), kill_vec.end(), pid_str);
392 if (it == kill_vec.end()) {
393 fl_add_browser_line(dialog_->browser_kill, pid_str.c_str());
394 int const n = fl_get_browser_maxline(dialog_->browser_kill);
395 fl_select_browser_line(dialog_->browser_kill, n);
398 setEnabled(dialog_->browser_kill, true);
399 setEnabled(dialog_->button_remove, true);
400 setEnabled(dialog_->button_add, false);
402 return ButtonPolicy::SMI_VALID;
406 ButtonPolicy::SMInput FormForks::input_button_remove()
408 // Pressed the "Remove" button.
410 // 1. Remove the selected item in the browser of processes to kill.
412 // 2. Activate the "add" button and "all" buttons.
414 // 3. Deactivate the "remove" button.
416 int const sel = fl_get_browser(dialog_->browser_kill);
417 fl_delete_browser_line(dialog_->browser_kill, sel);
419 setEnabled(dialog_->button_add, true);
420 setEnabled(dialog_->button_all, true);
421 setEnabled(dialog_->button_remove, false);
423 return ButtonPolicy::SMI_VALID;