Add:gui_internal:Further work on flexible menus
[navit-package] / navit / command.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdarg.h>
4 #include <stdlib.h>
5 #include <glib.h>
6 #include "item.h"
7 #include "xmlconfig.h"
8 #include "main.h"
9 #include "navit.h"
10 #include "vehicle.h"
11 #include "speech.h"
12 #include "gui.h"
13 #include "debug.h"
14 #include "callback.h"
15 #include "command.h"
16 #include "event.h"
17
18 /*
19 gui.fullscreen()
20 gui.menu()
21 gui.get_data() 
22 zoom_in() 
23 zoom_out()
24 speech.active=!speech.active
25 osd_configuration=1
26 Not yet:
27 osd[type=="xxx"].active=0;osd[type=="yyy"].active=0
28 */
29
30
31 struct result {
32         struct attr attr;
33         double val;
34         char *var;
35         int varlen;
36         char *attrn;
37         int attrnlen;
38         int allocated;
39 };
40
41 struct context {
42         struct attr *attr;
43         int error;
44         char *expr;
45         struct result res;
46 };
47
48 struct command_saved_cb {
49         struct callback *cb;
50         struct attr attr;
51 };
52
53 struct command_saved {
54         struct context ctx;
55         struct result res;
56         char *command;                          // The command string itself
57         struct event_idle *idle_ev;             // Event to update this command
58         struct callback *idle_cb;
59         struct callback *register_cb;                   // Callback to register all the callbacks
60         struct event_idle *register_ev;         // Idle event to register all the callbacks
61         struct attr navit;
62         int num_cbs;
63         struct command_saved_cb *cbs;           // List of callbacks for this saved command
64         struct callback *cb; // Callback that should be called when we re-evaluate
65         int error;
66 };
67
68 enum error {
69         no_error=0,missing_closing_brace, missing_colon, wrong_type, illegal_number_format, illegal_character, missing_closing_bracket, invalid_type, not_ready
70 };
71
72 static void eval_comma(struct context *ctx, struct result *res);
73 static struct attr ** eval_list(struct context *ctx);
74
75 static void
76 result_free(struct result *res)
77 {
78 }
79
80 static int command_register_callbacks(struct command_saved *cs);
81
82 static char *
83 get_op(struct context *ctx, int test, ...)
84 {
85         char *op,*ret=NULL;
86         va_list ap;
87
88         while (g_ascii_isspace(*ctx->expr)) {
89                 ctx->expr++;
90         }
91
92         va_start(ap, test);
93         while ((op = va_arg(ap, char *))) {
94                 if (!strncmp(ctx->expr, op, strlen(op))) {
95                         ret=ctx->expr;
96                         if (! test)
97                                 ctx->expr+=strlen(op);
98                         break;
99                 }
100         }
101         va_end(ap);
102         return ret;
103 }
104
105 /*static int
106 is_int(struct result *res)
107 {
108         return 1;
109 }*/
110
111 static int
112 is_double(struct result *res)
113 {
114         return 0;
115 }
116
117 static void
118 dump(struct result *res)
119 {
120         char object[res->varlen+1];
121         char attribute[res->attrnlen+1];
122         if (res->var)
123                 strncpy(object, res->var, res->varlen);
124         object[res->varlen]='\0';
125         if (res->attrn)
126                 strncpy(attribute, res->attrn, res->attrnlen);
127         attribute[res->attrnlen]='\0';
128         dbg(0,"type:%s\n", attr_to_name(res->attr.type));
129         dbg(0,"attribute '%s' from '%s'\n", attribute, object);
130 }
131
132 static enum attr_type
133 command_attr_type(struct result *res)
134 {
135         char attrn[res->attrnlen+1];
136
137         strncpy(attrn, res->attrn, res->attrnlen);
138         attrn[res->attrnlen]='\0';
139         return attr_from_name(attrn);
140 }
141
142 static int
143 command_object_get_attr(struct context *ctx, struct attr *object, enum attr_type attr_type, struct attr *ret)
144 {
145         struct object_func *func=object_func_lookup(object->type);
146         if (!func || !func->get_attr)
147                 return 0;
148         return func->get_attr(object->u.data, attr_type, ret, NULL);
149 }
150
151 static void
152 command_get_attr(struct context *ctx, struct result *res)
153 {
154         int result;
155         enum attr_type attr_type=command_attr_type(res);
156         result=command_object_get_attr(ctx, &res->attr, attr_type, &res->attr);
157         if (result) {
158                 res->var=res->attrn;
159                 res->varlen=res->attrnlen;
160         } else {
161                 res->attr.type=attr_none;
162                 res->var=NULL;
163                 res->varlen=0;
164         }
165         res->attrn=NULL;
166         res->attrnlen=0;
167         dump(res);
168 }
169
170 static void
171 command_set_attr(struct context *ctx, struct result *res, struct result *newres)
172 {
173         int result=0;
174         enum attr_type attr_type=command_attr_type(res);
175         struct object_func *func=object_func_lookup(res->attr.type);
176         if (!func || !func->set_attr)
177                 return;
178         newres->attr.type=attr_type;
179         result=func->set_attr(res->attr.u.data, &newres->attr);
180         *res=*newres;
181 }
182
183 static void
184 resolve_object(struct context *ctx, struct result *res)
185 {
186         if (res->attr.type == attr_none && res->varlen) {
187                 res->attr=*ctx->attr;
188                 res->attrn=res->var;
189                 res->attrnlen=res->varlen;
190                 res->var=NULL;
191                 res->varlen=0;
192         }
193 }
194
195 static void
196 resolve(struct context *ctx, struct result *res, struct attr *parent) //FIXME What is that parent for?
197 {
198         resolve_object(ctx, res);
199         if (res->attrn)
200                 command_get_attr(ctx, res);
201 }
202
203 static double
204 get_double(struct context *ctx, struct result *res)
205 {
206         resolve(ctx, res, NULL);
207         return res->val;
208 }
209
210
211
212 static int
213 get_int(struct context *ctx, struct result *res)
214 {
215         resolve(ctx, res, NULL);
216         if (res->attr.type == attr_none)
217                 return 0;
218         if (res->attr.type >= attr_type_int_begin && res->attr.type <= attr_type_int_end) {
219                 return res->attr.u.num;
220         }
221         if (res->attr.type >= attr_type_double_begin && res->attr.type <= attr_type_double_end) {
222                 return (int) (*res->attr.u.numd);
223         }
224         ctx->error=wrong_type;
225         return 0;
226 }
227
228
229 static char *
230 get_string(struct context *ctx, struct result *res)
231 {
232         resolve(ctx, res, NULL);
233         return attr_to_text(&res->attr, NULL, 0);
234 }
235
236 static void
237 set_double(struct context *ctx, struct result *res, double val)
238 {
239         result_free(res);
240         res->val=val;
241 }
242
243 static void
244 set_int(struct context *ctx, struct result *res, int val)
245 {
246         result_free(res);
247         res->attr.type=attr_type_int_begin;
248         res->attr.u.num=val;
249 }
250
251
252 static void
253 eval_value(struct context *ctx, struct result *res) {
254         char *op;
255         int len,dots=0;
256         op=ctx->expr;
257         res->varlen=0;
258         res->var=NULL;
259         res->attrnlen=0;
260         res->attrn=NULL;
261
262         while (g_ascii_isspace(*op)) {
263                 op++;
264         }
265
266         if (op[0] >= 'a' && op[0] <= 'z') {
267                 res->attr.type=attr_none;
268                 res->var=op;
269                 while ((op[0] >= 'a' && op[0] <= 'z') || op[0] == '_') {
270                         res->varlen++;
271                         op++;
272                 }
273                 ctx->expr=op;
274                 return;
275         }
276         if ((op[0] >= '0' && op[0] <= '9') ||
277             (op[0] == '.' && op[1] >= '0' && op[1] <= '9') ||
278             (op[0] == '-' && op[1] >= '0' && op[1] <= '9') ||
279             (op[0] == '-' && op[1] == '.' && op[2] >= '0' && op[2] <= '9')) {
280                 while ((op[0] >= '0' && op[0] <= '9') || op[0] == '.' || (res->varlen == 0 && op[0] == '-')) {
281                         if (op[0] == '.')
282                                 dots++;
283                         if (dots > 1) {
284                                 ctx->error=illegal_number_format;
285                                 return;
286                         }
287                         res->varlen++;
288                         op++;
289                 }
290                 if (dots) {
291                         res->val = strtod(ctx->expr, NULL);
292                         res->attr.type=attr_type_double_begin;
293                         res->attr.u.numd=&res->val;
294                 } else {
295                         res->attr.type=attr_type_int_begin;
296                         res->attr.u.num=atoi(ctx->expr);
297                 }
298                 ctx->expr=op;
299                 return;
300         }
301         if (op[0] == '"') {
302                 do {
303                         op++;
304                 } while (op[0] != '"');
305                 res->attr.type=attr_type_string_begin;
306                 len=op-ctx->expr-1;
307                 res->attr.u.str=g_malloc(len+1);
308                 strncpy(res->attr.u.str, ctx->expr+1, len);
309                 res->attr.u.str[len]='\0';
310                 op++;
311                 ctx->expr=op;
312                 return;
313         }
314         ctx->error=illegal_character;
315 }
316
317 static int
318 get_next_object(struct context *ctx, struct result *res) {
319         
320         while (*ctx->expr) {
321                 res->varlen = 0;
322                 ctx->error = 0;
323
324                 eval_value(ctx,res);
325                 
326                 if ((res->attr.type == attr_none) && (res->varlen > 0)) {
327                         if (ctx->expr[0] != '.') {
328                                 return 1;               // 1 means "this is the final object name"
329                         } else {
330                                 return 2;               // 2 means "there are more object names following" (e.g. we just hit 'vehicle' in 'vehicle.position_speed'
331                         }
332                 }
333
334                 if (ctx->error) {
335                         // Probably hit an operator
336                         ctx->expr++;
337                 }
338         }
339
340         return 0;
341 }
342
343 static void
344 eval_brace(struct context *ctx, struct result *res)
345 {
346         if (get_op(ctx,0,"(",NULL)) {
347                 eval_comma(ctx, res);
348                 if (ctx->error) return;
349                 if (!get_op(ctx,0,")",NULL)) 
350                         ctx->error=missing_closing_brace;
351                 return;
352         }
353         eval_value(ctx, res);
354 }
355
356 static void
357 command_call_function(struct context *ctx, struct result *res)
358 {
359         struct attr cbl,**list=NULL;
360         char function[res->attrnlen+1];
361         if (res->attrn)
362                 strncpy(function, res->attrn, res->attrnlen);
363         function[res->attrnlen]='\0';
364         dbg(0,"function=%s\n", function);
365         if (ctx->expr[0] != ')') {
366                 list=eval_list(ctx);    
367                 if (ctx->error) return;
368         }
369         if (!get_op(ctx,0,")",NULL)) {
370                 ctx->error=missing_closing_brace;
371                 return;
372         }
373         if (command_object_get_attr(ctx, &res->attr, attr_callback_list, &cbl)) {
374                 int valid;
375                 dbg(0,"function call %s from %s\n",function, attr_to_name(res->attr.type));
376                 callback_list_call_attr_4(cbl.u.callback_list, attr_command, function, list, NULL, &valid);
377         }
378         res->var=NULL;
379         res->varlen=0;
380         res->attrn=NULL;
381         res->attrnlen=0;
382         res->attr.type=attr_none;
383 }
384
385 static void
386 eval_postfix(struct context *ctx, struct result *res)
387 {
388         struct result tmp;
389         char *op;
390
391         eval_brace(ctx, res);
392         if (ctx->error) return;
393         for (;;) {
394                 if (!(op=get_op(ctx,0,"[","(",".",NULL)))
395                         return;
396                 if (op[0] == '.') {
397                         eval_brace(ctx, &tmp);
398                         if (ctx->error) return;
399                         resolve(ctx, res,NULL);
400                         if (ctx->error) return;
401                         res->attrn=tmp.var;
402                         res->attrnlen=tmp.varlen;
403                         dump(res);
404                 } else if (op[0] == '[') {
405                         if (!get_op(ctx,0,"]",NULL)) {
406                                 ctx->error=missing_closing_bracket;
407                                 return;
408                         }
409                 } else if (op[0] == '(') {
410                         dbg(0,"function call\n");
411                         resolve_object(ctx, res);
412                         command_call_function(ctx, res);
413                 }
414         }
415 }
416
417 static void
418 eval_unary(struct context *ctx, struct result *res) 
419 {
420         char *op;
421         op=get_op(ctx,0,"~","!",NULL);
422         if (op) {
423                 eval_unary(ctx, res);
424                 if (ctx->error) return;
425                 if (op[0] == '~')
426                         set_int(ctx, res, ~get_int(ctx, res));
427                 else
428                         set_int(ctx, res, !get_int(ctx, res));
429         } else
430                 eval_postfix(ctx, res);
431 }
432
433 static void
434 eval_multiplicative(struct context *ctx, struct result *res) 
435 {
436         struct result tmp;
437         char *op;
438
439         eval_unary(ctx, res);
440         if (ctx->error) return;
441         for (;;) {
442                 if (!(op=get_op(ctx,0,"*","/","%",NULL))) return;
443                 eval_unary(ctx, &tmp);
444                 if (ctx->error) return;
445                 if (is_double(res) || is_double(&tmp)) {
446                         if (op[0] == '*')
447                                 set_double(ctx, res, get_double(ctx, res) * get_double(ctx, &tmp));
448                         else if (op[0] == '/')
449                                 set_double(ctx, res, get_double(ctx, res) / get_double(ctx, &tmp));
450                         else {
451                                 ctx->error=invalid_type;
452                                 return;
453                         }
454                 } else {
455                         if (op[0] == '*')
456                                 set_int(ctx, res, get_int(ctx, res) * get_int(ctx, &tmp));
457                         else if (op[0] == '/')
458                                 set_int(ctx, res, get_int(ctx, res) / get_int(ctx, &tmp));
459                         else
460                                 set_int(ctx, res, get_int(ctx, res) % get_int(ctx, &tmp));
461                 }
462                 if (ctx->error) return;
463         }
464 }
465
466 static void
467 eval_additive(struct context *ctx, struct result *res) 
468 {
469         struct result tmp;
470         char *op;
471
472         eval_multiplicative(ctx, res);
473         if (ctx->error) return;
474         for (;;) {
475                 if (!(op=get_op(ctx,0,"-","+",NULL))) return;
476                 eval_multiplicative(ctx, &tmp);
477                 if (ctx->error) return;
478                 if (is_double(res) || is_double(&tmp)) {
479                         if (op[0] == '+')
480                                 set_double(ctx, res, get_double(ctx, res) + get_double(ctx, &tmp));
481                         else
482                                 set_double(ctx, res, get_double(ctx, res) - get_double(ctx, &tmp));
483                 } else {
484                         if (op[0] == '+')
485                                 set_int(ctx, res, get_int(ctx, res) + get_int(ctx, &tmp));
486                         else
487                                 set_int(ctx, res, get_int(ctx, res) - get_int(ctx, &tmp));
488                 }
489                 if (ctx->error) return;
490         }
491 }
492
493 static void
494 eval_equality(struct context *ctx, struct result *res) 
495 {
496         struct result tmp;
497         char *op;
498
499         eval_additive(ctx, res);
500         if (ctx->error) return;
501         for (;;) {
502                 if (!(op=get_op(ctx,0,"==","!=","<=",">=","<",">",NULL))) return;
503                 eval_additive(ctx, &tmp);
504                 if (ctx->error) return;
505
506                 switch (op[0]) {
507                 case '=':
508                         set_int(ctx, res, (get_int(ctx, res) == get_int(ctx, &tmp)));
509                         break;
510                 case '!':
511                         set_int(ctx, res, (get_int(ctx, res) != get_int(ctx, &tmp)));
512                         break;
513                 case '<':
514                         if (op[1] == '=') {
515                                 set_int(ctx, res, (get_int(ctx, res) <= get_int(ctx, &tmp)));
516                         } else {
517                                 set_int(ctx, res, (get_int(ctx, res) < get_int(ctx, &tmp)));
518                         }
519                         break;
520                 case '>':
521                         if (op[1] == '=') {
522                                 set_int(ctx, res, (get_int(ctx, res) >= get_int(ctx, &tmp)));
523                         } else {
524                                 set_int(ctx, res, (get_int(ctx, res) > get_int(ctx, &tmp)));
525                         }
526                         break;
527                 default:
528                         break;
529                 }
530                 result_free(&tmp);
531         }
532 }
533
534
535 static void
536 eval_bitwise_and(struct context *ctx, struct result *res) 
537 {
538         struct result tmp;
539
540         eval_equality(ctx, res);
541         if (ctx->error) return;
542         for (;;) {
543                 if (get_op(ctx,1,"&&",NULL)) return;
544                 if (!get_op(ctx,0,"&",NULL)) return;
545                 eval_equality(ctx, &tmp);
546                 if (ctx->error) return;
547                 set_int(ctx, res, get_int(ctx, res) & get_int(ctx, &tmp));
548                 if (ctx->error) return;
549         }
550 }
551
552 static void
553 eval_bitwise_xor(struct context *ctx, struct result *res) 
554 {
555         struct result tmp;
556
557         eval_bitwise_and(ctx, res);
558         if (ctx->error) return;
559         for (;;) {
560                 if (!get_op(ctx,0,"^",NULL)) return;
561                 eval_bitwise_and(ctx, &tmp);
562                 if (ctx->error) return;
563                 set_int(ctx, res, get_int(ctx, res) ^ get_int(ctx, &tmp));
564                 if (ctx->error) return;
565         }
566 }
567
568 static void
569 eval_bitwise_or(struct context *ctx, struct result *res) 
570 {
571         struct result tmp;
572
573         eval_bitwise_xor(ctx, res);
574         if (ctx->error) return;
575         for (;;) {
576                 if (get_op(ctx,1,"||",NULL)) return;
577                 if (!get_op(ctx,0,"|",NULL)) return;
578                 eval_bitwise_xor(ctx, &tmp);
579                 if (ctx->error) return;
580                 set_int(ctx, res, get_int(ctx, res) | get_int(ctx, &tmp));
581                 if (ctx->error) return;
582         }
583 }
584
585 static void
586 eval_logical_and(struct context *ctx, struct result *res) 
587 {
588         struct result tmp;
589
590         eval_bitwise_or(ctx, res);
591         if (ctx->error) return;
592         for (;;) {
593                 if (!get_op(ctx,0,"&&",NULL)) return;
594                 eval_bitwise_or(ctx, &tmp);
595                 if (ctx->error) return;
596                 set_int(ctx, res, get_int(ctx, res) && get_int(ctx, &tmp));
597                 if (ctx->error) return;
598         }
599 }
600
601 static void
602 eval_logical_or(struct context *ctx, struct result *res) 
603 {
604         struct result tmp;
605
606         eval_logical_and(ctx, res);
607         if (ctx->error) return;
608         for (;;) {
609                 if (!get_op(ctx,0,"||",NULL)) return;
610                 eval_logical_and(ctx, &tmp);
611                 if (ctx->error) return;
612                 set_int(ctx, res, get_int(ctx, res) || get_int(ctx, &tmp));
613                 if (ctx->error) return;
614         }
615 }
616
617 static void
618 eval_conditional(struct context *ctx, struct result *res)
619 {
620         struct result tmp;
621         int cond;
622
623         eval_logical_or(ctx, res);
624         if (ctx->error) return;
625         if (!get_op(ctx,0,"?",NULL)) return;
626         cond=!!get_int(ctx, res);
627         if (ctx->error) return;
628         eval_logical_or(ctx, &tmp);
629         if (ctx->error) return;
630         if (cond)
631                 *res=tmp;
632         if (!get_op(ctx,0,":",NULL)) {
633                 ctx->error=missing_colon;
634                 return;
635         }
636         eval_logical_or(ctx, &tmp);
637         if (ctx->error) return;
638         if (!cond)
639                 *res=tmp;
640 }
641
642 /* = *= /= %= += -= >>= <<= &= ^= |= */
643
644 static void
645 eval_assignment(struct context *ctx, struct result *res)
646 {
647         struct result tmp;
648         eval_conditional(ctx, res);
649         if (ctx->error) return;
650         if (!get_op(ctx,0,"=",NULL)) return;
651         eval_conditional(ctx, &tmp);
652         if (ctx->error) return;
653         resolve_object(ctx, res);
654         command_set_attr(ctx, res, &tmp);
655 }
656
657 /* , */
658 static void
659 eval_comma(struct context *ctx, struct result *res)
660 {
661         struct result tmp;
662
663         eval_assignment(ctx, res);
664         if (ctx->error) return;
665         for (;;) {
666                 if (!get_op(ctx,0,",",NULL)) return;
667                 eval_assignment(ctx, &tmp);
668                 if (ctx->error) return;
669                 *res=tmp;
670         }
671 }
672
673 static struct attr **
674 eval_list(struct context *ctx)
675 {
676         struct result tmp;
677
678         struct attr **ret=NULL;
679         for (;;) {
680                 eval_assignment(ctx, &tmp);
681                 if (ctx->error) {
682                         attr_list_free(ret);
683                         return NULL;
684                 }
685                 resolve(ctx, &tmp, NULL);
686                 ret=attr_generic_add_attr(ret, &tmp.attr);
687                 if (!get_op(ctx,0,",",NULL)) return ret;
688         }
689 }
690
691 #if 0
692
693 void command(struct attr *attr, char *expr)
694 {
695         struct result res;
696         struct context ctx;
697         memset(&res, 0, sizeof(res));
698         memset(&ctx, 0, sizeof(ctx));
699         ctx.attr=attr;
700         ctx.error=0;
701         ctx.expr=expr;
702         printf("command='%s'\n", expr);
703         eval_comma(&ctx,&res);
704         printf("err=%d %s\n", ctx.error, ctx.expr);
705         dump(&res);
706         printf("***\n");
707         resolve(&ctx, &res, NULL);
708         dump(&res);
709         printf("%s\n", get_string(&ctx, &res));
710 }
711 #endif
712
713 static void
714 command_evaluate_to(struct attr *attr, char *expr, struct context *ctx, struct result *res)
715 {
716         memset(res, 0, sizeof(*res));
717         memset(ctx, 0, sizeof(*ctx));
718         ctx->attr=attr;
719         ctx->expr=expr;
720         eval_comma(ctx,res);
721 }
722
723 void
724 command_evaluate_to_void(struct attr *attr, char *expr, int **error)
725 {
726         struct result res;
727         struct context ctx;
728         command_evaluate_to(attr, expr, &ctx, &res);
729         if (!ctx.error)
730                 resolve(&ctx, &res, NULL);
731         if (error)
732                 *error=&ctx.error;
733
734 }
735
736 char *
737 command_evaluate_to_string(struct attr *attr, char *expr, int **error)
738 {
739         struct result res;
740         struct context ctx;
741         char *ret=NULL;
742
743         command_evaluate_to(attr, expr, &ctx, &res);
744         if (!ctx.error)
745                 ret=get_string(&ctx, &res);
746         if (error)
747                 *error=&ctx.error;
748         if (ctx.error)
749                 return NULL;
750         else
751                 return ret;
752 }
753
754 int
755 command_evaluate_to_int(struct attr *attr, char *expr, int **error)
756 {
757         struct result res;
758         struct context ctx;
759         int ret=0;
760
761         command_evaluate_to(attr, expr, &ctx, &res);
762         if (!ctx.error)
763                 ret=get_int(&ctx, &res);
764         if (error)
765                 *error=&ctx.error;
766         if (ctx.error)
767                 return 0;
768         else
769                 return ret;
770 }
771
772 void
773 command_evaluate(struct attr *attr, char *expr)
774 {
775         struct result res;
776         struct context ctx;
777         memset(&res, 0, sizeof(res));
778         memset(&ctx, 0, sizeof(ctx));
779         ctx.attr=attr;
780         ctx.error=0;
781         ctx.expr=expr;
782         for (;;) {
783                 eval_comma(&ctx,&res);
784                 if (ctx.error)
785                         return;
786                 resolve(&ctx, &res, NULL);
787                 if (ctx.error)
788                         return;
789                 if (!get_op(&ctx,0,";",NULL)) return;
790         }
791 }
792
793 #if 0
794 void
795 command_interpreter(struct attr *attr)
796 {
797                 char buffer[4096];
798                 int size;
799                 for (;;) {
800                 size=read(0, buffer, 4095);
801                 buffer[size]='\0';
802                 if (size) {
803                         buffer[size-1]='\0';
804                 }
805                 command(attr, buffer);
806                 }
807 }
808 #endif
809
810 static void
811 command_table_call(struct command_table *table, int count, void *data, char *command, struct attr **in, struct attr ***out, int *valid)
812 {
813         int i;
814         for (i = 0 ; i < count ; i++) {
815                 if (!strcmp(command,table->command)) {
816                         if (valid)
817                                 *valid=1;
818                         table->func(data, command, in, out);
819                 }
820                 table++;
821         }
822 }
823
824 void
825 command_add_table_attr(struct command_table *table, int count, void *data, struct attr *attr)
826 {
827         attr->type=attr_callback;
828         attr->u.callback=callback_new_attr_3(callback_cast(command_table_call),attr_command, table, count, data);
829 }
830
831 void
832 command_add_table(struct callback_list *cbl, struct command_table *table, int count, void *data)
833 {
834         struct attr attr;
835         command_add_table_attr(table, count, data, &attr);
836         callback_list_add(cbl, attr.u.callback);
837 }
838
839 void
840 command_saved_set_cb (struct command_saved *cs, struct callback *cb)
841 {
842         cs->cb = cb;
843 }
844
845 int
846 command_saved_get_int (struct command_saved *cs)
847 {
848         return get_int(&cs->ctx, &cs->res);
849 }
850
851 int 
852 command_saved_error (struct command_saved *cs)
853 {
854         return cs->error;
855 }
856
857 static void
858 command_saved_evaluate_idle (struct command_saved *cs) 
859 {
860         // Only run once at a time
861         if (cs->idle_ev) {
862                 event_remove_idle(cs->idle_ev);
863                 cs->idle_ev = NULL;
864         }
865
866         command_evaluate_to(&cs->navit, cs->command, &cs->ctx, &cs->res);
867
868         if (!cs->ctx.error) {
869                 cs->error = 0;
870
871                 if (cs->cb) {
872                         callback_call_1(cs->cb, cs);
873                 }
874         } else {
875                 cs->error = cs->ctx.error;
876         }
877 }
878
879 static void
880 command_saved_evaluate(struct command_saved *cs)
881 {       
882         if (cs->idle_ev) {
883                 // We're already scheduled for reevaluation
884                 return;
885         }
886
887         if (!cs->idle_cb) {
888                 cs->idle_cb = callback_new_1(callback_cast(command_saved_evaluate_idle), cs);
889         }
890
891         cs->idle_ev = event_add_idle(100, cs->idle_cb);
892 }
893
894 static void
895 command_saved_callbacks_changed(struct command_saved *cs)
896 {
897         // For now, we delete each and every callback and then re-create them
898         int i;
899         struct object_func *func;
900         struct attr attr;
901
902         if (cs->register_ev) {
903                 event_remove_idle(cs->register_ev);
904                 cs->register_ev = NULL;
905         }
906
907         attr.type = attr_callback;
908
909         for (i = 0; i < cs->num_cbs; i++) {
910                 func = object_func_lookup(cs->cbs[i].attr.type);
911                 
912                 if (!func->remove_attr) {
913                         dbg(0, "Could not remove command-evaluation callback because remove_attr is missing for type %i!\n", cs->cbs[i].attr.type);
914                         continue;
915                 }
916
917                 attr.u.callback = cs->cbs[i].cb;
918
919                 func->remove_attr(cs->cbs[i].attr.u.data, &attr);
920                 callback_destroy(cs->cbs[i].cb);
921         }
922
923         g_free(cs->cbs);
924         cs->cbs = NULL;
925         cs->num_cbs = 0;
926
927         // Now, re-create all the callbacks
928         command_register_callbacks(cs);
929 }
930
931 static int
932 command_register_callbacks(struct command_saved *cs)
933 {
934         struct attr prev,cb_attr,attr;
935         int status;
936         struct object_func *func;
937         struct callback *cb;
938         
939         attr = cs->navit;
940         cs->ctx.expr = cs->command;
941         cs->ctx.attr = &attr;
942         prev = cs->navit;       
943
944         while ((status = get_next_object(&cs->ctx, &cs->res)) != 0) {
945                 resolve(&cs->ctx, &cs->res, NULL);
946
947                 if (cs->ctx.error || (cs->res.attr.type == attr_none)) {
948                         // We could not resolve an object, perhaps because it has not been created
949                         return 0;
950                 }
951
952                 if (prev.type != attr_none) {
953                         func = object_func_lookup(prev.type);
954
955                         if (func->add_attr) {
956                                 if (status == 2) { // This is not the final attribute name
957                                         cb = callback_new_attr_1(callback_cast(command_saved_callbacks_changed), cs->res.attr.type, (void*)cs);
958                                         attr = cs->res.attr;
959                                 } else if (status == 1) { // This is the final attribute name
960                                         cb = callback_new_attr_1(callback_cast(command_saved_evaluate), cs->res.attr.type, (void*)cs);
961                                         cs->ctx.attr = &cs->navit;
962                                 } else {
963                                         dbg(0, "Error: Strange status returned from get_next_object()\n");
964                                 }
965
966                                 cs->num_cbs++;
967                                 cs->cbs = g_realloc(cs->cbs, (sizeof(struct command_saved_cb) * cs->num_cbs));
968                                 cs->cbs[cs->num_cbs-1].cb = cb;
969                                 cs->cbs[cs->num_cbs-1].attr = prev;
970                                         
971                                 cb_attr.u.callback = cb;
972                                 cb_attr.type = attr_callback;
973
974                                 func->add_attr(prev.u.data, &cb_attr);
975
976                         } else {
977                                 dbg(0, "Could not add callback because add_attr is missing for type %i}n", prev.type);
978                         }
979                 }
980
981                 if (status == 2) {
982                         prev = cs->res.attr;
983                 } else {
984                         prev = cs->navit;
985                 }
986         }
987
988         command_saved_evaluate_idle(cs);
989
990         return 1;
991 }
992
993 struct command_saved
994 *command_saved_new(char *command, struct navit *navit, struct callback *cb)
995 {
996         struct command_saved *ret;
997
998         ret = g_new0(struct command_saved, 1);
999         ret->command = g_strdup(command);
1000         ret->navit.u.navit = navit;
1001         ret->navit.type = attr_navit;
1002         ret->cb = cb;
1003         ret->error = not_ready;
1004
1005         if (!command_register_callbacks(ret)) {
1006                 // We try this as an idle call again
1007                 ret->register_cb = callback_new_1(callback_cast(command_saved_callbacks_changed), ret);
1008                 ret->register_ev = event_add_idle(300, ret->register_cb);
1009         }               
1010
1011         return ret;
1012 }
1013
1014 void 
1015 command_saved_destroy(struct command_saved *cs)
1016 {
1017         g_free(cs->command);
1018         g_free(cs);
1019 }