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 #pragma implementation
19 #include "FormForks.h"
20 #include "ControlForks.h"
21 #include "forms/form_forks.h"
23 #include "helper_funcs.h"
24 #include "xforms_helpers.h"
26 #include "support/lstrings.h"
27 #include FORMS_H_LOCATION
33 typedef FormCB<ControlForks, FormDB<FD_forks> > base_class;
35 FormForks::FormForks()
36 : base_class(_("Child processes"))
40 void FormForks::build() {
41 dialog_.reset(build_forks(this));
43 // It appears that the browsers aren't initialised properly.
44 // This fudge fixes tings.
45 fl_add_browser_line(dialog_->browser_children, " ");
46 fl_add_browser_line(dialog_->browser_kill, " ");
47 fl_clear_browser(dialog_->browser_children);
48 fl_clear_browser(dialog_->browser_kill);
50 // Manage the ok, apply, restore and cancel/close buttons
51 bc().setOK(dialog_->button_ok);
52 bc().setApply(dialog_->button_apply);
53 bc().setCancel(dialog_->button_close);
56 // Set up the tooltip mechanism
57 string str = _("All currently running child processes forked by LyX.");
58 tooltips().init(dialog_->browser_children, str);
59 // Work-around xforms' bug; enable tooltips for browser widgets.
60 setPrehandler(dialog_->browser_children);
62 str = _("A list of all child processes to kill.");
63 tooltips().init(dialog_->browser_kill, str);
64 // Work-around xforms' bug; enable tooltips for browser widgets.
65 setPrehandler(dialog_->browser_kill);
67 str = _("Add all processes to the list of processes to kill.");
68 tooltips().init(dialog_->button_all, str);
70 str = _("Add the currently selected child process to the list of processes to kill.");
71 tooltips().init(dialog_->button_add, str);
73 str = _("Remove the currently selected item from the list of processes to kill.");
74 tooltips().init(dialog_->button_remove, str);
78 void FormForks::update()
83 string const current_pid_str =
84 getString(dialog_->browser_kill);
85 pid_t const current_pid = strToInt(current_pid_str);
87 vector<pid_t> pids = controller().getPIDs();
89 // No child processes.
91 if (fl_get_browser_maxline(dialog_->browser_kill) > 0)
92 fl_clear_browser(dialog_->browser_kill);
93 if (fl_get_browser_maxline(dialog_->browser_children) > 0)
94 fl_clear_browser(dialog_->browser_children);
96 setEnabled(dialog_->browser_children, false);
97 setEnabled(dialog_->browser_kill, false);
98 setEnabled(dialog_->button_all, false);
99 setEnabled(dialog_->button_add, false);
100 setEnabled(dialog_->button_remove, false);
105 // Remove any processes from the kill browser that aren't in the
106 // vector of existing PIDs.
107 for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_kill);
109 string const pid_str =
110 getString(dialog_->browser_kill, i);
111 pid_t const pid = strToInt(pid_str);
112 vector<pid_t>::const_iterator it =
113 find(pids.begin(), pids.end(), pid);
114 if (it == pids.end())
115 fl_delete_browser_line(dialog_->browser_kill, i);
118 // Build the children browser from scratch.
119 if (fl_get_browser_maxline(dialog_->browser_children) > 0)
120 fl_clear_browser(dialog_->browser_children);
122 for (vector<pid_t>::const_iterator it = pids.begin();
123 it != pids.end(); ++it) {
124 string const pid_str = tostr(*it);
125 string const command = controller().getCommand(*it);
126 string const line = pid_str + '\t' + command;
128 fl_add_browser_line(dialog_->browser_children, line.c_str());
130 if (*it == current_pid)
131 fl_select_browser_line(dialog_->browser_children, i);
135 setEnabled(dialog_->browser_children, true);
136 setEnabled(dialog_->button_all, true);
137 setEnabled(dialog_->button_add, true);
141 void FormForks::apply()
143 // Get the list of all processes to kill.
144 vector<string> const kill_vec =
145 getVector(dialog_->browser_kill);
147 if (kill_vec.empty())
150 // Remove these items from the vector of child processes.
151 for (int i = 1; i <= fl_get_browser_maxline(dialog_->browser_children);
153 string const selection =
154 getString(dialog_->browser_children, i);
156 split(selection, pid_str, '\t');
158 vector<string>::const_iterator it =
159 find(kill_vec.begin(), kill_vec.end(), pid_str);
161 if (it != kill_vec.end())
162 fl_delete_browser_line(dialog_->browser_children, i);
165 // Clear the kill browser and deactivate appropriately.
166 fl_clear_browser(dialog_->browser_kill);
167 setEnabled(dialog_->browser_kill, false);
168 setEnabled(dialog_->button_remove, false);
170 // Pass these pids to the controller for destruction.
171 for (vector<string>::const_iterator it = kill_vec.begin();
172 it != kill_vec.end(); ++it) {
173 pid_t const pid = strToInt(*it);
174 controller().kill(pid);
180 ButtonPolicy::SMInput FormForks::input(FL_OBJECT * ob, long)
182 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
184 if (ob == dialog_->browser_children) {
185 activate = input_browser_children();
187 } else if (ob == dialog_->browser_kill) {
188 activate = input_browser_kill();
190 } else if (ob == dialog_->button_all) {
191 activate = input_button_all();
193 } else if (ob == dialog_->button_add) {
194 activate = input_button_add();
196 } else if (ob == dialog_->button_remove) {
197 activate = input_button_remove();
203 ButtonPolicy::SMInput FormForks::input_browser_children()
205 // Selected an item in the browser containing a list of all child
208 // 1. Highlight this item in the browser of processes to kill
209 // if it is already there.
211 // 2. If it is there, enable the remove button so that it can
212 // be removed from this list, if so desired.
214 // 3. If it isn't there, activate the add button so that it can
215 // be added to this list if so desired.
217 string const selection =
218 getString(dialog_->browser_children);
220 split(selection, pid_str, '\t');
222 vector<string> const kill_vec =
223 getVector(dialog_->browser_kill);
225 vector<string>::const_iterator it =
226 find(kill_vec.begin(), kill_vec.end(), pid_str);
228 fl_deselect_browser(dialog_->browser_kill);
229 if (it != kill_vec.end()) {
230 int const n = int(it - kill_vec.begin());
231 fl_select_browser_line(dialog_->browser_kill, n+1);
232 fl_set_browser_topline(dialog_->browser_kill, n+1);
235 setEnabled(dialog_->button_remove, it != kill_vec.end());
236 setEnabled(dialog_->button_add, it == kill_vec.end());
238 return ButtonPolicy::SMI_NOOP;
246 FindPID(string const & pid) : pid_(pid) {}
247 bool operator()(string const & line)
253 split(line, pid_str, '\t');
254 return pid_str == pid_;
264 ButtonPolicy::SMInput FormForks::input_browser_kill()
266 // Selected an item in the browser containing a list of processes
269 // 1. Highlight this item in the browser of all child processes.
271 // 2. Enable the remove button so that it can removed from this list,
274 // 3. Disable the add button.
276 string const pid_str =
277 getString(dialog_->browser_kill);
279 // Find this string in the list of all child processes
280 vector<string> const child_vec =
281 getVector(dialog_->browser_children);
283 vector<string>::const_iterator it =
284 find_if(child_vec.begin(), child_vec.end(), FindPID(pid_str));
286 fl_deselect_browser(dialog_->browser_children);
287 if (it != child_vec.end()) {
288 int const n = int(it - child_vec.begin());
289 fl_select_browser_line(dialog_->browser_children, n+1);
290 fl_set_browser_topline(dialog_->browser_children, n+1);
293 setEnabled(dialog_->button_remove, true);
294 setEnabled(dialog_->button_add, false);
296 return ButtonPolicy::SMI_NOOP;
302 vector<string> const getPIDvector(FL_OBJECT * ob)
304 vector<string> vec = getVector(ob);
308 for (vector<string>::iterator it = vec.begin(); it != vec.end(); ++it) {
310 split(*it, pid_str, '\t');
320 ButtonPolicy::SMInput FormForks::input_button_all()
322 // Pressed the "All" button.
324 // 1. Check that the browser of processes to kill doesn't already
325 // contain the entire list.
327 // 2. If it doesn't, copy the PIDs of all child processes into the
328 // browser of processes to kill.
330 // 3. Deactivate the "children" browser and the "add" and "all" buttons
332 // 4. Activate the "kill" browser and the "remove" button"
334 ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
336 vector<string> const pid_vec = getPIDvector(dialog_->browser_children);
338 // to resolve a warning about comparison between signed and unsigned.
339 int const pid_vec_size = int(pid_vec.size());
341 if (fl_get_browser_maxline(dialog_->browser_kill) != pid_vec_size) {
342 activate = ButtonPolicy::SMI_VALID;
344 fl_clear_browser(dialog_->browser_kill);
345 for (vector<string>::const_iterator it = pid_vec.begin();
346 it != pid_vec.end(); ++it) {
347 fl_add_browser_line(dialog_->browser_kill, it->c_str());
350 if (fl_get_browser_maxline(dialog_->browser_kill) >= 1)
351 fl_set_browser_topline(dialog_->browser_kill, 1);
354 setEnabled(dialog_->browser_children, false);
355 setEnabled(dialog_->button_add, false);
356 setEnabled(dialog_->button_all, false);
357 setEnabled(dialog_->browser_kill, true);
358 setEnabled(dialog_->button_remove, true);
364 ButtonPolicy::SMInput FormForks::input_button_add()
366 // Pressed the "Add" button.
368 // 1. Copy the PID of the selected item in the browser of all child
369 // processes over into the browser of processes to kill.
371 // 2. Activate the "kill" browser and the "remove" button.
373 // 3. Deactivate the "add" button.
375 string const selection = getString(dialog_->browser_children);
377 split(selection, pid_str, '\t');
379 vector<string> const kill_vec =
380 getVector(dialog_->browser_kill);
382 vector<string>::const_iterator it =
383 find(kill_vec.begin(), kill_vec.end(), pid_str);
385 if (it == kill_vec.end()) {
386 fl_add_browser_line(dialog_->browser_kill, pid_str.c_str());
387 int const n = fl_get_browser_maxline(dialog_->browser_kill);
388 fl_select_browser_line(dialog_->browser_kill, n);
391 setEnabled(dialog_->browser_kill, true);
392 setEnabled(dialog_->button_remove, true);
393 setEnabled(dialog_->button_add, false);
395 return ButtonPolicy::SMI_VALID;
399 ButtonPolicy::SMInput FormForks::input_button_remove()
401 // Pressed the "Remove" button.
403 // 1. Remove the selected item in the browser of processes to kill.
405 // 2. Activate the "add" button and "all" buttons.
407 // 3. Deactivate the "remove" button.
409 int const sel = fl_get_browser(dialog_->browser_kill);
410 fl_delete_browser_line(dialog_->browser_kill, sel);
412 setEnabled(dialog_->button_add, true);
413 setEnabled(dialog_->button_all, true);
414 setEnabled(dialog_->button_remove, false);
416 return ButtonPolicy::SMI_VALID;