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