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
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 FORMS_H_LOCATION
30 typedef FormCB<ControlForks, FormDB<FD_forks> > base_class;
32 FormForks::FormForks()
33 : base_class(_("Child processes"))
37 void FormForks::build() {
38 dialog_.reset(build_forks(this));
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);
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);
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);
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);
64 str = _("Add all processes to the list of processes to kill.");
65 tooltips().init(dialog_->button_all, str);
67 str = _("Add the currently selected child process to the list of processes to kill.");
68 tooltips().init(dialog_->button_add, str);
70 str = _("Remove the currently selected item from the list of processes to kill.");
71 tooltips().init(dialog_->button_remove, str);
75 void FormForks::update()
80 string const current_pid_str =
81 getString(dialog_->browser_kill);
82 pid_t const current_pid = strToInt(current_pid_str);
84 vector<pid_t> pids = controller().getPIDs();
86 // No child processes.
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);
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);
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);
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);
115 // Build the children browser from scratch.
116 if (fl_get_browser_maxline(dialog_->browser_children) > 0)
117 fl_clear_browser(dialog_->browser_children);
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;
125 fl_add_browser_line(dialog_->browser_children, line.c_str());
127 if (*it == current_pid)
128 fl_select_browser_line(dialog_->browser_children, i);
132 setEnabled(dialog_->browser_children, true);
133 setEnabled(dialog_->button_all, true);
134 setEnabled(dialog_->button_add, true);
138 void FormForks::apply()
140 // Get the list of all processes to kill.
141 vector<string> const kill_vec =
142 getVector(dialog_->browser_kill);
144 if (kill_vec.empty())
147 // Remove these items from the vector of child processes.
148 for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_children);
150 string const selection =
151 getString(dialog_->browser_children, i);
153 split(selection, pid_str, '\t');
155 vector<string>::const_iterator it =
156 find(kill_vec.begin(), kill_vec.end(), pid_str);
158 if (it != kill_vec.end())
159 fl_delete_browser_line(dialog_->browser_children, i);
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);
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);
177 ButtonPolicy::SMInput FormForks::input(FL_OBJECT * ob, long)
179 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
181 if (ob == dialog_->browser_children) {
182 activate = input_browser_children();
184 } else if (ob == dialog_->browser_kill) {
185 activate = input_browser_kill();
187 } else if (ob == dialog_->button_all) {
188 activate = input_button_all();
190 } else if (ob == dialog_->button_add) {
191 activate = input_button_add();
193 } else if (ob == dialog_->button_remove) {
194 activate = input_button_remove();
200 ButtonPolicy::SMInput FormForks::input_browser_children()
202 // Selected an item in the browser containing a list of all child
205 // 1. Highlight this item in the browser of processes to kill
206 // if it is already there.
208 // 2. If it is there, enable the remove button so that it can
209 // be removed from this list, if so desired.
211 // 3. If it isn't there, activate the add button so that it can
212 // be added to this list if so desired.
214 string const selection =
215 getString(dialog_->browser_children);
217 split(selection, pid_str, '\t');
219 vector<string> const kill_vec =
220 getVector(dialog_->browser_kill);
222 vector<string>::const_iterator it =
223 find(kill_vec.begin(), kill_vec.end(), pid_str);
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);
232 setEnabled(dialog_->button_remove, it != kill_vec.end());
233 setEnabled(dialog_->button_add, it == kill_vec.end());
235 return ButtonPolicy::SMI_NOOP;
243 FindPID(string const & pid) : pid_(pid) {}
244 bool operator()(string const & line)
250 split(line, pid_str, '\t');
251 return pid_str == pid_;
261 ButtonPolicy::SMInput FormForks::input_browser_kill()
263 // Selected an item in the browser containing a list of processes
266 // 1. Highlight this item in the browser of all child processes.
268 // 2. Enable the remove button so that it can removed from this list,
271 // 3. Disable the add button.
273 string const pid_str =
274 getString(dialog_->browser_kill);
276 // Find this string in the list of all child processes
277 vector<string> const child_vec =
278 getVector(dialog_->browser_children);
280 vector<string>::const_iterator it =
281 find_if(child_vec.begin(), child_vec.end(), FindPID(pid_str));
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);
290 setEnabled(dialog_->button_remove, true);
291 setEnabled(dialog_->button_add, false);
293 return ButtonPolicy::SMI_NOOP;
299 vector<string> const getPIDvector(FL_OBJECT * ob)
301 vector<string> vec = getVector(ob);
305 for (vector<string>::iterator it = vec.begin(); it != vec.end(); ++it) {
307 split(*it, pid_str, '\t');
317 ButtonPolicy::SMInput FormForks::input_button_all()
319 // Pressed the "All" button.
321 // 1. Check that the browser of processes to kill doesn't already
322 // contain the entire list.
324 // 2. If it doesn't, copy the PIDs of all child processes into the
325 // browser of processes to kill.
327 // 3. Deactivate the "children" browser and the "add" and "all" buttons
329 // 4. Activate the "kill" browser and the "remove" button"
331 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
333 vector<string> const pid_vec = getPIDvector(dialog_->browser_children);
335 // to resolve a warning about comparison between signed and unsigned.
336 int const pid_vec_size = int(pid_vec.size());
338 if (fl_get_browser_maxline(dialog_->browser_kill) != pid_vec_size) {
339 activate = ButtonPolicy::SMI_VALID;
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());
347 if (fl_get_browser_maxline(dialog_->browser_kill) >= 1)
348 fl_set_browser_topline(dialog_->browser_kill, 1);
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);
361 ButtonPolicy::SMInput FormForks::input_button_add()
363 // Pressed the "Add" button.
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.
368 // 2. Activate the "kill" browser and the "remove" button.
370 // 3. Deactivate the "add" button.
372 string const selection = getString(dialog_->browser_children);
374 split(selection, pid_str, '\t');
376 vector<string> const kill_vec =
377 getVector(dialog_->browser_kill);
379 vector<string>::const_iterator it =
380 find(kill_vec.begin(), kill_vec.end(), pid_str);
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);
388 setEnabled(dialog_->browser_kill, true);
389 setEnabled(dialog_->button_remove, true);
390 setEnabled(dialog_->button_add, false);
392 return ButtonPolicy::SMI_VALID;
396 ButtonPolicy::SMInput FormForks::input_button_remove()
398 // Pressed the "Remove" button.
400 // 1. Remove the selected item in the browser of processes to kill.
402 // 2. Activate the "add" button and "all" buttons.
404 // 3. Deactivate the "remove" button.
406 int const sel = fl_get_browser(dialog_->browser_kill);
407 fl_delete_browser_line(dialog_->browser_kill, sel);
409 setEnabled(dialog_->button_add, true);
410 setEnabled(dialog_->button_all, true);
411 setEnabled(dialog_->button_remove, false);
413 return ButtonPolicy::SMI_VALID;