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 lyx::support::split;
30 using lyx::support::strToInt;
38 typedef FormCB<ControlForks, FormDB<FD_forks> > base_class;
40 FormForks::FormForks()
41 : base_class(_("Child Processes"))
45 void FormForks::build() {
46 dialog_.reset(build_forks(this));
48 // It appears that the browsers aren't initialised properly.
49 // This fudge fixes tings.
50 fl_add_browser_line(dialog_->browser_children, " ");
51 fl_add_browser_line(dialog_->browser_kill, " ");
52 fl_clear_browser(dialog_->browser_children);
53 fl_clear_browser(dialog_->browser_kill);
55 // Manage the ok, apply, restore and cancel/close buttons
56 bcview().setOK(dialog_->button_ok);
57 bcview().setApply(dialog_->button_apply);
58 bcview().setCancel(dialog_->button_close);
61 // Set up the tooltip mechanism
62 string str = _("All currently running child processes forked by LyX.");
63 tooltips().init(dialog_->browser_children, 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_children);
69 str = _("A list of all child processes to kill.");
70 tooltips().init(dialog_->browser_kill, str);
71 #if FL_VERSION == 0 || (FL_REVISION == 0 && FL_FIXLEVEL == 0)
72 // Work-around xforms' bug; enable tooltips for browser widgets.
73 setPrehandler(dialog_->browser_kill);
76 str = _("Add all processes to the list of processes to kill.");
77 tooltips().init(dialog_->button_all, str);
79 str = _("Add the currently selected child process to the list of processes to kill.");
80 tooltips().init(dialog_->button_add, str);
82 str = _("Remove the currently selected item from the list of processes to kill.");
83 tooltips().init(dialog_->button_remove, str);
87 void FormForks::update()
92 string const current_pid_str =
93 getString(dialog_->browser_kill);
94 pid_t const current_pid = strToInt(current_pid_str);
96 vector<pid_t> pids = controller().getPIDs();
98 // No child processes.
100 if (fl_get_browser_maxline(dialog_->browser_kill) > 0)
101 fl_clear_browser(dialog_->browser_kill);
102 if (fl_get_browser_maxline(dialog_->browser_children) > 0)
103 fl_clear_browser(dialog_->browser_children);
105 setEnabled(dialog_->browser_children, false);
106 setEnabled(dialog_->browser_kill, false);
107 setEnabled(dialog_->button_all, false);
108 setEnabled(dialog_->button_add, false);
109 setEnabled(dialog_->button_remove, false);
114 // Remove any processes from the kill browser that aren't in the
115 // vector of existing PIDs.
116 for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_kill);
118 string const pid_str =
119 getString(dialog_->browser_kill, i);
120 pid_t const pid = strToInt(pid_str);
121 vector<pid_t>::const_iterator it =
122 find(pids.begin(), pids.end(), pid);
123 if (it == pids.end())
124 fl_delete_browser_line(dialog_->browser_kill, i);
127 // Build the children browser from scratch.
128 if (fl_get_browser_maxline(dialog_->browser_children) > 0)
129 fl_clear_browser(dialog_->browser_children);
131 for (vector<pid_t>::const_iterator it = pids.begin();
132 it != pids.end(); ++it) {
133 string const pid_str = tostr(*it);
134 string const command = controller().getCommand(*it);
135 string const line = pid_str + '\t' + command;
137 fl_add_browser_line(dialog_->browser_children, line.c_str());
139 if (*it == current_pid)
140 fl_select_browser_line(dialog_->browser_children, i);
144 setEnabled(dialog_->browser_children, true);
145 setEnabled(dialog_->button_all, true);
146 setEnabled(dialog_->button_add, true);
150 void FormForks::apply()
152 // Get the list of all processes to kill.
153 vector<string> const kill_vec =
154 getVector(dialog_->browser_kill);
156 if (kill_vec.empty())
159 // Remove these items from the vector of child processes.
160 for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_children);
162 string const selection =
163 getString(dialog_->browser_children, i);
165 split(selection, pid_str, '\t');
167 vector<string>::const_iterator it =
168 find(kill_vec.begin(), kill_vec.end(), pid_str);
170 if (it != kill_vec.end())
171 fl_delete_browser_line(dialog_->browser_children, i);
174 // Clear the kill browser and deactivate appropriately.
175 fl_clear_browser(dialog_->browser_kill);
176 setEnabled(dialog_->browser_kill, false);
177 setEnabled(dialog_->button_remove, false);
179 // Pass these pids to the controller for destruction.
180 for (vector<string>::const_iterator it = kill_vec.begin();
181 it != kill_vec.end(); ++it) {
182 pid_t const pid = strToInt(*it);
183 controller().kill(pid);
189 ButtonPolicy::SMInput FormForks::input(FL_OBJECT * ob, long)
191 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
193 if (ob == dialog_->browser_children) {
194 activate = input_browser_children();
196 } else if (ob == dialog_->browser_kill) {
197 activate = input_browser_kill();
199 } else if (ob == dialog_->button_all) {
200 activate = input_button_all();
202 } else if (ob == dialog_->button_add) {
203 activate = input_button_add();
205 } else if (ob == dialog_->button_remove) {
206 activate = input_button_remove();
212 ButtonPolicy::SMInput FormForks::input_browser_children()
214 // Selected an item in the browser containing a list of all child
217 // 1. Highlight this item in the browser of processes to kill
218 // if it is already there.
220 // 2. If it is there, enable the remove button so that it can
221 // be removed from this list, if so desired.
223 // 3. If it isn't there, activate the add button so that it can
224 // be added to this list if so desired.
226 string const selection =
227 getString(dialog_->browser_children);
229 split(selection, pid_str, '\t');
231 vector<string> const kill_vec =
232 getVector(dialog_->browser_kill);
234 vector<string>::const_iterator it =
235 find(kill_vec.begin(), kill_vec.end(), pid_str);
237 fl_deselect_browser(dialog_->browser_kill);
238 if (it != kill_vec.end()) {
239 int const n = int(it - kill_vec.begin());
240 fl_select_browser_line(dialog_->browser_kill, n+1);
241 fl_set_browser_topline(dialog_->browser_kill, n+1);
244 setEnabled(dialog_->button_remove, it != kill_vec.end());
245 setEnabled(dialog_->button_add, it == kill_vec.end());
247 return ButtonPolicy::SMI_NOOP;
255 FindPID(string const & pid) : pid_(pid) {}
256 bool operator()(string const & line)
262 split(line, pid_str, '\t');
263 return pid_str == pid_;
273 ButtonPolicy::SMInput FormForks::input_browser_kill()
275 // Selected an item in the browser containing a list of processes
278 // 1. Highlight this item in the browser of all child processes.
280 // 2. Enable the remove button so that it can removed from this list,
283 // 3. Disable the add button.
285 string const pid_str =
286 getString(dialog_->browser_kill);
288 // Find this string in the list of all child processes
289 vector<string> const child_vec =
290 getVector(dialog_->browser_children);
292 vector<string>::const_iterator it =
293 find_if(child_vec.begin(), child_vec.end(), FindPID(pid_str));
295 fl_deselect_browser(dialog_->browser_children);
296 if (it != child_vec.end()) {
297 int const n = int(it - child_vec.begin());
298 fl_select_browser_line(dialog_->browser_children, n+1);
299 fl_set_browser_topline(dialog_->browser_children, n+1);
302 setEnabled(dialog_->button_remove, true);
303 setEnabled(dialog_->button_add, false);
305 return ButtonPolicy::SMI_NOOP;
311 vector<string> const getPIDvector(FL_OBJECT * ob)
313 vector<string> vec = getVector(ob);
317 for (vector<string>::iterator it = vec.begin(); it != vec.end(); ++it) {
319 split(*it, pid_str, '\t');
329 ButtonPolicy::SMInput FormForks::input_button_all()
331 // Pressed the "All" button.
333 // 1. Check that the browser of processes to kill doesn't already
334 // contain the entire list.
336 // 2. If it doesn't, copy the PIDs of all child processes into the
337 // browser of processes to kill.
339 // 3. Deactivate the "children" browser and the "add" and "all" buttons
341 // 4. Activate the "kill" browser and the "remove" button"
343 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
345 vector<string> const pid_vec = getPIDvector(dialog_->browser_children);
347 // to resolve a warning about comparison between signed and unsigned.
348 int const pid_vec_size = int(pid_vec.size());
350 if (fl_get_browser_maxline(dialog_->browser_kill) != pid_vec_size) {
351 activate = ButtonPolicy::SMI_VALID;
353 fl_clear_browser(dialog_->browser_kill);
354 for (vector<string>::const_iterator it = pid_vec.begin();
355 it != pid_vec.end(); ++it) {
356 fl_add_browser_line(dialog_->browser_kill, it->c_str());
359 if (fl_get_browser_maxline(dialog_->browser_kill) >= 1)
360 fl_set_browser_topline(dialog_->browser_kill, 1);
363 setEnabled(dialog_->browser_children, false);
364 setEnabled(dialog_->button_add, false);
365 setEnabled(dialog_->button_all, false);
366 setEnabled(dialog_->browser_kill, true);
367 setEnabled(dialog_->button_remove, true);
373 ButtonPolicy::SMInput FormForks::input_button_add()
375 // Pressed the "Add" button.
377 // 1. Copy the PID of the selected item in the browser of all child
378 // processes over into the browser of processes to kill.
380 // 2. Activate the "kill" browser and the "remove" button.
382 // 3. Deactivate the "add" button.
384 string const selection = getString(dialog_->browser_children);
386 split(selection, pid_str, '\t');
388 vector<string> const kill_vec =
389 getVector(dialog_->browser_kill);
391 vector<string>::const_iterator it =
392 find(kill_vec.begin(), kill_vec.end(), pid_str);
394 if (it == kill_vec.end()) {
395 fl_add_browser_line(dialog_->browser_kill, pid_str.c_str());
396 int const n = fl_get_browser_maxline(dialog_->browser_kill);
397 fl_select_browser_line(dialog_->browser_kill, n);
400 setEnabled(dialog_->browser_kill, true);
401 setEnabled(dialog_->button_remove, true);
402 setEnabled(dialog_->button_add, false);
404 return ButtonPolicy::SMI_VALID;
408 ButtonPolicy::SMInput FormForks::input_button_remove()
410 // Pressed the "Remove" button.
412 // 1. Remove the selected item in the browser of processes to kill.
414 // 2. Activate the "add" button and "all" buttons.
416 // 3. Deactivate the "remove" button.
418 int const sel = fl_get_browser(dialog_->browser_kill);
419 fl_delete_browser_line(dialog_->browser_kill, sel);
421 setEnabled(dialog_->button_add, true);
422 setEnabled(dialog_->button_all, true);
423 setEnabled(dialog_->button_remove, false);
425 return ButtonPolicy::SMI_VALID;