Added SILC Map.
[silc.git] / apps / silcmap / silcmap_command.c
1 /*
2
3   silcmap_command.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2003 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 #include "silcincludes.h"
21 #include "silcclient.h"
22 #include "silcmap.h"
23
24 /******* Command Script Parsing **********************************************/
25
26 SILC_CONFIG_CALLBACK(silc_map_cmd_server);
27 SILC_CONFIG_CALLBACK(silc_map_cmd_loadmap);
28 SILC_CONFIG_CALLBACK(silc_map_cmd_writemap);
29 SILC_CONFIG_CALLBACK(silc_map_cmd_writemaphtml);
30 SILC_CONFIG_CALLBACK(silc_map_cmd_writehtml);
31 SILC_CONFIG_CALLBACK(silc_map_cmd_cut);
32 SILC_CONFIG_CALLBACK(silc_map_cmd_rectangle);
33 SILC_CONFIG_CALLBACK(silc_map_cmd_circle);
34 SILC_CONFIG_CALLBACK(silc_map_cmd_line);
35 SILC_CONFIG_CALLBACK(silc_map_cmd_text);
36
37 static const SilcConfigTable silc_map_table_loadmap[] =
38 {
39   { "filename", SILC_CONFIG_ARG_STR, silc_map_cmd_loadmap, NULL },
40 };
41
42 static const SilcConfigTable silc_map_table_writemap[] =
43 {
44   { "filename", SILC_CONFIG_ARG_STR, silc_map_cmd_writemap, NULL },
45 };
46
47 static const SilcConfigTable silc_map_table_writemaphtml[] =
48 {
49   { "filename", SILC_CONFIG_ARG_STR, silc_map_cmd_writemaphtml, NULL },
50   { "image", SILC_CONFIG_ARG_STR, silc_map_cmd_writemaphtml, NULL },
51   { "cut_lat", SILC_CONFIG_ARG_STRE, silc_map_cmd_writemaphtml, NULL },
52   { "cut_lon", SILC_CONFIG_ARG_STRE, silc_map_cmd_writemaphtml, NULL },
53 };
54
55 static const SilcConfigTable silc_map_table_writehtml[] =
56 {
57   { "filename", SILC_CONFIG_ARG_STR, silc_map_cmd_writehtml, NULL },
58 };
59
60 static const SilcConfigTable silc_map_table_cut[] =
61 {
62   { "lat", SILC_CONFIG_ARG_STR, silc_map_cmd_cut, NULL },
63   { "lon", SILC_CONFIG_ARG_STR, silc_map_cmd_cut, NULL },
64   { "width", SILC_CONFIG_ARG_INT, silc_map_cmd_cut, NULL },
65   { "height", SILC_CONFIG_ARG_INT, silc_map_cmd_cut, NULL },
66   { "filename", SILC_CONFIG_ARG_STR, silc_map_cmd_cut, NULL },
67 };
68
69 static const SilcConfigTable silc_map_table_rectangle[] =
70 {
71   { "lat", SILC_CONFIG_ARG_STR, silc_map_cmd_rectangle, NULL },
72   { "lon", SILC_CONFIG_ARG_STR, silc_map_cmd_rectangle, NULL },
73   { "color", SILC_CONFIG_ARG_STR, silc_map_cmd_rectangle, NULL },
74   { "label", SILC_CONFIG_ARG_STR, silc_map_cmd_rectangle, NULL },
75   { "lposx", SILC_CONFIG_ARG_INT, silc_map_cmd_rectangle, NULL },
76   { "lposy", SILC_CONFIG_ARG_INT, silc_map_cmd_rectangle, NULL },
77   { "lcolor", SILC_CONFIG_ARG_STR, silc_map_cmd_rectangle, NULL },
78 };
79
80 static const SilcConfigTable silc_map_table_circle[] =
81 {
82   { "lat", SILC_CONFIG_ARG_STR, silc_map_cmd_circle, NULL },
83   { "lon", SILC_CONFIG_ARG_STR, silc_map_cmd_circle, NULL },
84   { "color", SILC_CONFIG_ARG_STR, silc_map_cmd_circle, NULL },
85   { "label", SILC_CONFIG_ARG_STR, silc_map_cmd_circle, NULL },
86   { "lposx", SILC_CONFIG_ARG_INT, silc_map_cmd_circle, NULL },
87   { "lposy", SILC_CONFIG_ARG_INT, silc_map_cmd_circle, NULL },
88   { "lcolor", SILC_CONFIG_ARG_STR, silc_map_cmd_circle, NULL },
89 };
90
91 static const SilcConfigTable silc_map_table_line[] =
92 {
93   { "a_lat", SILC_CONFIG_ARG_STR, silc_map_cmd_line, NULL },
94   { "a_lon", SILC_CONFIG_ARG_STR, silc_map_cmd_line, NULL },
95   { "b_lat", SILC_CONFIG_ARG_STR, silc_map_cmd_line, NULL },
96   { "b_lon", SILC_CONFIG_ARG_STR, silc_map_cmd_line, NULL },
97   { "width", SILC_CONFIG_ARG_STR, silc_map_cmd_line, NULL },
98   { "color", SILC_CONFIG_ARG_STR, silc_map_cmd_line, NULL },
99 };
100
101 static const SilcConfigTable silc_map_table_text[] =
102 {
103   { "lat", SILC_CONFIG_ARG_STR, silc_map_cmd_text, NULL },
104   { "lon", SILC_CONFIG_ARG_STR, silc_map_cmd_text, NULL },
105   { "color", SILC_CONFIG_ARG_STR, silc_map_cmd_text, NULL },
106   { "text", SILC_CONFIG_ARG_STR, silc_map_cmd_text, NULL },
107 };
108
109 static const SilcConfigTable silc_map_table_server[] =
110 {
111   /* Details */
112   { "hostname", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
113   { "ip", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
114   { "port", SILC_CONFIG_ARG_INT, silc_map_cmd_server, NULL },
115   { "public_key", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
116   { "country", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
117   { "city", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
118   { "admin", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
119   { "description", SILC_CONFIG_ARG_STRE, silc_map_cmd_server, NULL },
120   { "writemaphtml_url", SILC_CONFIG_ARG_STRE, silc_map_cmd_server, NULL },
121
122   /* Connect params */
123   { "connect", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
124   { "connect_timeout", SILC_CONFIG_ARG_INT, silc_map_cmd_server, NULL },
125
126   /* Statistics */
127   { "starttime", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
128   { "uptime", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
129   { "clients", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
130   { "channels", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
131   { "server_ops", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
132   { "router_ops", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
133   { "cell_clients", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
134   { "cell_channels", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
135   { "cell_servers", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
136   { "all_clients", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
137   { "all_channels", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
138   { "all_servers", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
139   { "all_routers", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
140   { "all_server_ops", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
141   { "all_router_ops", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
142   { "motd", SILC_CONFIG_ARG_TOGGLE, silc_map_cmd_server, NULL },
143
144   /* Colors */
145   { "up_color", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
146   { "down_color", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
147   { "up_text_color", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
148   { "down_text_color", SILC_CONFIG_ARG_STR, silc_map_cmd_server, NULL },
149
150   /* Map commands */
151   { "cut", SILC_CONFIG_ARG_BLOCK,
152     silc_map_cmd_cut, silc_map_table_cut },
153   { "rectangle", SILC_CONFIG_ARG_BLOCK,
154     silc_map_cmd_rectangle, silc_map_table_rectangle },
155   { "circle", SILC_CONFIG_ARG_BLOCK,
156     silc_map_cmd_circle, silc_map_table_circle },
157   { "line", SILC_CONFIG_ARG_BLOCK,
158     silc_map_cmd_line, silc_map_table_line },
159   { "text", SILC_CONFIG_ARG_BLOCK,
160     silc_map_cmd_text, silc_map_table_text },
161 };
162
163 static const SilcConfigTable silc_map_table_main[] =
164 {
165   { "server", SILC_CONFIG_ARG_BLOCK,
166     silc_map_cmd_server, silc_map_table_server },
167   { "loadmap", SILC_CONFIG_ARG_BLOCK,
168     silc_map_cmd_loadmap, silc_map_table_loadmap },
169   { "writemap", SILC_CONFIG_ARG_BLOCK,
170     silc_map_cmd_writemap, silc_map_table_writemap },
171   { "writemaphtml", SILC_CONFIG_ARG_BLOCK,
172     silc_map_cmd_writemaphtml, silc_map_table_writemaphtml },
173   { "writehtml", SILC_CONFIG_ARG_BLOCK,
174     silc_map_cmd_writehtml, silc_map_table_writehtml },
175   { "cut", SILC_CONFIG_ARG_BLOCK,
176     silc_map_cmd_cut, silc_map_table_cut },
177   { "rectangle", SILC_CONFIG_ARG_BLOCK,
178     silc_map_cmd_rectangle, silc_map_table_rectangle },
179   { "circle", SILC_CONFIG_ARG_BLOCK,
180     silc_map_cmd_circle, silc_map_table_circle },
181   { "line", SILC_CONFIG_ARG_BLOCK,
182     silc_map_cmd_line, silc_map_table_line },
183   { "text", SILC_CONFIG_ARG_BLOCK,
184     silc_map_cmd_text, silc_map_table_text },
185   { NULL },
186 };
187
188 /* Command datas.  Used when command is outside server { } section. */
189 static char *filename = NULL;
190 static char *lat = NULL;
191 static char *lon = NULL;
192 static char *lat2 = NULL;
193 static char *lon2 = NULL;
194 static SilcUInt32 width = 0;
195 static SilcUInt32 height = 0;
196 static SilcInt16 r = 0;
197 static SilcInt16 g = 0;
198 static SilcInt16 b = 0;
199 static SilcInt16 lr = -1;
200 static SilcInt16 lg = -1;
201 static SilcInt16 lb = -1;
202 static char *text = NULL;
203 static SilcInt32 lposx = 0;
204 static SilcInt32 lposy = 0;
205 static bool color_set = FALSE;
206 static bool lcolor_set = FALSE;
207
208 /* Current server section. */
209 SilcMapConnection curr_conn = NULL;
210
211 /* Command: server, performs the connection to the remote server and
212    gathers statistical information. */
213
214 SILC_CONFIG_CALLBACK(silc_map_cmd_server)
215 {
216   SilcMap map = context;
217   int retval = SILC_CONFIG_OK;
218
219   if (!map->bitmap) {
220     fprintf(stderr, "You must call loadmap command before server command\n");
221     return SILC_CONFIG_ESILENT;
222   }
223
224   if (type == SILC_CONFIG_ARG_BLOCK) {
225     SILC_LOG_DEBUG(("Server config parsed"));
226
227     if (!curr_conn->ips) {
228       fprintf(stderr, "IP must be configured\n");
229       return SILC_CONFIG_EMISSFIELDS;
230     }
231     if (!curr_conn->hostnames) {
232       fprintf(stderr, "Hostname must be configured\n");
233       return SILC_CONFIG_EMISSFIELDS;
234     }
235     if (!curr_conn->port) {
236       fprintf(stderr, "Port must be configured\n");
237       return SILC_CONFIG_EMISSFIELDS;
238     }
239
240     /* The server data is now gathered.  We continue by creating the
241        connection to the server and executing the requested commands. */
242     silc_map_connect(map, curr_conn);
243     map->conns_num++;
244
245     /* Cleanup */
246     curr_conn = NULL;
247
248     return retval;
249   }
250
251   /* Mark the current parsed server */
252   if (!curr_conn) {
253     curr_conn = silc_calloc(1, sizeof(*curr_conn));
254     if (!curr_conn)
255       return SILC_CONFIG_ESILENT;
256
257     curr_conn->hostnames = silc_dlist_init();
258     curr_conn->ips = silc_dlist_init();
259     curr_conn->commands = silc_dlist_init();
260     curr_conn->map = map;
261     if (!map->conns)
262       map->conns = silc_dlist_init();
263     silc_dlist_add(map->conns, curr_conn);
264   }
265
266   if (!strcmp(name, "hostname")) {
267     silc_dlist_add(curr_conn->hostnames, strdup((char *)val));
268   } else if (!strcmp(name, "ip")) {
269     silc_dlist_add(curr_conn->ips, strdup((char *)val));
270   } else if (!strcmp(name, "port")) {
271     curr_conn->port = (SilcUInt32)*(int *)val;
272   } else if (!strcmp(name, "public_key")) {
273     curr_conn->public_key = strdup((char *)val);
274   } else if (!strcmp(name, "country")) {
275     curr_conn->country = strdup((char *)val);
276   } else if (!strcmp(name, "city")) {
277     curr_conn->city = strdup((char *)val);
278   } else if (!strcmp(name, "admin")) {
279     curr_conn->admin = strdup((char *)val);
280   } else if (!strcmp(name, "description")) {
281     curr_conn->description = strdup((char *)val);
282   } else if (!strcmp(name, "writemaphtml_url")) {
283     curr_conn->writemaphtml_url = strdup((char *)val);
284   } else if (!strcmp(name, "connect")) {
285     curr_conn->connect = (bool)*(int *)val;
286   } else if (!strcmp(name, "connect_timeout")) {
287     curr_conn->connect_timeout = (SilcUInt32)*(int *)val;
288   } else if (!strcmp(name, "starttime")) {
289     curr_conn->starttime = (bool)*(int *)val;
290   } else if (!strcmp(name, "uptime")) {
291     curr_conn->uptime = (bool)*(int *)val;
292   } else if (!strcmp(name, "clients")) {
293     curr_conn->clients = (bool)*(int *)val;
294   } else if (!strcmp(name, "channels")) {
295     curr_conn->channels = (bool)*(int *)val;
296   } else if (!strcmp(name, "server_ops")) {
297     curr_conn->server_ops = (bool)*(int *)val;
298   } else if (!strcmp(name, "router_ops")) {
299     curr_conn->router_ops = (bool)*(int *)val;
300   } else if (!strcmp(name, "cell_clients")) {
301     curr_conn->cell_clients = (bool)*(int *)val;
302   } else if (!strcmp(name, "cell_channels")) {
303     curr_conn->cell_channels = (bool)*(int *)val;
304   } else if (!strcmp(name, "cell_servers")) {
305     curr_conn->cell_servers = (bool)*(int *)val;
306   } else if (!strcmp(name, "all_clients")) {
307     curr_conn->all_clients = (bool)*(int *)val;
308   } else if (!strcmp(name, "all_channels")) {
309     curr_conn->all_channels = (bool)*(int *)val;
310   } else if (!strcmp(name, "all_servers")) {
311     curr_conn->all_servers = (bool)*(int *)val;
312   } else if (!strcmp(name, "all_routers")) {
313     curr_conn->all_routers = (bool)*(int *)val;
314   } else if (!strcmp(name, "all_server_ops")) {
315     curr_conn->all_server_ops = (bool)*(int *)val;
316   } else if (!strcmp(name, "all_router_ops")) {
317     curr_conn->all_router_ops = (bool)*(int *)val;
318   } else if (!strcmp(name, "motd")) {
319     curr_conn->motd = (bool)*(int *)val;
320   } else if (!strcmp(name, "up_color")) {
321     curr_conn->up_color = strdup((char *)val);
322   } else if (!strcmp(name, "down_color")) {
323     curr_conn->down_color = strdup((char *)val);
324   } else if (!strcmp(name, "up_text_color")) {
325     curr_conn->up_text_color = strdup((char *)val);
326   } else if (!strcmp(name, "down_text_color")) {
327     curr_conn->down_text_color = strdup((char *)val);
328   } else {
329     retval = SILC_CONFIG_ESILENT;
330   }
331
332   return retval;
333 }
334
335 /* Command: loadmap, loadmaps the bitmap map image. */
336
337 SILC_CONFIG_CALLBACK(silc_map_cmd_loadmap)
338 {
339   SilcMap map = context;
340   int retval = SILC_CONFIG_OK;
341
342   if (type == SILC_CONFIG_ARG_BLOCK) {
343     if (!filename)
344       return SILC_CONFIG_EMISSFIELDS;
345
346     SILC_LOG_DEBUG(("loadmap: file: %s", filename));
347
348     /* Destroy old bitmap if loadmaped */
349     silc_free(map->bitmap);
350
351     /* Loadmap the bitmap image */
352     if (!silc_map_load_ppm(map, filename))
353       retval = SILC_CONFIG_ESILENT;
354
355     /* Cleanup */
356     silc_free(filename);
357     filename = NULL;
358
359     return retval;
360   }
361
362   if (!strcmp(name, "filename"))
363     filename = strdup((char *)val);
364   else
365     retval = SILC_CONFIG_ESILENT;
366
367   return retval;
368 }
369
370 /* Command: writemap, writemap the map into bitmap file. */
371
372 SILC_CONFIG_CALLBACK(silc_map_cmd_writemap)
373 {
374   SilcMap map = context;
375   int retval = SILC_CONFIG_OK;
376
377   if (type == SILC_CONFIG_ARG_BLOCK) {
378     if (!filename)
379       return SILC_CONFIG_EMISSFIELDS;
380
381     SILC_LOG_DEBUG(("writemap: file: %s", filename));
382
383     /* Execute directly if there are no connections */
384     if (map->conns_num == 0) {
385       /* Writemap the map */
386       if (!silc_map_write_ppm(map, filename))
387         retval = SILC_CONFIG_ESILENT;
388     } else {
389       map->writemap.filename = strdup(filename);
390       map->writemap.writemap = TRUE;
391     }
392
393     /* Cleanup */
394     silc_free(filename);
395     filename = NULL;
396
397     return retval;
398   }
399
400   if (!strcmp(name, "filename"))
401     filename = strdup((char *)val);
402   else
403     retval = SILC_CONFIG_ESILENT;
404
405   return retval;
406 }
407
408 /* Command: writemaphtml, writes HTML map of the image map. */
409
410 SILC_CONFIG_CALLBACK(silc_map_cmd_writemaphtml)
411 {
412   SilcMap map = context;
413   int retval = SILC_CONFIG_OK;
414
415   if (type == SILC_CONFIG_ARG_BLOCK) {
416     if (!filename)
417       return SILC_CONFIG_EMISSFIELDS;
418
419     SILC_LOG_DEBUG(("writehmaphtml: file: %s", filename));
420
421     /* Will generate HTML map page */
422     map->writemaphtml.filename = filename;
423     map->writemaphtml.text = text;
424     if (lon)
425       map->writemaphtml.x = silc_map_lon2x(map, lon);
426     if (lat)
427       map->writemaphtml.y = silc_map_lat2y(map, lat);
428     map->writemaphtml.writemaphtml = TRUE;
429
430     /* Clean up */
431     silc_free(lat);
432     silc_free(lon);
433     filename = NULL;
434     text = NULL;
435     lat = lon = NULL;
436
437     return retval;
438   }
439
440   if (!strcmp(name, "filename"))
441     filename = strdup((char *)val);
442   else if (!strcmp(name, "image"))
443     text = strdup((char *)val);
444   else if (!strcmp(name, "cut_lat"))
445     lat = strdup((char *)val);
446   else if (!strcmp(name, "cut_lon"))
447     lon = strdup((char *)val);
448   else
449     retval = SILC_CONFIG_ESILENT;
450
451   return retval;
452 }
453
454 /* Command: writehtml, writes the gathered data into HTML pages. */
455
456 SILC_CONFIG_CALLBACK(silc_map_cmd_writehtml)
457 {
458   SilcMap map = context;
459   int retval = SILC_CONFIG_OK;
460
461   if (type == SILC_CONFIG_ARG_BLOCK) {
462     if (!filename)
463       return SILC_CONFIG_EMISSFIELDS;
464
465     SILC_LOG_DEBUG(("writehtml: file: %s", filename));
466
467     /* Will generate HTML pages */
468     map->writehtml.filename = filename;
469     map->writehtml.writehtml = TRUE;
470     filename = NULL;
471
472     return retval;
473   }
474
475   if (!strcmp(name, "filename"))
476     filename = strdup((char *)val);
477   else
478     retval = SILC_CONFIG_ESILENT;
479
480   return retval;
481 }
482
483 /* Command: cut, cut's a specified area from the map. */
484
485 SILC_CONFIG_CALLBACK(silc_map_cmd_cut)
486 {
487   SilcMap map = context;
488   int retval = SILC_CONFIG_OK;
489   bool ret;
490
491   if (type == SILC_CONFIG_ARG_BLOCK) {
492     SilcMap map2;
493
494     if (!filename || !lat || !lon || !width || !height)
495       return SILC_CONFIG_EMISSFIELDS;
496
497     SILC_LOG_DEBUG(("cut: lat: %s lon: %s w: %ld h: %ld file: %s",
498                     lat, lon, width, height, filename));
499
500     /* Execute directly if not inside connection block */
501     if (!curr_conn) {
502       if (!map->conns_num) {
503         /* Before any connection blocks */
504
505         /* Cut the chunk from the map. */
506         ret = silc_map_cut(map, silc_map_lon2x(map, lon),
507                            silc_map_lat2y(map, lat),
508                            width, height, &map2);
509         if (ret) {
510           /* Writemap the chunk. */
511           ret = silc_map_write_ppm(map2, filename);
512           silc_map_free(map2);
513         }
514         if (!ret)
515           retval = SILC_CONFIG_ESILENT;
516       } else {
517         /* After all connection blocks */
518         map->cut.filename = strdup(filename);
519         map->cut.x = silc_map_lon2x(map, lon);
520         map->cut.y = silc_map_lat2y(map, lat);
521         map->cut.width = width;
522         map->cut.height = height;
523         map->cut.cut = TRUE;
524       }
525     } else {
526       SilcMapCommand cmd = silc_calloc(1, sizeof(*cmd));
527       if (!cmd)
528         return SILC_CONFIG_ESILENT;
529
530       silc_dlist_add(curr_conn->commands, cmd);
531       cmd->filename = strdup(filename);
532       cmd->x = silc_map_lon2x(map, lon);
533       cmd->y = silc_map_lat2y(map, lat);
534       cmd->width = width;
535       cmd->height = height;
536       cmd->cut = TRUE;
537     }
538
539     /* Cleanup */
540     silc_free(filename);
541     silc_free(lat);
542     silc_free(lon);
543     filename = NULL;
544     lat = NULL;
545     lon = NULL;
546     width = 0;
547     height = 0;
548
549     return retval;
550   }
551
552   if (!strcmp(name, "lat"))
553     lat = strdup((char *)val);
554   else if (!strcmp(name, "lon"))
555     lon = strdup((char *)val);
556   else if (!strcmp(name, "width"))
557     width = (SilcUInt32)*(int *)val;
558   else if (!strcmp(name, "height"))
559     height = (SilcUInt32)*(int *)val;
560   else if (!strcmp(name, "filename"))
561     filename = strdup((char *)val);
562   else
563     retval = SILC_CONFIG_ESILENT;
564
565   return retval;
566 }
567
568 /* Command: rectangle, draws a rectangle on the map. */
569
570 SILC_CONFIG_CALLBACK(silc_map_cmd_rectangle)
571 {
572   SilcMap map = context;
573   int retval = SILC_CONFIG_OK;
574   bool ret;
575
576   if (type == SILC_CONFIG_ARG_BLOCK) {
577     if (!lat || !lon)
578       return SILC_CONFIG_EMISSFIELDS;
579
580     SILC_LOG_DEBUG(("rectangle: lat: %s lon: %s color: %d %d %d",
581                     lat, lon, r, g, b));
582
583     if (lr == -1) {
584       lr = r;
585       lg = g;
586       lb = b;
587     }
588
589     /* Execute directly if not for connection */
590     if (!curr_conn) {
591       /* Draw the rectangle */
592       ret = silc_map_draw_rectangle(map, silc_map_lon2x(map, lon),
593                                     silc_map_lat2y(map, lat),
594                                     r, g, b, text, lposx, lposy, lr, lg, lb);
595       if (!ret)
596         retval = SILC_CONFIG_ESILENT;
597     } else {
598       SilcMapCommand cmd = silc_calloc(1, sizeof(*cmd));
599       if (!cmd)
600         return SILC_CONFIG_ESILENT;
601
602       silc_dlist_add(curr_conn->commands, cmd);
603       cmd->r = r;
604       cmd->g = g;
605       cmd->b = b;
606       cmd->lr = lr;
607       cmd->lg = lg;
608       cmd->lb = lb;
609       cmd->x = silc_map_lon2x(map, lon);
610       cmd->y = silc_map_lat2y(map, lat);
611       cmd->text = strdup(text);
612       cmd->lposx = lposx;
613       cmd->lposy = lposy;
614       cmd->draw_rectangle = TRUE;
615       cmd->color_set = color_set;
616       cmd->lcolor_set = lcolor_set;
617     }
618
619     /* Cleanup */
620     silc_free(text);
621     silc_free(lat);
622     silc_free(lon);
623     text = NULL;
624     lat = NULL;
625     lon = NULL;
626     lposx = 0;
627     lposy = 0;
628     lr = lg = lb = -1;
629     color_set = lcolor_set = FALSE;
630
631     return retval;
632   }
633
634   if (!strcmp(name, "lat"))
635     lat = strdup((char *)val);
636   else if (!strcmp(name, "lon"))
637     lon = strdup((char *)val);
638   else if (!strcmp(name, "color")) {
639     if (!silc_map_parse_color((const char *)val, &r, &g, &b))
640       retval = SILC_CONFIG_ESILENT;
641     color_set = TRUE;
642   } else if (!strcmp(name, "label"))
643     text = strdup((char *)val);
644   else if (!strcmp(name, "lposx"))
645     lposx = (SilcInt32)*(int *)val;
646   else if (!strcmp(name, "lposy"))
647     lposy = (SilcInt32)*(int *)val;
648   else if (!strcmp(name, "lcolor")) {
649     if (!silc_map_parse_color((const char *)val, &lr, &lg, &lb))
650       retval = SILC_CONFIG_ESILENT;
651     lcolor_set = TRUE;
652  } else
653     retval = SILC_CONFIG_ESILENT;
654
655   return retval;
656 }
657
658 /* Command: circle, draws a circle on the map. */
659
660 SILC_CONFIG_CALLBACK(silc_map_cmd_circle)
661 {
662   SilcMap map = context;
663   int retval = SILC_CONFIG_OK;
664   bool ret;
665
666   if (type == SILC_CONFIG_ARG_BLOCK) {
667     if (!lat || !lon)
668       return SILC_CONFIG_EMISSFIELDS;
669
670     SILC_LOG_DEBUG(("circle: lat: %s lon: %s color: %d %d %d",
671                     lat, lon, r, g, b));
672
673     if (lr == -1) {
674       lr = r;
675       lg = g;
676       lb = b;
677     }
678
679     /* Execute directly if not for connection */
680     if (!curr_conn) {
681       /* Draw the circle */
682       ret = silc_map_draw_circle(map, silc_map_lon2x(map, lon),
683                                  silc_map_lat2y(map, lat),
684                                  r, g, b, text, lposx, lposy, lr, lg, lb);
685       if (!ret)
686         retval = SILC_CONFIG_ESILENT;
687     } else {
688       SilcMapCommand cmd = silc_calloc(1, sizeof(*cmd));
689       if (!cmd)
690         return SILC_CONFIG_ESILENT;
691
692       silc_dlist_add(curr_conn->commands, cmd);
693       cmd->r = r;
694       cmd->g = g;
695       cmd->b = b;
696       cmd->lr = lr;
697       cmd->lg = lg;
698       cmd->lb = lb;
699       cmd->x = silc_map_lon2x(map, lon);
700       cmd->y = silc_map_lat2y(map, lat);
701       cmd->text = strdup(text);
702       cmd->lposx = lposx;
703       cmd->lposy = lposy;
704       cmd->draw_circle = TRUE;
705       cmd->color_set = color_set;
706       cmd->lcolor_set = lcolor_set;
707     }
708
709     /* Cleanup */
710     silc_free(text);
711     silc_free(lat);
712     silc_free(lon);
713     text = NULL;
714     lat = NULL;
715     lon = NULL;
716     lposx = 0;
717     lposy = 0;
718     lr = lg = lb = -1;
719     color_set = lcolor_set = FALSE;
720
721     return retval;
722   }
723
724   if (!strcmp(name, "lat"))
725     lat = strdup((char *)val);
726   else if (!strcmp(name, "lon"))
727     lon = strdup((char *)val);
728   else if (!strcmp(name, "color")) {
729     if (!silc_map_parse_color((const char *)val, &r, &g, &b))
730       retval = SILC_CONFIG_ESILENT;
731     color_set = TRUE;
732   } else if (!strcmp(name, "label"))
733     text = strdup((char *)val);
734   else if (!strcmp(name, "lposx"))
735     lposx = (SilcInt32)*(int *)val;
736   else if (!strcmp(name, "lposy"))
737     lposy = (SilcInt32)*(int *)val;
738   else if (!strcmp(name, "lcolor")) {
739     if (!silc_map_parse_color((const char *)val, &lr, &lg, &lb))
740       retval = SILC_CONFIG_ESILENT;
741     lcolor_set = TRUE;
742   } else
743     retval = SILC_CONFIG_ESILENT;
744
745   return retval;
746 }
747
748 /* Command: line, draws a line between two points in the map. */
749
750 SILC_CONFIG_CALLBACK(silc_map_cmd_line)
751 {
752   SilcMap map = context;
753   int retval = SILC_CONFIG_OK;
754   bool ret;
755
756   if (type == SILC_CONFIG_ARG_BLOCK) {
757     if (!lat || !lon || !lat2 || !lon2)
758       return SILC_CONFIG_EMISSFIELDS;
759
760     SILC_LOG_DEBUG(("line: alat: %s alon: %s blat: %s blon: %s "
761                     "width: %ld color: %d %d %d",
762                     lat, lon, lat2, lon2, width, r, g, b));
763
764     if (!width)
765       width = 1;
766
767     /* Execute directly if not for connection */
768     if (!curr_conn) {
769       /* Draw the line */
770       ret = silc_map_draw_line(map, width,
771                                silc_map_lon2x(map, lon),
772                                silc_map_lat2y(map, lat),
773                                silc_map_lon2x(map, lon2),
774                                silc_map_lat2y(map, lat2),
775                                r, g, b);
776       if (!ret)
777         retval = SILC_CONFIG_ESILENT;
778     } else {
779       SilcMapCommand cmd = silc_calloc(1, sizeof(*cmd));
780       if (!cmd)
781         return SILC_CONFIG_ESILENT;
782
783       silc_dlist_add(curr_conn->commands, cmd);
784       cmd->r = r;
785       cmd->g = g;
786       cmd->b = b;
787       cmd->x = silc_map_lon2x(map, lon);
788       cmd->y = silc_map_lat2y(map, lat);
789       cmd->x2 = silc_map_lon2x(map, lon2);
790       cmd->y2 = silc_map_lat2y(map, lat2);
791       cmd->width = width;
792       cmd->draw_line = TRUE;
793       cmd->color_set = color_set;
794     }
795
796     /* Cleanup */
797     silc_free(lat);
798     silc_free(lon);
799     silc_free(lat2);
800     silc_free(lon2);
801     lat = NULL;
802     lon = NULL;
803     lat2 = NULL;
804     lon2 = NULL;
805     width = 0;
806     color_set = FALSE;
807
808     return retval;
809   }
810
811   if (!strcmp(name, "a_lat"))
812     lat = strdup((char *)val);
813   else if (!strcmp(name, "a_lon"))
814     lon = strdup((char *)val);
815   else if (!strcmp(name, "b_lat"))
816     lat2 = strdup((char *)val);
817   else if (!strcmp(name, "b_lon"))
818     lon2 = strdup((char *)val);
819   else if (!strcmp(name, "width"))
820     width = (SilcUInt32)*(int *)val;
821   else if (!strcmp(name, "color")) {
822     if (!silc_map_parse_color((const char *)val, &r, &g, &b))
823       retval = SILC_CONFIG_ESILENT;
824     color_set = TRUE;
825   } else
826     retval = SILC_CONFIG_ESILENT;
827
828   return retval;
829 }
830
831 /* Command: text, prints a text on the map. */
832
833 SILC_CONFIG_CALLBACK(silc_map_cmd_text)
834 {
835   SilcMap map = context;
836   int retval = SILC_CONFIG_OK;
837   bool ret;
838
839   if (type == SILC_CONFIG_ARG_BLOCK) {
840     if (!lat || !lon || !text)
841       return SILC_CONFIG_EMISSFIELDS;
842
843     SILC_LOG_DEBUG(("text: lat: %s lon: %s color: %d %d %d text: %s",
844                     lat, lon, r, g, b, text));
845
846     /* Execute directly if not for connection */
847     if (!curr_conn) {
848       /* Print the text */
849       ret = silc_map_draw_text(map, text,
850                                silc_map_lon2x(map, lon),
851                                silc_map_lat2y(map, lat),
852                                r, g, b);
853       if (!ret)
854         retval = SILC_CONFIG_ESILENT;
855     } else {
856       SilcMapCommand cmd = silc_calloc(1, sizeof(*cmd));
857       if (!cmd)
858         return SILC_CONFIG_ESILENT;
859
860       silc_dlist_add(curr_conn->commands, cmd);
861       cmd->r = r;
862       cmd->g = g;
863       cmd->b = b;
864       cmd->x = silc_map_lon2x(map, lon);
865       cmd->y = silc_map_lat2y(map, lat);
866       cmd->text = strdup(text);
867       cmd->draw_text = TRUE;
868       cmd->color_set = color_set;
869     }
870
871     /* Cleanup */
872     silc_free(text);
873     silc_free(lat);
874     silc_free(lon);
875     text = NULL;
876     lat = NULL;
877     lon = NULL;
878     color_set = FALSE;
879
880     return retval;
881   }
882
883   if (!strcmp(name, "lat"))
884     lat = strdup((char *)val);
885   else if (!strcmp(name, "lon"))
886     lon = strdup((char *)val);
887   else if (!strcmp(name, "color")) {
888     if (!silc_map_parse_color((const char *)val, &r, &g, &b))
889       retval = SILC_CONFIG_ESILENT;
890     color_set = TRUE;
891   } else if (!strcmp(name, "text"))
892     text = strdup((char *)val);
893   else
894     retval = SILC_CONFIG_ESILENT;
895
896   return retval;
897 }
898
899 /* Parses the commands from the file `filename'. */
900
901 bool silc_map_commands_parse(SilcMap map, const char *filename)
902 {
903   SilcConfigEntity ent;
904   SilcConfigFile *file;
905   bool retval = TRUE;
906   int ret;
907
908   SILC_LOG_DEBUG(("Parsing commands"));
909
910   /* Open commands file */
911   file = silc_config_open(filename);
912   if (!file) {
913     fprintf(stderr, "Cannot open commands file '%s'\n", filename);
914     return FALSE;
915   }
916
917   /* Parse the commands */
918   ent = silc_config_init(file);
919   silc_config_register_table(ent, silc_map_table_main, map);
920   ret = silc_config_main(ent);
921
922   SILC_LOG_DEBUG(("Parsing status: %s", silc_config_strerror(ret)));
923
924   if (ret && ret != SILC_CONFIG_ESILENT) {
925     fprintf(stderr, "Error parsing commands: %s, line %ld\n",
926             silc_config_strerror(ret), silc_config_get_line(file));
927     retval = FALSE;
928   }
929
930   /* Cleanup */
931   silc_config_close(file);
932   return retval;
933 }