Renamed package to ion1, and made it conflict with package 'ion'.
[ion1.git] / src / query.c
blobe0e0f897c40163c1690f9a66a90ebc4edbdfb1a2
1 /*
2 * ion/query.c
4 * Copyright (c) Tuomo Valkonen 1999-2001.
5 * See the included file LICENSE for details.
6 */
8 #include <limits.h>
9 #include <unistd.h>
10 #include <string.h>
12 #include <libtu/parser.h>
13 #include <libtu/tokenizer.h>
14 #include <libtu/output.h>
16 #include "common.h"
17 #include "global.h"
18 #include "frame.h"
19 #include "client.h"
20 #include "queryp.h"
21 #include "exec.h"
22 #include "focus.h"
23 #include "workspace.h"
24 #include "wedln.h"
25 #include "complete_file.h"
26 #include "function.h"
27 #include "wmessage.h"
30 /*{{{ Generic */
33 static void frame_set_input(WFrame *frame, WInput *input)
35 frame->current_input=input;
36 if(IS_ACTIVE_FRAME(frame))
37 set_focus((WThing*)input);
41 WEdln *do_query_edln(WFrame *frame, WEdlnHandler *handler,
42 const char *prompt, const char *dflt,
43 EdlnCompletionHandler *chnd)
45 WRectangle geom;
46 WEdln *wedln;
48 if(frame->current_input!=NULL)
49 return NULL;
51 frame_client_geom(frame, &geom);
53 wedln=create_wedln((WWindow*)frame, geom, handler, prompt, dflt);
55 if(wedln!=NULL){
56 wedln->edln.completion_handler=chnd;
57 frame_set_input(frame, (WInput*)wedln);
60 return wedln;
64 void fwarn(WFrame *frame, char *p)
66 WRectangle geom;
67 WEdln *wedln;
68 WMessage *wmsg;
69 char *p2;
71 if(p==NULL || frame->current_input!=NULL)
72 return;
74 frame_client_geom(frame, &geom);
76 p2=scat("-Error- ", p);
77 if(p2!=NULL){
78 wmsg=create_wmsg((WWindow*)frame, geom, p2);
79 free(p2);
80 }else{
81 wmsg=create_wmsg((WWindow*)frame, geom, p);
83 free(p);
85 if(wmsg!=NULL)
86 frame_set_input(frame, (WInput*)wmsg);
89 #define FWARN(ARGS) fwarn((WFrame*)thing, errmsg ARGS)
91 /*}}}*/
94 /*{{{ Files */
97 static char wdbuf[PATH_MAX+10]="/";
98 static int wdstatus=0;
100 static const char *my_getwd()
103 if(wdstatus==0){
104 if(getcwd(wdbuf, PATH_MAX)==NULL){
105 wdstatus=-1;
106 strcpy(wdbuf, "/");
107 }else{
108 wdstatus=1;
109 strcat(wdbuf, "/");
113 return wdbuf;
117 void handler_runfile(WThing *thing, char *str, char *userdata)
119 char *p;
121 if(*str=='\0')
122 return;
124 if(userdata!=NULL)
125 do_open_with(SCREEN_OF(thing), userdata, str);
127 p=strrchr(str, '/');
128 if(p==NULL){
129 wdstatus=0;
130 }else{
131 *(p+1)='\0';
132 strncpy(wdbuf, str, PATH_MAX);
137 void handler_runwith(WThing *thing, char *str, char *userdata)
139 WScreen *scr=SCREEN_OF(thing);
141 if(userdata==NULL)
142 return;
144 if(*str!='\0')
145 do_open_with(scr, userdata, str);
146 else
147 wm_exec(scr, userdata);
151 void handler_exec(WThing *thing, char *str, char *userdata)
153 WScreen *scr=SCREEN_OF(thing);
155 if(*str==':')
156 do_open_with(scr, "ion-runinxterm", str+1);
157 else
158 wm_exec(scr, str);
162 void query_exec(WFrame *frame)
164 do_query_edln(frame, handler_exec, "Run:", NULL, complete_file_with_path);
168 void query_runfile(WFrame *frame, char *prompt, char *cmd)
170 WEdln *wedln=do_query_edln(frame, handler_runfile,
171 prompt, my_getwd(), complete_file);
172 if(wedln!=NULL)
173 wedln->userdata=scopy(cmd);
177 void query_runwith(WFrame *frame, char *prompt, char *cmd)
179 WEdln *wedln=do_query_edln(frame, handler_runwith,
180 prompt, NULL, NULL);
181 if(wedln!=NULL)
182 wedln->userdata=scopy(cmd);
186 /*}}}*/
189 /*{{{ Navigation */
192 static bool attach_test(WFrame *dst, WClient *client, WFrame *thing)
194 if(!same_screen((WThing*)dst, (WThing*)client)){
195 /* complaint should go in 'thing' -frame */
196 FWARN(("Cannot attach: not on same screen."));
197 return FALSE;
199 return frame_attach_client(dst, client, TRUE);
203 void handler_attachclient(WThing *thing, char *str, char *userdata)
205 WClient *client=lookup_client(str);
207 if(client==NULL){
208 FWARN(("No client named '%s'", str));
209 return;
212 attach_test((WFrame*)thing, client, (WFrame*)thing);
216 void handler_gotoclient(WThing *thing, char *str, char *userdata)
218 WClient *client=lookup_client(str);
220 if(client==NULL){
221 FWARN(("No client named '%s'", str));
222 return;
225 goto_client(client);
229 void query_attachclient(WFrame *frame)
231 do_query_edln(frame, handler_attachclient,
232 "Attach client:", "", complete_client);
236 void query_gotoclient(WFrame *frame)
238 do_query_edln(frame, handler_gotoclient,
239 "Goto client:", "", complete_client);
243 bool empty_name(const char *p)
245 return (strspn(p, " \t")==strlen(p));
249 void handler_workspace(WThing *thing, char *name, char *userdata)
251 WScreen *scr=SCREEN_OF(thing);
252 WWorkspace *ws;
254 if(empty_name(name))
255 return;
257 ws=lookup_workspace(name);
259 if(ws==NULL){
260 ws=create_workspace(scr, name, TRUE);
261 if(ws==NULL){
262 FWARN(("Unable to create workspace."));
263 return;
267 switch_workspace(ws);
271 void query_workspace(WFrame *frame)
273 do_query_edln(frame, handler_workspace,
274 "Goto/create workspace:", "", complete_workspace);
278 void handler_workspace_with(WThing *thing, char *name, char *userdata)
280 WScreen *scr=SCREEN_OF(thing);
281 WWorkspace *ws;
282 WClient *client;
283 WFrame *frame;
285 if(empty_name(name))
286 return;
288 ws=lookup_workspace(name);
289 client=lookup_client(userdata);
291 if(ws!=NULL){
292 frame=(WFrame*)find_current(ws);
293 if(frame==NULL || !WTHING_IS(frame, WFrame)){
294 FWARN(("Workspace %s has no current frame", name));
295 return;
297 }else{
298 if(client==NULL){
299 FWARN(("Client disappeared"));
300 return;
303 ws=create_workspace(scr, name, TRUE);
304 if(ws==NULL){
305 FWARN(("Unable to create workspace."));
306 return;
309 frame=FIRST_THING(ws, WFrame);
311 assert(frame!=NULL);
314 if(attach_test((WFrame*)frame, client, (WFrame*)thing))
315 goto_client(client);
319 void query_workspace_with(WFrame *frame)
321 WEdln *wedln;
322 WClient *client=frame->current_client;
323 char *p;
325 if(client==NULL){
326 query_workspace(frame);
327 return;
330 p=client_full_label(client);
332 wedln=do_query_edln(frame, handler_workspace_with,
333 "Create workspace/attach:", p, complete_workspace);
334 if(wedln==NULL)
335 free(p);
336 else
337 wedln->userdata=p;
341 void handler_renameworkspace(WThing *thing, char *name, char *userdata)
343 WWorkspace *ws=SCREEN_OF(thing)->current_workspace;
345 if(empty_name(name))
346 return;
348 rename_workspace(ws, name);
352 void query_renameworkspace(WFrame *frame)
354 WWorkspace *ws = wglobal.current_screen->current_workspace;
356 do_query_edln(frame, handler_renameworkspace,
357 "Rename workspace to:", ws->name, complete_workspace);
361 /*}}}*/
364 /*{{{ Misc. */
366 /* ugly hack to know what we operate on in opt_default() */
367 static WThing *function_thing=NULL;
368 static WThing *function_frame=NULL;
369 static char *last_error_message=NULL;
372 static void function_warn_handler(const char *message)
374 if(last_error_message!=NULL)
375 free(last_error_message);
376 last_error_message=scopy(message);
380 /* We don't want to refer to destroyed things. */
381 void query_check_function_thing(WThing *t)
383 if(function_thing==t)
384 function_thing=t->t_parent;
385 if(function_frame==t)
386 function_frame=NULL;
390 void query_set_function_thing(WThing *t)
392 if(t!=NULL)
393 function_thing=t;
397 static bool opt_default(Tokenizer *tokz, int n, Token *toks)
399 WThing *thing=function_thing;
400 WFunction *func;
401 char *name=TOK_IDENT_VAL(&(toks[0]));
403 if(thing==NULL)
404 return FALSE;
406 func=lookup_func(name, FUNTAB_MAIN);
408 if(func==NULL){
409 warn("Unknown function '%s' or not in FUNTAB_MAIN.", name);
410 return FALSE;
413 if(!check_args(tokz, toks, n, func->argtypes)){
414 warn("Argument check for function '%s' failed. Prototype is '%s'.",
415 name, func->argtypes);
416 return FALSE;
419 func->callhnd(thing, func, n-1, &(toks[1]));
421 /*if(wglobal.focus_next!=NULL)
422 function_thing=wglobal.focus_next;*/
424 return TRUE;
428 static ConfOpt command_opts[]={
429 {"#default", NULL, opt_default, NULL},
430 {NULL, NULL, NULL, NULL}
434 bool command_sequence(WThing *thing, char *fn)
436 static bool command_sq=FALSE;
437 bool retval;
439 Tokenizer *tokz;
441 if(command_sq){
442 warn("Nested command sequence.");
443 return FALSE;
446 command_sq=TRUE;
447 function_thing=thing;
449 tokz=tokz_prepare_buffer(fn, -1);
450 tokz->flags|=TOKZ_DEFAULT_OPTION;
451 retval=parse_config_tokz(tokz, command_opts);
452 tokz_close(tokz);
454 function_thing=NULL;
455 command_sq=FALSE;
457 return retval;
461 void handler_function(WThing *thing, char *fn, char *userdata)
463 WarnHandler *old_warn_handler;
464 Tokenizer *tokz;
465 bool error;
467 function_frame=thing;
469 old_warn_handler=set_warn_handler(function_warn_handler);
470 error=!command_sequence(thing, fn);
471 set_warn_handler(old_warn_handler);
473 if(function_frame!=NULL){
474 if(last_error_message!=NULL){
475 FWARN(("%s", last_error_message));
476 }else if(error){
477 FWARN(("An unknown error occurred while trying to "
478 "parse your request"));
482 function_frame=NULL;
484 if(last_error_message!=NULL){
485 free(last_error_message);
486 last_error_message=NULL;
491 void handler_yesno(WThing *thing, char *yesno, char *fn)
493 if(strcasecmp(yesno, "y") && strcasecmp(yesno, "yes"))
494 return;
496 handler_function(thing, fn, NULL);
500 void query_yesno(WFrame *frame, char *prompt, char *fn)
502 WEdln *wedln=do_query_edln(frame, handler_yesno,
503 prompt, NULL, NULL);
504 if(wedln!=NULL)
505 wedln->userdata=scopy(fn);
509 void query_function(WFrame *frame)
511 do_query_edln(frame, handler_function,
512 "Function name:", NULL, complete_mainfunc);
516 /*}}}*/