2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "libs/fvwmlib.h"
22 #include "libs/queue.h"
23 #include "libs/charmap.h"
24 #include "libs/wcontext.h"
25 #include "libs/Parse.h"
32 #include "functions.h"
42 int period
; /* in milliseconds */
45 static int last_schedule_id
= 0;
46 static int next_schedule_id
= -1;
47 static fqueue sq
= FQUEUE_INIT
;
49 static int cmp_times(Time t1
, Time t2
)
51 unsigned long ul1
= (unsigned long)t1
;
52 unsigned long ul2
= (unsigned long)t2
;
57 udiff
= *(signed long *)&diff
;
72 static int cmp_object_time(void *object1
, void *object2
, void *args
)
74 sq_object_type
*so1
= (sq_object_type
*)object1
;
75 sq_object_type
*so2
= (sq_object_type
*)object2
;
77 return cmp_times(so1
->time_to_execute
, so2
->time_to_execute
);
80 static int check_deschedule_obj_func(void *object
, void *args
)
82 sq_object_type
*obj
= object
;
84 return (obj
->id
== *(int *)args
);
87 static void destroy_obj_func(void *object
)
89 sq_object_type
*obj
= object
;
91 if (obj
->command
!= NULL
)
100 static void deschedule(int *pid
)
104 if (FQUEUE_IS_EMPTY(&sq
))
108 /* get the job group id to deschedule */
115 id
= last_schedule_id
;
117 /* deschedule matching jobs */
118 fqueue_remove_or_operate_all(
119 &sq
, check_deschedule_obj_func
, NULL
, destroy_obj_func
,
125 static void schedule(
126 Window window
, char *command
, Time time_to_execute
, int *pid
,
129 sq_object_type
*new_obj
;
131 if (command
== NULL
|| *command
== 0)
135 /* create the new object */
136 new_obj
= (sq_object_type
*)safemalloc(sizeof(sq_object_type
));
137 memset(new_obj
, 0, sizeof(sq_object_type
));
138 new_obj
->window
= window
;
139 new_obj
->command
= safestrdup(command
);
140 new_obj
->time_to_execute
= time_to_execute
;
141 new_obj
->period
= period
; /* 0 if this is not a periodic command */
142 /* set the job group id */
149 new_obj
->id
= next_schedule_id
;
151 if (next_schedule_id
>= 0)
154 next_schedule_id
= -1;
157 last_schedule_id
= new_obj
->id
;
158 /* insert into schedule queue */
159 fqueue_add_inside(&sq
, new_obj
, cmp_object_time
, NULL
);
164 static int check_execute_obj_func(void *object
, void *args
)
166 sq_object_type
*obj
= object
;
167 Time
*ptime
= (Time
*)args
;
169 return (cmp_times(*ptime
, obj
->time_to_execute
) >= 0);
172 static void execute_obj_func(void *object
, void *args
)
174 sq_object_type
*obj
= object
;
176 if (obj
->command
!= NULL
)
178 /* execute the command */
179 const exec_context_t
*exc
;
180 exec_context_changes_t ecc
;
181 exec_context_change_mask_t mask
= ECC_TYPE
| ECC_WCONTEXT
;
183 ecc
.type
= EXCT_SCHEDULE
;
184 ecc
.w
.wcontext
= C_ROOT
;
186 dpy
, obj
->window
, FvwmContext
,
187 (caddr_t
*)&ecc
.w
.fw
) != XCNOENT
)
189 ecc
.w
.wcontext
= C_WINDOW
;
192 exc
= exc_create_context(&ecc
, mask
);
193 execute_function(NULL
, exc
, obj
->command
, 0);
194 exc_destroy_context(exc
);
198 /* This is a periodic function, so reschedule it. */
199 sq_object_type
*new_obj
= (sq_object_type
*)safemalloc(sizeof(sq_object_type
));
200 memcpy(new_obj
, obj
, sizeof(sq_object_type
));
201 obj
->command
= NULL
; /* new_obj->command now points to cmd. */
202 new_obj
->time_to_execute
= fev_get_evtime() + new_obj
->period
;
203 /* insert into schedule queue */
204 fqueue_add_inside(&sq
, new_obj
, cmp_object_time
, NULL
);
211 /* executes all scheduled commands that are due for execution */
212 void squeue_execute(void)
216 if (FQUEUE_IS_EMPTY(&sq
))
220 current_time
= get_server_time();
221 fqueue_remove_or_operate_all(
222 &sq
, check_execute_obj_func
, execute_obj_func
,
223 destroy_obj_func
, ¤t_time
);
228 /* returns the time in milliseconds to wait before next queue command must be
229 * executed or -1 if none is queued */
230 int squeue_get_next_ms(void)
235 if (fqueue_get_first(&sq
, (void **)&obj
) == 0)
239 if (cmp_times(fev_get_evtime(), obj
->time_to_execute
) >= 0)
241 /* jobs pending to be executed immediately */
246 /* execute jobs later */
247 ms
= obj
->time_to_execute
- fev_get_evtime();
253 int squeue_get_next_id(void)
255 return next_schedule_id
;
258 int squeue_get_last_id(void)
260 return last_schedule_id
;
263 void CMD_Schedule(F_CMD_ARGS
)
275 FvwmWindow
* const fw
= exc
->w
.fw
;
276 Bool is_periodic
= False
;
278 token
= PeekToken(action
, &next
);
279 if (token
&& strcasecmp(token
, "periodic") == 0)
284 /* get the time to execute */
285 n
= GetIntegerArguments(action
, &action
, &ms
, 1);
288 fvwm_msg(ERR
, "CMD_Schedule",
289 "Requires time to schedule as argument");
297 /* eats up way too much cpu if schedule is used excessively */
298 current_time
= get_server_time();
300 /* with this version, scheduled commands may be executed earlier than
302 current_time
= fev_get_evtime();
304 time
= current_time
+ (Time
)ms
;
305 /* get the job group id to schedule */
306 n
= GetIntegerArgumentsAnyBase(action
, &taction
, &id
, 1);
316 /* get the window to operate on */
325 /* schedule the job */
326 schedule(xw
, action
, time
, pid
, (is_periodic
== True
? ms
: 0));
331 void CMD_Deschedule(F_CMD_ARGS
)
337 /* get the job group id to deschedule */
338 n
= GetIntegerArgumentsAnyBase(action
, &action
, &id
, 1);
341 /* none, use default */
348 /* deschedule matching jobs */