/* xrmap - vector based global map generating program 
 *
 * Copyright (C) 2001-2003 Jean-Pierre Demailly <demailly@ujf-grenoble.fr>
 * ftp://ftp.ac-grenoble.fr/ge/geosciences
 *
 * loosely derived from "rmap"
 * Copyright (C) 2000 Reza Naima <reza@reza.net>
 * http://www.reza.net/rmap/
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */

/* #define DEBUG */
/* #define TRACE */
/* #define SUPERTRACE */
#define ARCINFO

/* #include <sys/timeb.h> */

#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysymdef.h>
#include <X11/keysym.h>
#include <X11/xpm.h>

#ifdef ZLIB
#include <zlib.h>
#endif

#include "xrmap.h"
#include "version.h"
#include "bitmaps.h"
#include "menudefs.h"

/* Extended ascii conversion for search routine ('192 and more) */
/* ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ */
/* AAAAAAACEEEEIIIIDNOOOOO×OUUUUYPSaaaaaaaceeeeiiiitnooooo÷ouuuuyhy */
char cvs[] =
  "aaaaaaaceeeeiiiidnooooo×ouuuuypsaaaaaaaceeeeiiiitnooooo÷ouuuuyhy";
char *continent[] = { "AF", "AS", "EU", "NA", "SA", "OC" };

char *flag_formats[] = { "xpm", "gif", "png", "jpg", "eps", "svg" };
int  flag_rev[] =      { 3, 2, 1, 0, 5, 4}; 
char *flag_ordering;

char *flag_descr;
char **flag_type;
char **flag_dir;
int flag_size = 0;
int num_flag_dirs;
int num_flag_types;

/* Global variables */
Display * dpy;
Visual * visual;
Window Root, mainwin = 0, datawin = 0, cmdwin = 0, explwin = 0, flagwin = 0;
Colormap cmap = 0;
GC gc = 0;
Atom wm_delete_window, wm_protocols;
Pixel black, white;
Pixmap datapix = None;
Pixmap cmdpix = None;
Pixmap explpix = None;
Pixmap butpix[3] = { None, None, None };

XImage *flag_image[2] = { NULL, NULL};
XImage *big_flag_image = NULL;

int scr;
int color_depth;
int color_pad;
int bigendian;
unsigned char *color_table;

char language[4];

XFontStruct * xfont[6];
int fontasc[6], fonth[6], fontasc[6], char_width;

char *file_filter = NULL;
char *expl_implicit;
char expl_currdir[256];
int expl_table_entries;
int expl_lines;
int expl_shift = 0;
int expl_output = 0;
char *error_msg = NULL;
char **expl_dirtable = NULL;
char **msg = NULL;

short country_table[676];
char **feature_descr[6];

int feature_length[6] = { 
  C_ENDCOLOR-C_FG_TEXT, C_CITY_CIRCLE-C_BG_MAP, C_FG_TEXT-C_CITY_CIRCLE, 
  5, 11, 12};
int feature_index[6] = { C_FG_TEXT, C_BG_MAP, C_CITY_CIRCLE, 0, 5, 16};

char lineorder0[6] = "01234";
int mark_step0[5] = { 150, 1200, 3000, 6000, 10000};
int name_step0[5] = { 400, 3000, 8000, 15000, 25000};
int city_mark0[5]  = { 1, 2, 3, 4, 5 };
int city_size0[5] = { 3000000, 700000, 300000, 100000, 0};
int airport_mark0[5]  = { 1, 2, 3, 4, 5 };
int airport_size0[5] = { 3500, 3000, 2500, 1500, 0};
int peak_mark0[5]  = { 1, 2, 3, 4, 5 };
int peak_size0[5] = { 6500, 4000, 1000, 500, -500};
char city_filter0[4] = "CR*";
char loc_filter0[16] = "BCIKLORSTV*";
char cmd_killed_char;

#ifdef ARCINFO
char dump_precision[20] = "%.5f %.5f\n";
char *dump_file = NULL;
int dump_format = DUMP_JPD;
int dump_split = 0;
int dump_verbose = 1;
char *arc_file = NULL;
int *arc_numseg = NULL;
char ***arc_index = NULL;
int arc_lambert = 0;
int arc_start = 0;
int arc_precision = 6;
int arc_search = 0;
double arc_x, arc_y;
double arc_transl = 0;
double arc_scale = 1.0/6378000.0;
double arc_lat0 = 60.0;
double arc_lon0 = 0.0;
#endif

char *search_string;
int *loc_pointer = NULL;
int *presel_pointer = NULL;
char *data_text = NULL;
int search_index = -1;
int search_by = 1;
int num_found;
int num_listed;
int start_list;
int start_shortcut = 0;
int datawin_on = 0;
int flagwin_on = 0;
int cmdwin_on = 0;
int explwin_on = 0;
int exposed = 0;
int notified = 0;
int escape_length = 0;
int ranking = 0;
int expert = 0;
int brief_menu = 0;
int secure = 0;
int dms = 0;
int theming = 0;

int num_msg = 0;
int time_count = 0;

int numcountry = 0, numtz = 0, numloc = 0, numpresel = 0;

int runlevel = 0;
int path_start;
int img_output = 0;
int reverse = 0;
int but_main_pressed = 0;
int but_data_pressed = 0;
int but_expl_pressed = 0;
int control_pressed = 0;
int line_clicked;
int overwrite = 1;
int visible = 0;
int point_shown = 0;
int setup_change = 0;
int caret_pos = 0;
int w_button = 0;
int h_button = 0;
int w_buttons = 0;
int cmd_killed_pos = 0;
int cmd_killed_length = 0;
int action_width = 0;
int use_memory = 1;
int start_menu = 0;
int im_compress = 0;

int box_x, box_y, box_width, box_height, box_spacing, box_numitems;
int mouse_x1, mouse_y1, mouse_x2, mouse_y2, maxmove;
int datawin_x=-1000000, datawin_y;
int flagwin_x=-1000000, flagwin_y;
int cmdwin_x=-1000000, cmdwin_y;
int explwin_x=-1000000, explwin_y;
int pixmap_width[2], pixmap_height[2];
int pixmap_height_max = 0;

unsigned int datawin_width, datawin_height;
unsigned int flagwin_width, flagwin_height;
unsigned int cmdwin_width, cmdwin_height, cmdwin_height0 = 480;
unsigned int explwin_width, explwin_height, explwin_height0 = 320;

int cmd_mode = MODE_RUN, cmd_type = M_RUN_START;
int spacing_generalmenu;
int spacing_filemenu;
int spacing_optionmenu;
int spacing_colormenu;
int spacing_helpmenu;

int line_pos;
int old_city_shown = -2;
int city_shown = 0;
int city_shown_box_x, city_shown_box_y, city_shown_box_w, city_shown_box_h;
int city_already_shown = 0;
int city_found = -1;
int text_shown;
int num_doc;
int tb_width; /* textbox width */
int text_drawn; /* is text really drawn ? */

char * cmd_string;

double preview;
double ps_width=150.0, ps_lm=30.0, ps_bm=30.0, ps_lw=1.0;
int ps_rot = 0, ps_grayscale = 0, ps_frame = 1;

char * print_cmd;
char * editor_cmd;
char * im_viewer;
char * ps_viewer;
char * svg_viewer;
char * svg_convert;
char * html_viewer;
char * midi_cmd;
char * prog_cmd[7];

char * list_lang;

char time_string[80] = "";

char * datapix_name = NULL;
char * cmdpix_name = NULL;
char * explpix_name = NULL;
char * flag_name = NULL;
char * butpix_name[3] = { NULL, NULL, NULL };

Country **countries = NULL;
Timezone **timezones = NULL;
Location **locations = NULL;

Header * header = NULL;
Segment_index * segment_index = NULL;
signed char * segment_buffer = NULL;
signed char * fullmap_buffer = NULL;

int *textboxes = NULL;

void * out_fd = NULL;

#define SEG_SELECT
#ifdef SEG_SELECT
int seg_mode = 0;
int seg_nummarked = 0;
char *seg_marked = NULL;
int *seg_specified = NULL;
#endif

/* forward references */
#define forward extern

forward int  set_flag_dirs();
forward void free_flag_data();
forward void list_flag_dirs();
forward void fix_features_description(ImageLayout * scene);
forward void search_city(ImageLayout * scene);
forward void search_output(ImageLayout * scene, int force);
forward void show_datawin(ImageLayout * scene, int raise);
forward void show_flagwin(ImageLayout * scene, int raise);
forward void update_auxil_windows(ImageLayout *scene);
forward void edit_rc_output(ImageLayout * scene);
forward int  parse_pixmaps(ImageLayout *scene, char *str);
forward int  parse_cmd_line(ImageLayout * scene, char *string, char *sep);
forward void generate(ImageLayout *scene);
forward void show_mark(ImageLayout *scene);

/* 
 *  SECTION 0 : A FEW BASIC ROUTINES
 */

int round2int(double x)
{
        if (x>0) 
           return (int)(x+0.5) ;
	else
	   return -(int)(-x+0.5);
}

short double2short(double x)
{
    if (x>32767.0) return 32767;
    if (x<-32767.0) return -32767;
    return (short)x;
}

double dms2decim(char * str)
{
double eps=1.0, deg=0.0, min=0.0, sec=0.0;

    if (*str == '-') {
       ++str;
       eps = -1.0;
    }
    if (index(str, '°')) {
       sscanf(str, "%lf°%lf'%lf", &deg, &min, &sec);
       return eps*(deg+(min+sec/60.0)/60.0);
    } else
    if (index(str, '\'')) {
       sscanf(str, "%lf'%lf", &min, &sec);
       return eps*((min+sec/60.0)/60.0);
    } else
    if (index(str, '\"')) {
       sscanf(str, "%lf", &sec);
       return eps*(sec/3600.0);
    } else
       return eps*atof(str);
}

void decim2dms(double value, char * str)
{
    int eps, d, m, s;

    if (dms!=1) {
       sprintf(str, (dms==-1)?"%.6f":"%.3f", value); 
       return;
    }

    if (value<0) {
       value = -value; 
       eps = -1;
    } else
       eps = 1;
    value = value+1/7200.0;
    d = (int) value;
    value = 60.0 * (value - d);
    m = (int) value;
    value = 60 * (value - m);       
    s = (int) value;
    sprintf(str, "%s%d°%02d'%02d\"", (eps==1)?"":"-", d, m, s);
}

/* Is it really more secure than plain tmpnam() ?? */
void secure_tmpnam(char *name)
{
    char compl[4];
    static int order = 0;
    compl[0] = 'a' + ((order/676)%26);
    compl[1] = 'a' + ((order/26)%26);
    compl[2] = 'a' + (order%26);
    compl[3] = '\0';
    ++order;
    sprintf(name, "%s/XXXXXX", P_tmpdir);
    close(mkstemp(name));
    unlink(name);
    strcat(name, compl);
}

/* This tells us whether user should enter text or not */
int text_input_mode()
{
   return
       cmd_mode==MODE_CMD || 
      (cmd_mode==MODE_MENU && cmd_type==M_MENU_SEARCH) || 
      (cmd_mode==MODE_FILE && cmd_type>M_FILE_START && cmd_type<M_FILE_SAVE)|| 
      (cmd_mode==MODE_FILE && cmd_type==M_FILE_SAVE && line_clicked==1) || 
      (cmd_mode==MODE_HELP && cmd_type==M_HELP_EDIT) ||
      (cmd_mode==MODE_OPTION && cmd_type>M_OPTION_START) ||
      (cmd_mode==MODE_COLOR && cmd_type>M_COLOR_START);
}

/* This tells us whether user should click on a box */
int click_input_mode()
{
   return
      (cmd_mode==MODE_FILE && cmd_type==M_FILE_DATA) || 
      (cmd_mode==MODE_FILE && cmd_type==M_FILE_EXTERNAL) || 
      (cmd_mode==MODE_FILE && cmd_type==M_FILE_PRINTCFG) || 
      (cmd_mode==MODE_FILE && cmd_type==M_FILE_SAVE) || 
      (cmd_mode==MODE_MENU && cmd_type==M_MENU_SEARCH) ||
      (cmd_mode==MODE_MENU && cmd_type==M_MENU_LIST) ||
      (cmd_mode==MODE_HELP && cmd_type==M_HELP_SHORTCUTS) ||
      (cmd_mode==MODE_HELP && cmd_type==M_HELP_DOC) ||
      (cmd_mode==MODE_HELP && cmd_type==M_HELP_EXTRA) ||
      (cmd_mode==MODE_HELP && cmd_type==M_HELP_EDIT) ||
       cmd_mode==MODE_OPTION || cmd_mode==MODE_COLOR;
}

int wild_strcmp(char * string, char * needle)
{
int i, j, l;
    i = 0;
    while (string[i]!='\0' && needle[i]!='\0' && 
           string[i]==needle[i] && needle[i]!='*') ++i;
    if (needle[i]=='\0')
       return (string[i]!='\0');
    if (needle[i]!='*') 
       return 1;
    l = strlen(string+i);
    for (j=0; j<=l; j++)
       if (!wild_strcmp(string+i+j, needle+i+1)) return 0;
    return 1;
}

int string_cmp(char * string, char * needle)
{
int i, l;
char *ptr;
unsigned char c;

    l = strlen(string); 
    ptr = NULL;

    for (i=0; i<l; i++) {
       c = string[i];
       if (c<='Z') {
	 if (c>='A' && c<='Z') c += 32;
	 else
	 if (c=='-') c=' ';
	 else
	 if (c=='(') {
	    c='\0';
	    ptr = string+i+1;
	 }
         else
	 if (c==')') c='\0';
	 string[i] = c;
       } else
       if (c>=192)
	 string[i] = cvs[c-192];
    }

    if (!wild_strcmp(string, needle)) return 0;
    if (ptr && !wild_strcmp(ptr, needle)) return 0;
    return 1;
}

/* 
 *  SECTION 1 : LOW LEVEL X11 ROUTINES
 */

/* Read primary selection buffer (Copy/Paste X Buffer) */

char * read_primary()
{
	Atom actual_type;
	int actual_format;
	long nitem, bytes_after, nread;
	unsigned char *data;
	char *outdata;

	nread = 0;
	outdata = malloc(2);
	*outdata = '\0';
	/* X-selection paste loop */
	do {
                /* get remaining selection max 1024 chars */
		if (XGetWindowProperty		
			(dpy, DefaultRootWindow(dpy), XA_CUT_BUFFER0, 
                         nread / 4, 1024, False,
			 AnyPropertyType, &actual_type, &actual_format, &nitem,
			 &bytes_after, (unsigned char **) &data)
			!= Success)
			return(0);
		/* paste last batch one char at a time */
		nread += nitem;
                outdata = realloc(outdata, (nread+2) * sizeof(char));
		strcat(outdata, data);
		XFree(data);
	} while (bytes_after > 0);
	return(outdata);
}

/* Write primary selection buffer (Copy/Paste X Buffer) */

void write_primary(char *text)
{
        XChangeProperty(dpy, DefaultRootWindow(dpy), XA_CUT_BUFFER0,
                      XA_STRING, 8, PropModeReplace, text,
                      strlen(text));
}

void get_color(char* c, ImageLayout * scene, int i) {
        XColor color, exact;
        Colormap ncmap;
	Colordata *colors;
        unsigned char r, g, b;
        int bool = 0;
        
	if (!c) return;
	colors = &scene->color[i];
	if (*c == '+') {
	   colors->bool = ON;
	   bool = 1;
	   ++c;
	}
	if (*c == '-') {
	   colors->bool = OFF;
	   bool = 1;
	   ++c;
	}
	if (!(*c)) return;

  	if (color_depth <= 8)
           ncmap = XCreateColormap(dpy, Root, visual, AllocNone);
	else
	   ncmap = cmap;

	if (ncmap) {
	   XAllocNamedColor(dpy, ncmap, c, &color, &exact);
   	   colors->r = exact.red;
   	   colors->g = exact.green;
   	   colors->b = exact.blue;
	   if (color_depth <= 8) {
 	      r = exact.red >> 8;
 	      g = exact.green >> 8;
 	      b = exact.blue >> 8;
              if (XAllocColor(dpy, cmap, &exact))
 		 colors->pix = exact.pixel;
	      else
                 colors->pix = 
                    color_table[(((6*g)>>8)*36)+(((6*r)>>8)*6)+((6*b)>>8)];
	   } else
              colors->pix = exact.pixel;
   	   if (reverse && i<C_FG_TEXT) {
              color.red = 65535 - exact.red;
              color.green = 65535 - exact.green;
              color.blue = 65535 - exact.blue;
	      if (color_depth <= 8) {
 	         r = color.red >> 8;
 	         g = color.green >> 8;
 	         b = color.blue >> 8;
                 if (XAllocColor(dpy, cmap, &color))
 		    colors->pix = color.pixel;
	         else
                    colors->pix =
                       color_table[(((6*g)>>8)*36)+(((6*r)>>8)*6)+((6*b)>>8)];
	      } else {
                 XAllocColor(dpy, cmap, &color);
                 colors->pix = color.pixel;
	      }
   	   }
	}
   	if (color_depth <= 8)
           XFreeColormap(dpy, ncmap);

	strncpy(colors->name, c, 39);
        colors->name[39] = '\0';
}

void set_bg_fg(ImageLayout * scene)
{
	if (gc) {
           XSetBackground(dpy, gc, scene->color[C_BG_TEXT].pix);
           XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix);
	}
}

void get_all_colors(ImageLayout * scene)
{
        int i, j, r, g, b;
        XColor color;

	if (color_depth<=8) {
	   if (cmap) XFreeColormap(dpy, cmap);
	   cmap = XCreateColormap(dpy, Root, visual, AllocNone);
	   /* first create color cube 6 x 6 x 6 */
	   for (i=0; i<216; i++) {
	      r = (i / 6) % 6;
	      g = i / 36;
	      b = i % 6;
	      color.red = r * 51 * 257;
	      color.green = g * 51 * 257;
	      color.blue = b * 51 * 257;
	      XAllocColor(dpy, cmap, &color);
	      color_table[i] = color.pixel;
	   }
	}

        /* complete other colors, starting with special menu colors 
           (just for the case of pseudo-colors being handled adequately) */
	for (j=0; j<C_ENDCOLOR; j++) {
	   i = (j+C_BG_MAP) % C_ENDCOLOR;
	   if (scene->color[i].bool != INACTIVE) {
	      if (i>=C_FG_TEXT) scene->color[i].bool = 1;
	      get_color(scene->color[i].name, scene, i);
	   }
	}

	if (color_depth<=8) {
           if (mainwin) XSetWindowColormap(dpy, mainwin, cmap);
           if (datawin) XSetWindowColormap(dpy, datawin, cmap);
           if (cmdwin) XSetWindowColormap(dpy, cmdwin, cmap);
           if (explwin) XSetWindowColormap(dpy, explwin, cmap);
           if (flagwin) XSetWindowColormap(dpy, flagwin, cmap);
	}

	set_bg_fg(scene);
}

int get_window_placement(Window win, int *x, int *y, 
			 unsigned int *w, unsigned int *h)
{
   unsigned int b, d;
   Window root, junk; 

   XFlush(dpy);
   XGetGeometry(dpy, win, &root, x, y, w, h, &b, &d);
   XTranslateCoordinates(dpy, win, RootWindow(dpy, scr), 0, 0, x, y, &junk);
   return 1;
}

void draw_separator(ImageLayout *scene, int x, int position)
{
int y;

    y = (position-TOP)*(fonth[0]+16);
    XClearArea(dpy, cmdwin, x, y, 3, fonth[0]+6, False);
}

void draw_tick(ImageLayout *scene, int mode, int num, int position)
{
int i, a, d, x1, x2, y, spacing = 0;
char *str = "";

        if (num<=0) return;
	y = (position-TOP)*(fonth[0]+16)+fonth[0]+6;

        if (mode==MODE_MENU) {
           str = labels_generalmenu;
           spacing = spacing_generalmenu;
	}
        if (mode==MODE_OPTION) {
           str = labels_optionmenu;
           spacing = spacing_optionmenu;
	}
        if (mode==MODE_COLOR) {
           str = labels_colormenu;
           spacing = spacing_colormenu;
	}
        if (mode==MODE_HELP) {
           str = labels_helpmenu;
           spacing = spacing_helpmenu;
	}
        if (mode==MODE_FILE) {
           str = labels_filemenu;
           spacing = spacing_filemenu;
	}

        x1 = XTextWidth(xfont[0], str, spacing*(num-1)-1);
        x2 = XTextWidth(xfont[0], str, spacing*num-1);

        XClearArea(dpy, cmdwin, 0, y, cmdwin_width, cmdwin_height-y, False);

        XSetForeground(dpy, gc, scene->color[C_FG_TICKS].pix);
	a = (x1+x2+4)/2;
	++y;
	for (i=0; i<=7; i++) {
	   d = 3-i/2;
	   XDrawLine(dpy, cmdwin, gc, a-d, y+i, a+d, y+i);
	}
}

void draw_win_string(ImageLayout *scene, Window win, char *s, int position)
{
        int i, y0=0, yt=0, tw, width, height;

        if (win==mainwin) {
	   width = scene->width;
	   height = scene->height;
	} else {
	   width = cmdwin_width;
	   height = cmdwin_height;
	}
        if (position<BOTTOM/2) {
	   yt = (position-TOP)*(fonth[0]+16);
	   y0 = yt + fontasc[0] + 2;
	} else {
	   yt = height - (BOTTOM-position)*(fonth[0]+4);
	   y0 = yt - xfont[0]->max_bounds.descent - 4;
	   yt = yt - fonth[0] - 6;
	}
        XSetForeground(dpy, gc, scene->color[C_BG_TEXT].pix);
        XFillRectangle(dpy, win, gc, 0, yt, width, fonth[0]+6);
        XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix);
        XDrawImageString(dpy, win, gc, 4, y0, s, strlen(s));
	if (text_input_mode() && position==BOTTOM) {
	   tw = XTextWidth(xfont[0], s, caret_pos);
           XSetForeground(dpy, gc, scene->color[C_FG_CARET].pix);
           XFillRectangle(dpy, win, gc, tw+4, yt+fonth[0]+3, char_width, 2);
	}

	if (win==cmdwin && position==TOP) {
           XSetForeground(dpy, gc, scene->color[C_BG_ESCAPE].pix);
           XFillRectangle(dpy, win, gc, width-3*action_width, 0, 
                                    3*action_width, fonth[0]+6);

	   for (i=ACTIVATE; i<=QUIT; i++) {
	      draw_separator(scene, width-(3-i)*action_width, TOP);
              XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix);
	      XDrawString(dpy, win, gc, 
                   width-(3-i)*action_width+8, fontasc[0]+2,
                   msg[i], strlen(msg[i]));
	   }
	}
	XFlush(dpy);
	text_shown = 1;
}

void show_title(ImageLayout * scene, Window win)
{
        char title[120];

	if (!win) return;

	if (win==mainwin)
	   sprintf(title, "%s / %s %s", 
               PACKAGE, wintitle_descr[0], projtype[scene->projection]);

	if (win==datawin)
	   sprintf(title, "%s / %s", PACKAGE, wintitle_descr[1]);

	if (win==cmdwin)
	   sprintf(title, "%s / %s", PACKAGE, wintitle_descr[2]);

	if (win==explwin)
	   sprintf(title, "%s / %s", PACKAGE, wintitle_descr[3]);

	if (win==flagwin)
	   sprintf(title, "%s / %s", PACKAGE, wintitle_descr[4]);

        XStoreName(dpy, win, title);
}

void set_font_params(int which)
{
int i, w;
        if (which<0 || which>5) return;
	fontasc[which] = xfont[which]->max_bounds.ascent;
	fonth[which] = fontasc[which] + xfont[which]->max_bounds.descent;
	if (which==0) {
	   char_width = XTextWidth(xfont[0], "w", 1);
	   action_width = 0;
	   for (i=ACTIVATE; i<=QUIT; i++) {
	      w = XTextWidth(xfont[0], msg[i], strlen(msg[i]));
	      if (w>action_width) action_width = w;
	   }
	   action_width += 16;
	}
        cmdwin_height0 = 3*(fonth[0]+16)+17*(fonth[0]+10);
}

int set_font(char *s, int which)
{
	XFontStruct * nfont;
	nfont = XLoadQueryFont(dpy, s);
	if (nfont == (XFontStruct *)NULL) {
	   fprintf(stderr, msg[CANT_OPEN_FONT], s);
	   fprintf(stderr, "\n");
	   return 1;
	}
        if (xfont[which]) XFreeFont(dpy, xfont[which]);
	xfont[which] = nfont;
        if (which==0)
           XSetFont(dpy, gc, nfont->fid);
	set_font_params(which);
	setup_change |= FONT_CHANGE;
	return 0;
}

void image_init(ImageLayout *scene) {
	char str[256], compl[128], lat[40], lon[40];

	XFlush(dpy);
	usleep(10000);

	if (scene->projection==SPHERICAL) 
           *compl = '\0';
	else
	   sprintf(compl, "aspect %.2f, ", scene->aspect);

	decim2dms(scene->gopt.xrot, lat);
	decim2dms(scene->gopt.yrot, lon);
	sprintf(str, "%s %dx%d (%s %s, "
                    "zoom %.2f, %slat %s, lon %s, inc %.2f) ...",
                msg[BUILDING_MAP], scene->width, scene->height, 
		msg[PROJECTION_TYPE], projtype[scene->projection], 
                scene->gopt.zoom, compl, lat, lon, scene->gopt.zrot);
        if (!start_menu) draw_win_string(scene, mainwin, str, TOP);

	if (scene->pixmap) XFreePixmap(dpy, scene->pixmap);
	scene->pixmap = 
           XCreatePixmap(dpy, mainwin, 
                         scene->width, scene->height, color_depth);

	if (scene->prepixmap) XFreePixmap(dpy, scene->prepixmap);
	scene->prepixmap = 
           XCreatePixmap(dpy, mainwin, 
                         scene->width, scene->height, color_depth);
	XFlush(dpy);
	usleep(10000);
}

void create_GCs(ImageLayout *s) {
        XGCValues               gcv;
        int                     mask;
        mask = GCForeground | GCBackground | GCFont;
        gcv.background = s->color[C_BG_TEXT].pix;
	gcv.foreground = s->color[C_FG_TEXT].pix;
	gcv.font = xfont[0]->fid;
        gc = XCreateGC(dpy, Root, mask, &gcv);
}

void print_string(char * s)
{
    if (out_fd) {
#ifdef ZLIB
       if (im_compress)
          gzprintf((gzFile *)out_fd, "%s", s);
       else
	  fprintf((FILE *)out_fd, "%s", s);
#else
       fprintf((FILE *)out_fd, "%s", s);
#endif
    } else
       printf("%s", s);
}

void draw_pixel(ImageLayout *s, int x, int y, Pixel pix)
{
     XSetForeground(dpy, gc, pix);
     XDrawPoint(dpy, s->pixmap, gc, x, y);     
}

void draw_pointseg(ImageLayout *s, double x, double y, Pixel pix)
{
     char line[80];
     XSetForeground(dpy, gc, pix);
     XDrawPoint(dpy, s->pixmap, gc, (int)x, (int)y);     
     if (img_output == OUT_EPS) {
        sprintf(line, "%.2f %.2f D\n", x, s->height-y-1.0);
        print_string(line);
     }
}

void reformat_string(char *dest, char *src, int mode)
{
   int j, k;
   k = 0;
   for (j=0; j<=strlen(src); j++) {
      if (src[j]=='(') {
         dest[k++] = ' ';
	 if (mode) dest[k++] = '\\';
      }
      if (mode && src[j]==')')
         dest[k++] = '\\';
      dest[k++] = src[j];
   }
}

void PixmapDrawString(ImageLayout *scene, 
                     int x, int y, int w, int h, char *str, int length)
{
        int i, j, i1, i2, skip;
	int mask, mask1, mask2;

        if (scene->ropt.smartlabels) {
	   text_drawn = 0;
	   if (!textboxes) {
	      tb_width = (scene->width+31)>>5;
	      if (textboxes) free(textboxes);
	      textboxes = (int *)
                 calloc(tb_width * scene->height, sizeof(int));
	   }
	   if (x>=scene->width) return;
	   if (x+w<=0) return;
	   if (y>=scene->height) return;
	   if (y+h<=0) return;
	   if (x<0) {
	      w = x+w;
	      x = 0;
	   }
           if (x+w>scene->width)
              w = scene->width - x;
	   if (y<0) {
	      h = y+h;
	      y = 0;
	   }
           if (y+h>scene->height)
              h = scene->height - y;
	   i1 = x>>5;
	   i2 = (x+w-1)>>5;
	   mask1 = (-1)>>(x&31);
           mask2 = (-1)<<(31-((x+w-1)&31));
	   if (i1==i2)
	      mask1 &= mask2;
	   for (j=y; j<y+h; j++) {
              mask = mask1;
	      skip = j*tb_width;
	      i = i1;
	      while (i<=i2) {
		 if (textboxes[i+skip] & mask) return;
		 if ((++i)<i2) mask = -1; else mask = mask2;
	      }
	   }
	   for (j=y; j<y+h; j++) {
              mask = mask1;
	      skip = j*tb_width;
	      i = i1;
	      while(i<=i2) {
	         textboxes[i+skip] |= mask;
		 if ((++i)<i2) mask = -1; else mask = mask2;
	      }
	   }
	}
	   
        XDrawString(dpy, scene->pixmap, gc, x, y, str, length);
        text_drawn = 1;
}

void draw_string(ImageLayout *s, ScreenPt *pt, char * text, 
		 int nfont, int pos, int space, int ind)
{
        int i, j, l, numl=0;
        int text_x, text_y, text_w;
        char *ptr1, *ptr2;
        char name[256], line[256];

	text_drawn = 0;
	if (!text || !*text) return;
        XSetFont(dpy, gc, xfont[nfont]->fid);
        XSetForeground(dpy, gc, (ind==-1)?s->currentpixel:s->color[ind].pix);
        text_x = (int)pt->coord[X];
        text_y = (int)pt->coord[Y];

	if (pos) {
           /* (i, j) mean width, height of text, possibly with sign */
	   i = 0;
	   if (pos<=3)
	      j = fontasc[nfont]-fonth[nfont]-1;
	   else
	   if (pos>=5)
	      j = fontasc[nfont]+1;
	   else
	      j = 0;
	   ptr1 = text;
	   while (ptr1) {
	      ptr2 = strstr(ptr1, "\\n");
	      if (ptr2) 
		 ++numl;
              else
                 ptr2 = ptr1+strlen(ptr1);
              l = XTextWidth(xfont[nfont], ptr1, (int)(ptr2-ptr1));
	      if (l>i) i = l;
	      if (*ptr2=='\\') {
                 ptr1 = ptr2+2;
		 if (pos<=3) j -= fonth[nfont];
	      } else
	         ptr1 = NULL;
	   }
	   if (pos==4) i += space;
	   else
	   if (pos==2 || pos==6) {
	      i = i/2;
	      if (j>0) j += space+1;
	      if (j<0) j -= space+1;
	   }
	   else {
	      /* 7/10 is approximately srqt(2)/2 ... */
              l = 7*space/10+1;
	      if (pos==1 || pos==7) i = -l-1; else i += l-1;
	      if (j>0) j += l;
	      if (j<0) j -= l;
	   }
	   text_x -= i; 
           text_y += j;
        } else
	   text_x += space+2;

        j = 0; /* used as line counter */

      redo:
	ptr1 = NULL;
	l = strlen(text);
	for (i=0; i<l-1; i++) if (text[i]=='\\' && text[i+1]=='n') {
	   text[i] = '\0';
	   ptr1 = text+i+2;
	   break;
	}

	if (s->ropt.smartlabels) {
	   text_w = XTextWidth(xfont[nfont], text, strlen(text));
           PixmapDrawString(s, text_x, text_y + j*fonth[nfont], 
	          text_w, fonth[nfont],
                  text, strlen(text));
	} else {
	   if (city_already_shown) {
              XSetForeground(dpy, gc, s->color[C_FG_MARKED].pix);
	      city_shown_box_x = text_x - 1;
	      city_shown_box_y = text_y - fontasc[nfont];
	      text_w = XTextWidth(xfont[nfont], text, strlen(text)) + 1;
	      if (text_w>city_shown_box_w) city_shown_box_w = text_w;
	      city_shown_box_h = (j+1)*fonth[nfont] + 1;
	      XDrawString(dpy, mainwin, gc,
                 text_x, text_y + j*fonth[nfont], text, strlen(text));
	   } else
	      XDrawString(dpy, s->pixmap, gc,
                 text_x, text_y + j*fonth[nfont], text, strlen(text));
           text_drawn = 1;
	}

	/* bail out if some overlapping occurred with the first lines */
	if (!text_drawn) return;

	if (img_output == OUT_EPS) {
  	   if (j==0) {
	      if (ind==-1)
	         sprintf(line, "%.4f %.4f %.4f RGB f%d\n",
	            s->red_current/65535.0, 
                    s->green_current/65535.0, 
                    s->blue_current/65535.0, 
	            nfont);
	      else
	         sprintf(line, "c%d f%d\n", ind, nfont);
 	      print_string(line);
	   }
	   reformat_string(name, text, 1);
           sprintf(line, "%.2f %.2f m (%s) %d %d %d %d SS\n", 
              pt->coord[X], s->height - pt->coord[Y] - 1, name,
              pos, space+1, j, numl);
	   print_string(line);
	}

        if (ptr1) {
           *(ptr1-2) = '\\';
	   text = ptr1;
	   ++j;
	   goto redo;
	}
}

void draw_segment(ImageLayout *s, ScreenPt a, ScreenPt b, Pixel color) 
{
        char line[256];
       
        if (abs(b.coord[X]-a.coord[X])>escape_length) {
 	   path_start = 1;
	   return;
	}
        XSetForeground(dpy, gc, color);
        XDrawLine(dpy, s->pixmap, gc, 
           (int)a.coord[X], (int)a.coord[Y], (int)b.coord[X], (int)b.coord[Y]);

	if (img_output == OUT_EPS) {
	    if (path_start) {
	       sprintf(line, "%.2f %.2f m %.2f %.2f l\n", 
		       a.coord[X], s->height-a.coord[Y]-1.0, 
		       b.coord[X], s->height-b.coord[Y]-1.0);
	    } else {
               sprintf(line, "%.2f %.2f l\n", 
                       b.coord[X], s->height-b.coord[Y]-1.0);
	    }
	    print_string(line);
	}
        path_start = 0;
}   

Window make_window (int width, int height) {
        Window w;
        black = BlackPixel(dpy, scr);
        white = WhitePixel(dpy, scr);

	w = XCreateSimpleWindow(dpy, Root,
                      10, 10,
                      width, height, 0,
                      white, black);
        XSetWindowColormap(dpy, w, cmap);

        XSelectInput(dpy, w, 
            ButtonPressMask | ButtonReleaseMask | 
            PointerMotionMask | EnterWindowMask | LeaveWindowMask | 
            KeyPressMask | KeyReleaseMask | 
            ExposureMask | StructureNotifyMask);

        wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
        wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
        XSetWMProtocols(dpy, w, &wm_delete_window, 1);
        return w;
}

void close_datawin(ImageLayout * scene)
{
   int i;
   city_found = -1;
   city_shown = 0;
   datawin_on = 0;
   get_window_placement(datawin, &datawin_x, &datawin_y, &i, &i);
   XUnmapWindow(dpy, datawin);
   XClearWindow(dpy, mainwin);
}

void close_flagwin(ImageLayout * scene)
{
   int i;
   flagwin_on = 0;
   get_window_placement(flagwin, &flagwin_x, &flagwin_y, &i, &i);
   XUnmapWindow(dpy, flagwin);
   XClearWindow(dpy, mainwin);
}

void close_cmdwin(ImageLayout * scene)
{
   int i;
   cmdwin_on = 0;
   cmd_mode = MODE_RUN;
   cmd_type = M_RUN_START;
   get_window_placement(cmdwin, &cmdwin_x, &cmdwin_y, &i, &i);
   XUnmapWindow(dpy, cmdwin);
}

Bool evpred(d, e, a)
Display *              d;
XEvent *               e;
XPointer               a;
{
   if (e->type==Expose) {
      if (e->xexpose.window==mainwin) exposed |= MAIN_WINDOW;
      if (e->xexpose.window==datawin) exposed |= DATA_WINDOW;
      if (e->xexpose.window==cmdwin)  exposed |= CMD_WINDOW;
      if (e->xexpose.window==explwin) exposed |= EXPL_WINDOW;
      if (e->xexpose.window==flagwin) exposed |= FLAG_WINDOW;            
   }
   if (e->type==ConfigureNotify) {
      if (e->xexpose.window==mainwin) notified |= MAIN_WINDOW;
      if (e->xexpose.window==datawin) notified |= DATA_WINDOW;
      if (e->xexpose.window==cmdwin)  notified |= CMD_WINDOW;
      if (e->xexpose.window==explwin) notified |= EXPL_WINDOW;
      if (e->xexpose.window==flagwin) notified |= FLAG_WINDOW;            
   }
   return (True);
}

void clear_city_shown()
{
   if (city_shown) 
      XClearArea(dpy, mainwin, city_shown_box_x, city_shown_box_y, 
                               city_shown_box_w, city_shown_box_h, False);
}

void clear_strip(ImageLayout * scene, int pos)
{
   if (pos==TOP)
      XClearArea(dpy, mainwin, 0, 0, scene->width, fonth[0]+6, False);
   if (pos==BOTTOM)
      XClearArea(dpy, mainwin, 0, scene->height-fonth[0]-6, 
                         scene->width, fonth[0]+6, False);
}

void do_caret(ImageLayout * scene, int u)
{
        int l;
        l = strlen(cmd_string);
        caret_pos = 0;
        while (caret_pos<l &&
           XTextWidth(xfont[0], cmd_string, caret_pos+1)<u-4) ++caret_pos;
	draw_win_string(scene, cmdwin, cmd_string, BOTTOM);
        XFlush(dpy);
}

void normalize_size_cmdwin() 
{
    if (cmdwin_height<=3*(fonth[0]+16)) {
       cmdwin_height = cmdwin_height0;
       XResizeWindow(dpy, cmdwin, cmdwin_width, cmdwin_height);
    }
    expert = 0;
}

void show_new_center(ImageLayout * scene, int u, int v, int wid)
{
	XSetForeground(dpy, gc, scene->color[C_FG_SELRECT].pix);
        XDrawLine(dpy, mainwin, gc, u-wid, v, u+wid, v);
        XDrawLine(dpy, mainwin, gc, u, v-wid, u, v+wid);
}

void show_area_border(ImageLayout * scene, int x, int y)
{
int i1, j1, i2, j2;

        if (x>mouse_x2) {
	   i1 = mouse_x2; i2 = x;
	} else {
	   i1 = x; i2 = mouse_x2;
	}  
        if (mouse_y2>mouse_y1) {
	   j1 = mouse_y1; j2 = mouse_y2;
	} else {
	   j1 = mouse_y2; j2 = mouse_y1;
	}  
	if (i1>0) --i1;
	if (j1>0) --j1;
        XCopyArea(dpy, scene->pixmap, mainwin, gc,
		       i1, j1, i2-i1+1, j2-j1+1, i1, j1);
        if (mouse_x2>mouse_x1) {
	   i1 = mouse_x1; i2 = mouse_x2;
	} else {
	   i1 = mouse_x2; i2 = mouse_x1;
	}  
        if (y>mouse_y2) {
	   j1 = mouse_y2; j2 = y;
	} else {
	   j1 = y; j2 = mouse_y2;
	}  
	if (i1>0) --i1;
	if (j1>0) --j1;
        XCopyArea(dpy, scene->pixmap, mainwin, gc,
		       i1, j1, i2-i1+1, j2-j1+1, i1, j1);
	i1 = (mouse_x1+mouse_x2)/2;
	j1 = (mouse_y1+mouse_y2)/2;
        XCopyArea(dpy, scene->pixmap, mainwin, gc, 
                       i1-4, j1-4, 9, 9, i1-4, j1-4);
	mouse_x2 = x;
	mouse_y2 = y;
        if (mouse_x2>mouse_x1) {
	   i1 = mouse_x1; i2 = mouse_x2;
	} else {
	   i1 = mouse_x2; i2 = mouse_x1;
	}  
        if (mouse_y2>mouse_y1) {
	   j1 = mouse_y1; j2 = mouse_y2;
	} else {
	   j1 = mouse_y2; j2 = mouse_y1;
	}  
	if (i2-i1>maxmove) maxmove = i2-i1;
	if (j2-j1>maxmove) maxmove = j2-j1;
	XSetForeground(dpy, gc, scene->color[C_FG_SELRECT].pix);
        XDrawRectangle(dpy, mainwin, gc, i1, j1, i2-i1, j2-j1);
	i1 = (mouse_x1+mouse_x2)/2;
	j1 = (mouse_y1+mouse_y2)/2;
	show_new_center(scene, i1, j1, 4);
}



/* 
 *  SECTION 2 : PARSING ROUTINES
 */

void expand_path(char *str)
{
char *ptr;
char buf[512];
   if (str[0]=='~' && str[1]=='/' && (ptr=getenv("HOME"))) {
      strcpy(buf, ptr);
      strcat(buf, str+1);
      strncpy(str, buf, 255);
      str[255] = '\0';
   }
}

void translate_string(char * str)
{
int i, l;
    l = strlen(str);
    for (i=0; i<l; i++)
       if (str[i]<'\040') str[i]='\040';
}

char * parse_item(char *str, int *num)
{
        char *ptr0, *ptr, *ptrp;
	char c;
	int i;

	if (!str) return NULL;
	if (!*str) return NULL;
	ptr0 = str;
	while (*ptr0 && isspace(*ptr0)) ++ptr0;

        ptr = index(ptr0, ',');
	if (!ptr) ptr = index(ptr0, ' ');
	if (!ptr) return NULL;
        c = *ptr;
	*ptr = '\0';
	if (*ptr0>='0' && *ptr0<='9') 
           *num = atoi(ptr0);
	else {
	   i = 0;
           if (!strncasecmp(ptr0, "int", 3)) i = 0; else
           if (!strncasecmp(ptr0, "nat", 3)) i = 3; else
	   if (!strncasecmp(ptr0, "riv", 3)) i = 5; else
	   if (!strncasecmp(ptr0, "cil", 3)) i = 16; else
	   if (!strncasecmp(ptr0, "ear", 3)) i = C_BG_MAP; else 
	   if (!strncasecmp(ptr0, "lab", 3)) i = C_CITY_CIRCLE; else 
	   if (!strncasecmp(ptr0, "mnu", 3)) i = C_FG_TEXT; else {
               *ptr = c;
	       return NULL;
	   }
	   ptrp = ptr0+3;
	   while (*ptrp>='A') ++ptrp;
	   *num = i+atoi(ptrp);
	}
        *ptr = c;
	++ptr;
	while (*ptr && isspace(*ptr)) ++ptr;
        return ptr;
}

void set_opt_color(ImageLayout * scene, char * string, int force)
{
int i;
char *ptr;
        if (!(ptr=parse_item(string, &i))) return;
	if (*ptr && i>=0 && i<C_ENDCOLOR) {
	    if (scene->color[i].bool != INACTIVE || force) {
	        if (i>=C_FG_TEXT) scene->color[i].bool = 1;
	        get_color(ptr, scene, i);
	        if (color_depth<=8)
	           get_all_colors(scene);
	    }
	}
}

void get_output_type(ImageLayout *scene) 
{
    int l;

    l = strlen(scene->outfile);
    if (l==0) {
        img_output = OUT_NONE;
	return;
    }

    if (!strcmp(scene->outfile+l-3, ".gz")) l-= 3;

    if (!strncmp(scene->outfile+l-4, ".ppm", 4))
        img_output = OUT_PPM;
    else
    if (!strncmp(scene->outfile+l-4, ".xpm", 4))
        img_output = OUT_XPM;
    else
    if (!strncmp(scene->outfile+l-4, ".eps", 4))
        img_output = OUT_EPS;
    else
    if (!strncmp(scene->outfile+l-3, ".ps", 3))
        img_output = OUT_PS;
    else
    if (!strncmp(scene->outfile+l-3, ".rc", 3))
        img_output = OUT_RC;
    else
        /* otherwise set default format = XPM */
        img_output = OUT_XPM;
}

void feature_undefine(ImageLayout *scene, int i)
{
    int j;
    if (i<0 || i>=scene->numdef) return;
    if (scene->def[i]) free(scene->def[i]);
    --scene->numdef;
    for (j=i; j<scene->numdef; j++)
       scene->def[j] = scene->def[j+1];
}

void parse_define(ImageLayout *scene, char *ptr)
{
    int i;

    if (!strncmp(ptr, "undef|", 6)) {
       feature_undefine(scene, atoi(ptr+6));
       return;
    }

    if (*ptr == '*') {
       edit_rc_output(scene);
       return;
    }

    if (!strncmp(ptr, "eraseall", 8)) {
       scene->numpoint = 0;
       if (scene->mempoint) {
          free(scene->mempoint);
	  scene->mempoint = NULL;
       }
    }

    if (!strncmp(ptr, "erase", 5)) {
       char *str;
       char needle[10];
       int i, j, l = strlen(ptr);
       if (l==5) {
          str = malloc(8);
	  if (line_clicked>=1)
	     sprintf(str, ",%d,", line_clicked+start_list-1);
	  else
	     *str = '\0';
       } else {
	  str = malloc(l-2);
	  *str = ',';
	  for (i=1; i<l-5; i++) str[i] = ptr[i+5];
	  str[l-5] = ',';
	  str[l-4] = '\0';
       }
       for (i=0; i<scene->numpoint; i++) {
	  sprintf(needle, ",%d,", i);
	  if (strstr(str, needle)) scene->mempoint[2*i] = 100.0;
       }
       j = 0;
       for (i=0; i<scene->numpoint; i++) {
          scene->mempoint[2*j] = scene->mempoint[2*i];
          scene->mempoint[2*j+1] = scene->mempoint[2*i+1];
	  if (scene->mempoint[2*i]<95.0) ++j;
       }
       scene->numpoint = j;
       free(str);
       return;
    }

    if (!strncmp(ptr, "input|", 6)) {
       char *str0, *str = NULL;
       int start = 1;
       double x, y;
       str0 = strdup(ptr+6);
       while (1) {
	  if (start) {
	     str = (char *)strtok(str0, ",");
	     start = 0;
	  } else
	     str = (char *)strtok(NULL, ",");
          if (!str) break;
	  x = dms2decim(str);
	  str = strtok(NULL, "|");
	  if (!str) break;
          y = dms2decim(str);
	  ++scene->numpoint;
          scene->mempoint = (double *) realloc(scene->mempoint,
                                  2*scene->numpoint*sizeof(double));
          scene->mempoint[2*scene->numpoint-2] = x;
          scene->mempoint[2*scene->numpoint-1] = y;
       }
       free(str0);
       return;
    }

    i = scene->numdef;
    ++scene->numdef;
    scene->def = 
       (char**)realloc(scene->def, scene->numdef*sizeof(char *));
    scene->def[i] = malloc((strlen(ptr)+2)*sizeof(char));
    if (scene->def[i]) {
       strcpy(scene->def[i]+1, ptr);
       if (!strncmp(ptr, "modif|", 6)) 
          scene->def[i][0] = (char)1;
       else
       if (!strncmp(ptr, "exec|", 5))
          scene->def[i][0] = (char)2;
       else
          scene->def[i][0] = (char)0;
    }
}

void parse_rcfile (ImageLayout *s) {
	FILE *frc = NULL;
	int i, j, pos=0, parselevel=0, numtype;
	int ret, length, line_number=0;
	char buf[512];
	char type[256];
	char item_color[256];
	char active;
	char *str, *ptr;

	/* initialize stuff */
	length = 512;
	str = (char *) malloc(length);

	/* read the color config file and allocate colors */
	if (theming)
           frc = fopen(s->theme, "r");
	else
           frc = fopen(s->rcfile, "r");

	/* if relative path && open failed try in 
	   SHAREDIR/rc/  directory  if just a plain rcfile  or in
           SHAREDIR/themes/  directory  if this is a theme */
	if (frc == NULL && s->rcfile[0]!= '/' && s->rcfile[0]!= '.') {
	   if (theming)
              sprintf(str, "%s/themes/%s", SHAREDIR, s->theme);
	   else
              sprintf(str, "%s/rc/%s", SHAREDIR, s->rcfile);
           frc = fopen(str, "r");
	}

	if (frc == NULL) {
	   sprintf(str, msg[COULDNT_OPEN_RCFILE], s->rcfile);
	   fprintf(stderr, "%s\n", str);
	   if (runlevel==0) {
	      exit(-2);
	   } else {
	      draw_win_string(s, mainwin, str, BOTTOM);
	      XFlush(dpy);
	      usleep(WARNING_TIME);
	      return;
	   }
	}
	j = 0;

	/* now parse the file */
    longline:
	while ((ret = fread(buf, 1, 510, frc)) != 0) {
		pos = (int) ftell(frc) - ret;
		for (i=0; i<ret; i++) {
		        if (j>=length-2) {
		           length += 512;
			   str = realloc(str, length);
			}
			if (buf[i] == '\n') {
		                line_number++;
				str[j] = '\0';
				fseek(frc, pos+i+1, SEEK_SET);
				break;
			}
		        str[j++] = buf[i];
		}
                if (buf[i] != '\n') {
		   if (ret<510)
		      str[j] = '\0';
                   else
		      goto longline;
		}

		/* remove comments */
		for (i=0; i<j; i++) {
			if (str[i] == '%')  {
				str[i] = '\0';
                                j = i;
				break;
			}
		} 
		
		/* remove trailing blank characters */
		while (j>0 && isspace(str[j-1])) str[--j] = '\0';

		/* don't consider blank lines */
		if (j==0) continue;

		/* remove initial blank characters */
		i = 0;
		while (str[i] && isspace(str[i])) ++i;
		if (i>0) {
		   j = i;
		   while (str[j]) {
		      str[j-i] = str[j];
                      ++j;
		   }
		   str[j-i] = '\0';
		}
                j = 0;

		if (str[0] == '<') {
		   if (!strncasecmp(str, "<colors>", 8))
		      parselevel = 0;
                   else
		   if (!strncasecmp(str, "<parameters>", 12))
		      parselevel = 1;
                   else
		   if (!strncasecmp(str, "<defines>", 9))
		      parselevel = 2;
		   continue;
		}

                if (parselevel==0) {
		   ret = sscanf(str, "%s %c%s", type, &active, item_color);
		   strcat(type, " /");
		   (void)parse_item(type, &numtype);
		   ptr = item_color;
		   if (ptr) while (*ptr && isspace(*ptr)) ++ptr;

		   if (ret != 3 || (active!='+' && active!='-')) {
			fprintf(stderr, msg[UNABLE_PARSE_STRING], 
				str, line_number, s->rcfile);	
                        fprintf(stderr, "\n");
			continue;
		   }
		   if (numtype < 0 || numtype >= C_ENDCOLOR) {
			fprintf(stderr, msg[VALUE_OUT_OF_RANGE],
			       C_ENDCOLOR-1, line_number, s->rcfile);
                        fprintf(stderr, "\n");
		   } else {
			if (active == '+')
				s->color[numtype].bool = ON;
			else
			if (active == '-')
				s->color[numtype].bool = OFF;
                  	if (s->color[numtype].bool != INACTIVE) {
				strncpy(s->color[numtype].name, ptr, 39);
				s->color[numtype].name[39] = '\0';
			}
		   }
		}

                if (parselevel==1) {
		   parse_cmd_line(s, str, " ");
		   continue;
		}

                if (parselevel==2) {
		   parse_define(s, str);
		   continue;
		}
	}
	fclose(frc);
	free(str);
}

void update_auxil_windows(ImageLayout *scene)
{
   int i;
   if (cmdwin_on)
      draw_win_cmd(scene, 0);
   if (datawin_on) {
      old_city_shown = -2;
      for (i=0; i<=1; i++) {
         if (flag_image[i]) XDestroyImage(flag_image[i]);
         flag_image[i] = NULL;
      }
      show_datawin(scene, 0);
   }
   if (flagwin_on) {
      if (big_flag_image) XDestroyImage(big_flag_image);
      big_flag_image = NULL;
      show_flagwin(scene, 0);
   }
   if (explwin_on)
      show_explwin(scene, 0, 0);
}

void set_auxil_win_background(ImageLayout * scene)
{
   if (datapix)
      XSetWindowBackgroundPixmap(dpy, datawin, datapix);
   else
      XSetWindowBackground(dpy, datawin, scene->color[C_BG_TEXT].pix);
   if (cmdpix)
      XSetWindowBackgroundPixmap(dpy, cmdwin, cmdpix);
   else
      XSetWindowBackground(dpy, cmdwin, scene->color[C_BG_CMDWIN].pix);
   XSetWindowBackground(dpy, flagwin, scene->color[C_BG_TEXT].pix);
   if (explpix)
      XSetWindowBackgroundPixmap(dpy, explwin, explpix);
   else
      XSetWindowBackground(dpy, explwin, scene->color[C_BG_CMDWIN].pix);
}

void parse_theme(ImageLayout *scene)
{
   if (scene->theme[0]) {
      theming = 1;
      parse_rcfile(scene);
      theming = 0;
      get_all_colors(scene);
      parse_pixmaps(scene, NULL);
      set_auxil_win_background(scene); 
      if (color_depth<=8) {
	 if (datawin_on) {
            XUnmapWindow(dpy, datawin);
            XMapWindow(dpy, datawin);
	 }
	 if (cmdwin_on) {
            XUnmapWindow(dpy, cmdwin);
            XMapWindow(dpy, cmdwin);
	 }
	 if (flagwin_on) {
            XUnmapWindow(dpy, flagwin);
            XMapWindow(dpy, flagwin);
	 }
	 if (explwin_on) {
            XUnmapWindow(dpy, explwin);
            XMapWindow(dpy, explwin);
	 }
         generate(scene);
         show_mark(scene);
      }
      update_auxil_windows(scene);
   }
}

int strpcmp(char *s, char *t, int n)
{
        int mode;

        if (n<0) {
	   mode = 0;
	   n = -n;
	} else
	   mode = 1;
        if (!s || !t) return -1;
	if (runlevel==0 && *s!='-' && *s!='+') return -1;

        if (*t!='+' && *t!='-') { 
           while(*s=='-') ++s; 
	}
	if (strlen(s)<n || strlen(s)>strlen(t)) return -1;
        n = strlen(s);

	if (mode) 
           return strncmp(s, t, n);
	else
           return strncasecmp(s, t, n);
}

int color_number(int mode, char * str)
{
       int i, run;
       char *endptr;

       if (!str) return -1;
       run = runlevel;
       runlevel = 1;
       if (mode) 
	  for (i = 0; i < NUM_CONTINENTS; i++) {
             if (!strpcmp(str, continent_name[i], -2)) {
	        runlevel = run;
	        return i+1;
	     }
	  }
       else
	  for (i = 0; i < NUM_ITEMS; i++) {
             if (!strpcmp(str, item_name[i], -2)) {
	        runlevel = run;
	        return i;
	     }
	  }
       runlevel = run;
       i = strtol(str, &endptr, 10);
       if (!endptr) return -1;
       return i;
}

double angle_inc(double z)
{
        double norm[] = { 1.0, 0.75, 0.5, 0.3, 0.2, 0.15 };
        double val, valn, fact;
	int i;

	if (z<=1.0) return 15.0;

	val = 15.0/z;
	valn = 10.0;
	fact = 10.0;
	i=0;
	while (valn>val) {
	   ++i;
	   if (i>5) {
	      fact *= 0.1;
	      i = 0;
	   }
	   valn = norm[i]*fact;
	}

        return valn;
}

void check_spacing(ImageLayout * scene)
{
        if (scene->ropt.spacing_lat< 1.0/scene->gopt.zoom)
	    scene->ropt.spacing_lat = angle_inc(scene->gopt.zoom);

        if (scene->ropt.spacing_lon< 1.0/scene->gopt.zoom)
	    scene->ropt.spacing_lon = angle_inc(scene->gopt.zoom);
}

void check_lineorder(ImageLayout * scene)
{
char str[6];
int busy[5];
int i, j;

    i=0;
    j=0;
    bzero(busy, sizeof(busy));

    for (i=0; i<strlen(scene->gopt.lineorder); i++) {
      if (scene->gopt.lineorder[i]>='0' && 
          scene->gopt.lineorder[i]<='4' && 
          !busy[scene->gopt.lineorder[i]-'0']) {
	 busy[scene->gopt.lineorder[i]-'0'] = 1;
	 str[j] = scene->gopt.lineorder[i];
	 ++j;
      }
    }
    str[j] = '\0';
    strcpy(scene->gopt.lineorder, str);
}

void set_radius(ImageLayout * scene) 
{

        scene->earth_radius = (double)(scene->width/2);

        if (scene->projection==SPHERICAL && scene->width>scene->height)
	   scene->earth_radius = (double)(scene->height/2);

        scene->shiftx = 0.5*scene->width;
        scene->shifty = 0.5*scene->height;
}

int set_continents(ImageLayout * scene, char *c, int mode)
{
    char * number, *ptr1, *ptr2;
    char str[256];
    int i, tot;

    if (!strcasecmp(c, "all")) {
       if (mode) 
          scene->gopt.desired_continents = 0xFFFFFFFF;
       else
          scene->gopt.desired_categories = 0xFFFFFFFF;
       return 0;
    }
    
    number = (char *) malloc(strlen(c)+2);
    ptr1 = c;
    tot = 0;

    while (ptr1 && *ptr1) {
       ptr2 = index(ptr1, ',');
       strcpy(number, ptr1);
       if (ptr2) number[ptr2-ptr1] = '\0';
       i = color_number(mode, number);
       if (i < 1 || i > 4+2*mode) {
	  sprintf(str, msg[PARAMETER_RANGE], itemtype[mode], 4+2*mode, "\n");
	  if (runlevel)
             draw_win_string(scene, cmdwin, str, BOTTOM);
	  free(number);
	  return 1;
       }
       tot |= (0x00000001 << (i-1));
       if (ptr2)
          ptr1 = ptr2+1;
       else
	  ptr1 = NULL;
    }
    if (mode) 
       scene->gopt.desired_continents = tot;
    else
       scene->gopt.desired_categories = tot;
    free(number);
    return 0;
}

void usage()
{
int i, l;

    printf("%s\n", msg[BEGIN_USAGE]);
    for (i=BEGIN_USAGE+1; i<END_USAGE; i++)
        printf("             %s\n", msg[i]);
    printf("\n");
    for (i=BEGIN_LIST_PARAMETERS; i<END_LIST_PARAMETERS; i++) {
        l = strlen(msg[i])-2;
	if (msg[i][l]=='%' && msg[i][l+1]=='d')
	   sprintf(msg[i]+l, "%d", C_ENDCOLOR-1);
        printf("  %s\n", msg[i]);
    }
}

int set_proj(char *s)
{
        int run;
	int projection;

	run = runlevel;
	runlevel = 1;
	visible = 1;
	if (!strpcmp(s, "spherical", -3))
           projection = SPHERICAL;
	else
	if (!strpcmp(s, "rectangular", -3))
	   projection = RECTANGULAR;
	else
	if (!strpcmp(s, "cylindrical", -3))
	   projection = CYLINDRICAL;
	else
	if (!strpcmp(s, "mercator", -3))
	   projection = MERCATOR;
	else
	if (!strpcmp(s, "miller", -3))
	   projection = MILLER;
	else
	if (!strpcmp(s, "sinusoidal", -3))
	   projection = SINUSOIDAL;
	else
	if (!strpcmp(s, "elliptic", -3))
	   projection = ELLIPTIC;
	else
	if (!strpcmp(s, "mollweide", -3))
	   projection = MOLLWEIDE;
	else {
           projection = atoi(s); 
           if (projection<SPHERICAL || projection>=NUMPROJ) 
              projection = SPHERICAL;
	}
	runlevel = run;
	return projection;
}

void free_countries()
{
int i;
   for (i=0; i<numcountry; i++) {
      free(countries[i]->name);
      free(countries[i]->flags);
      free(countries[i]->curr_code);
      free(countries[i]->currency);
      free(countries[i]->telephone);
      free(countries[i]->capital);
      free(countries[i]);
   }
   free(countries);
   countries = NULL;
   numcountry = 0;
}

void free_TZ()
{
int i;
   if (timezones) { 
      for (i=0; i<numtz; i++) {
         free(timezones[i]->code);
         free(timezones[i]->flags);
         free(timezones[i]->name);
         free(timezones[i]->posix);
	 free(timezones[i]);
      }
      free(timezones);
      timezones = NULL;
   }
   numtz = 0;
}

void free_locations()
{
int i;
   if (locations) {
      for (i=0; i<numloc; i++) {
         if (locations[i]->name) free(locations[i]->name);
         if (locations[i]->region) free(locations[i]->region);
	 free(locations[i]);
      }
      free(locations);
      locations = NULL;
   }
   numloc = 0;
}

void free_preselected()
{
   if (presel_pointer) free(presel_pointer);
}

void free_data_buffers(ImageLayout * scene)
{
    if (segment_index) {
       free(segment_index);
       segment_index = NULL;
    }
    if (fullmap_buffer) {
       free(fullmap_buffer);
       fullmap_buffer = NULL;
       segment_buffer = NULL;
    } else {
       free (segment_buffer);
       segment_buffer = NULL;
    }
}

void error_tz(char * sect, char * str)
{
     fprintf(stderr, "Incorrect timezone label in section <%s> : %s\n", 
                     sect, str);
}

#define BIGNUM 100000000
void reordering(char mode)
{
long int v, *value;
int i, j, k, n, step;
int *order, *rank, *minrank;

   value = malloc(numloc*sizeof(long int));
   order = malloc(numloc*sizeof(int));

   rank = malloc(numloc*sizeof(int));
   minrank = malloc(numcountry*sizeof(int));

   for (step=0; step<=2; step++) {
      bzero(value, numloc*sizeof(long int));
      bzero(order, numloc*sizeof(int));
      n = 0;
      for (i=0; i<numloc; i++) {
         if (locations[i]->obj==mode) {
	    if (i%500==0)
	       fprintf(stderr, "Step %d, %d \n", step, i);
	    if (mode=='p')
	       v = locations[i]->alt;
	    else
	       v = locations[i]->population;
	    if (step==1)
	       v += BIGNUM*timezones[locations[i]->tz]->continent;
	    else
	    if (step==2)
	       v += BIGNUM*timezones[locations[i]->tz]->country;
	    value[n] = v;
	    order[n] = i;
	    for (j=0; j<=n-1; j++) {
	       if (v>value[j]) {
	          for (k=n; k>j; k--) {
		     value[k] = value[k-1]; 
		     order[k] = order[k-1]; 
	          }
	          value[j] = v;
	          order[j] = i;
                  break;
	       }
	    }
            ++n;
         }
      }
      for (i=0; i<n; i++)
         rank[order[i]] = i;
      for (i=0; i<numcountry; i++)
         minrank[i] = numloc;

      if (step==0 && mode!='p') {
         for (i=0; i<numloc; i++)
	    if (locations[i]->obj==mode) {
	       locations[i]->worldrank = rank[i]+1;
	    }
      }

      if (step==1) {
         for (i=0; i<numloc; i++) {
            if (locations[i]->obj==mode) {
	       j = timezones[locations[i]->tz]->continent;
	       if (rank[i]<minrank[j]) minrank[j] = rank[i];
            }
         }
         for (i=0; i<numloc; i++) {
	    if (locations[i]->obj==mode) {
	       j = timezones[locations[i]->tz]->continent;
	       locations[i]->contrank = rank[i]-minrank[j]+1;
	    }
	 }
      }

      if (step==2) {
         for (i=0; i<numloc; i++) {
            if (locations[i]->obj==mode) {
	       j = timezones[locations[i]->tz]->country;
	       if (rank[i]<minrank[j]) minrank[j] = rank[i];
            }
         }
         for (i=0; i<numloc; i++) {
	    if (locations[i]->obj==mode) {
	       j = timezones[locations[i]->tz]->country;
	       locations[i]->rank = rank[i]-minrank[j]+1;
	    }
	 }
      }
   }

   free(minrank);   
   free(value);   
   free(order);
   free(rank);
}

void simplify_string(char * str)
{
    int i, j=0, l;
    l = strlen(str);
    for (i=0; i<l; i++) {
       if (str[i]=='\\') {
	  ++i;
	  if (str[i]=='n') {
	     str[j] = ' ';
	     ++j;
	  }
       } else {
	  str[j] = str[i];
	  ++j;
       }
    }
    str[j] = '\0';
}

/*
int closest_locality(double x, double y)
{
    double dist, distp;
    int i, i0;
    dist = 1.0E9;
    i0 = -1;
    for (i=0; i<numloc; i++) 
    if (locations[i]->obj=='c') {
       distp = fabs(locations[i]->lat-x)+fabs(locations[i]->lon-y);
       if (distp<dist) {
	  i0 = i;
	  dist = distp;
       }
    } else break;
    return i0;
}


              j = closest_locality(locations[numloc]->lat, locations[numloc]->lon);
	      itz = locations[j]->tz;
              printf("%s|%s|%s|%s|%s|%s\n",
  	         timezones[itz]->code, locations[j]->region,
	         field[1], field[2], field[3], field[4]);
*/
   
void parse_locfile(ImageLayout *s) {
	FILE *f;	
	char buf[512], lat_str[40], lon_str[40];
        char field[11][128];
	char *sect[] = { "", 
             "countries", "timezones", "cities", "peaks", 
             "locations", "preselected" };
        char *str, *ptr, *ptrp;
	int bool, i, j, itz=0, numfields, datatype;

	if (!s->locfile || !*s->locfile) return;

	f = fopen(s->locfile, "r");
	if (f == NULL) {
	   sprintf(buf, msg[COULDNT_OPEN_LOCFILE], s->locfile);
	   if (runlevel==0)
	      fprintf(stderr, "%s\n", buf);
	   else {
	      draw_win_string(s, cmdwin, buf, BOTTOM);
	      XFlush(dpy);
	      usleep(WARNING_TIME);
	   }
	   return;
	}

	numfields = 0;
	datatype = T_NONE;
        while((str=fgets(buf, 510, f))) {
	   while (*str && isspace(*str)) ++str;
	   if (!*str || *str=='%') continue;
	   if (*str=='<') {
	      if (!strncmp(str, "<reset_countries>", 17)) {
                 free_countries();
	         continue;
	      }
	      if (!strncmp(str, "<reset_TZ>", 10)) {
                 free_TZ();
	         continue;
	      }
	      if (!strncmp(str, "<reset_locations>", 17)) {
                 free_locations();
	         continue;
              }
	      if (!strncmp(str, "<reset_preselected>", 19)) {
                 free_preselected();
	         continue;
              }
	      if (!strncmp(str, "<countries>", 11)) {
	         datatype = T_COUNTRIES;
	         numfields = 12;
	         continue;
	      }
	      if (!strncmp(str, "<timezones>", 11)) {
	         datatype = T_TIMEZONES;
	         numfields = 6;
	         continue;
	      }
	      if (!strncmp(str, "<cities>", 8)) {
	         datatype = T_CITIES;
	         itz = 0;
	         numfields = 11;
	         continue;
	      }
	      if (!strncmp(str, "<airports>", 10)) {
	         datatype = T_AIRPORTS;
	         itz = 0;
	         numfields = 8;
	         continue;
	      }
	      if (!strncmp(str, "<observatories>", 15)) {
	         datatype = T_OBSERVATORIES;
	         itz = 0;
	         numfields = 6;
	         continue;
	      }
	      if (!strncmp(str, "<peaks>", 7)) {
	         datatype = T_PEAKS;
	         itz = 0;
	         numfields = 9;
	         continue;
	      }
	      if (!strncmp(str, "<locations>", 11)) {
	         datatype = T_LOCATIONS;
	         numfields = 8;
	         continue;
	      }
	      if (!strncmp(str, "<preselected>", 13)) {
	         datatype = T_PRESELECTED;
	         numfields = 3;
	         continue;
	      }
	      if (datatype==T_COUNTRIES && !strncmp(str, "</countries>", 12)) {
	         datatype = T_NONE;
	         numfields = 0;
	         continue;
	      }
	      if (datatype==T_TIMEZONES && !strncmp(str, "</timezones>", 12)) {
	         datatype = T_NONE;
	         numfields = 0;
	         continue;
	      }
	      if (datatype==T_CITIES && !strncmp(str, "</cities>", 9)) {
	         datatype = T_NONE;
	         numfields = 0;
	         continue;
	      }
	      if (datatype==T_AIRPORTS && !strncmp(str, "</airports>", 11)) {
	         datatype = T_NONE;
	         numfields = 0;
	         continue;
	      }
	      if (datatype==T_OBSERVATORIES && 
                  !strncmp(str, "</observatories>", 16)) {
	         datatype = T_NONE;
	         numfields = 0;
	         continue;
	      }
	      if (datatype==T_PEAKS && !strncmp(str, "</peaks>", 8)) {
	         datatype = T_NONE;
	         numfields = 0;
	         continue;
	      }
	      if (datatype==T_LOCATIONS && !strncmp(str, "</locations>", 12)) {
	         datatype = T_NONE;
	         numfields = 0;
	         continue;
	      }
	      if (datatype==T_PRESELECTED && 
                  !strncmp(str, "</preselected>", 14)) {
	         datatype = T_NONE;
	         numfields = 0;
	         continue;
	      }
	   }
           bool = 0;
           for (i=0; i<numfields; i++) {
              while (*str && isspace(*str)) ++str;
	      ptr = str;
              while (*ptr && *ptr!='|') ++ptr;
	      if (!*ptr && i<numfields-1) bool=1;
              *ptr = '\0';
              ptrp = ptr+1;
	      --ptr;
              while(isspace(*ptr)) { *ptr = '\0'; --ptr; }
              strcpy(field[i], str);
	      str = ptrp;
           }
           if (bool) {
              fprintf(stderr, msg[FIELD_MISSING], field[0], sect[datatype]);
              fprintf(stderr, "\n");
	      continue;
	   }
	   if (datatype==T_COUNTRIES) {
	      i = (field[0][0]-'A')*26+(field[0][1]-'A');
              country_table[i] = numcountry;
	      countries = realloc(countries,
                                    (numcountry+1)*sizeof(Country *));
	      countries[numcountry] = malloc(sizeof(Country));
	      strcpy(countries[numcountry]->code2, field[0]);
	      strcpy(countries[numcountry]->code3, field[1]);
	      strcpy(countries[numcountry]->cia, field[4]);
	      strcpy(countries[numcountry]->iana, field[5]);
	      countries[numcountry]->name = strdup(field[2]);
	      countries[numcountry]->flags = strdup(field[3]);
	      countries[numcountry]->curr_code = strdup(field[6]);
	      countries[numcountry]->currency = strdup(field[7]);
	      countries[numcountry]->telephone = strdup(field[8]);
	      countries[numcountry]->capital = strdup(field[9]);
	      countries[numcountry]->area = atoi(field[10]);
	      countries[numcountry]->population = atoi(field[11]);
#ifdef DEBUG
	      fprintf(stderr, "%d : %s\n", numcountry, 
                                           countries[numcountry]->name);
#endif
	      ++numcountry;
	   }
           else
	   if (datatype==T_TIMEZONES) {
              timezones = (Timezone **)
                  realloc(timezones, (numtz+1)*sizeof(Timezone *));
	      timezones[numtz] = malloc(sizeof(Timezone));
	      timezones[numtz]->code = strdup(field[0]);
              i = (field[1][0]-'A')*26+(field[1][1]-'A');
	      timezones[numtz]->country = country_table[i];
	      timezones[numtz]->flags = strdup(field[3]);
	      timezones[numtz]->name = strdup(field[4]);
	      timezones[numtz]->posix = strdup(field[5]);
	      for (i=0; i<=5; i++) {
	          if (!strcasecmp(field[2], continent[i])) {
		     timezones[numtz]->continent = i;
		     break;
		  }
	      }
	      ++numtz;
	   }
	   else
           if (datatype==T_CITIES) {
              locations = (Location **)
                  realloc(locations, (numloc+1)*sizeof(Location *));
	      locations[numloc] = malloc(sizeof(Location));
	      locations[numloc]->obj = 'c';
	      locations[numloc]->draw = 0;
	      locations[numloc]->name = strdup(field[1]);
	      locations[numloc]->status = field[2][0];
	      locations[numloc]->region = strdup(field[3]);
	      locations[numloc]->population = atoi(field[4]);
	      locations[numloc]->rank = atoi(field[5]);
	      locations[numloc]->contrank = atoi(field[6]);
	      locations[numloc]->worldrank = atoi(field[7]);
	      locations[numloc]->lat = dms2decim(field[8]);
	      locations[numloc]->lon = dms2decim(field[9]);
	      if (index(field[10],'?'))
                 locations[numloc]->alt = -30000;
	      else
	         locations[numloc]->alt = round2int(atof(field[10]));
	      locations[numloc]->tz = -1;
	      bool = 1;
              for (i=0; i<numtz; i++) {
                 j = (i+itz)%numtz;
		 if (!strcmp(field[0], timezones[j]->code)) {
		    locations[numloc]->tz = j;
		    itz = j;
		    bool = 0;
                    break;
		 }
	      }
	      if (bool) error_tz("locations", field[0]);
	      ++numloc;
	   }
	   else
           if (datatype==T_AIRPORTS) {
              locations = (Location **)
                  realloc(locations, (numloc+1)*sizeof(Location *));
	      locations[numloc] = malloc(sizeof(Location));
	      locations[numloc]->obj = 'a';
	      locations[numloc]->draw = 0;
	      locations[numloc]->status = '*';
	      locations[numloc]->tz = -1;
              bool = 1;
              for (i=0; i<numtz; i++) {
                 j = (i+itz)%numtz;
		 if (!strcmp(field[0], timezones[j]->code)) {
		    locations[numloc]->tz = j;
		    itz = j;
		    bool = 0;
                    break;
		 }
	      }
	      if (bool) error_tz("airports", field[0]);
	      locations[numloc]->name = strdup(field[1]);
	      locations[numloc]->region = strdup(field[2]);
	      locations[numloc]->rank = atoi(field[3]);
	      locations[numloc]->population = atoi(field[4]);
	      locations[numloc]->lat = dms2decim(field[5]);
	      locations[numloc]->lon = dms2decim(field[6]);
	      locations[numloc]->alt = atoi(field[7]);
	      ++numloc;
	   }
	   else
           if (datatype==T_OBSERVATORIES) {
              locations = (Location **)
                  realloc(locations, (numloc+1)*sizeof(Location *));
	      locations[numloc] = malloc(sizeof(Location));
	      locations[numloc]->obj = 'b';
	      locations[numloc]->draw = 0;
	      locations[numloc]->status = '*';
	      locations[numloc]->tz = -1;
              bool = 1;
              for (i=0; i<numtz; i++) {
                 j = (i+itz)%numtz;
		 if (!strcmp(field[0], timezones[j]->code)) {
		    locations[numloc]->tz = j;
		    itz = j;
		    bool = 0;
                    break;
		 }
	      }
	      if (bool) error_tz("observatories", field[0]);
	      locations[numloc]->name = strdup(field[1]);
	      locations[numloc]->region = strdup(field[2]);
	      locations[numloc]->lat = dms2decim(field[3]);
	      locations[numloc]->lon = dms2decim(field[4]);
	      locations[numloc]->alt = atoi(field[5]);
	      ++numloc;
	   }
	   else
           if (datatype==T_PEAKS) {
              locations = (Location **)
                  realloc(locations, (numloc+1)*sizeof(Location *));
	      locations[numloc] = malloc(sizeof(Location));
	      locations[numloc]->obj = 'p';
	      locations[numloc]->draw = 0;
	      locations[numloc]->status = '*';
	      locations[numloc]->tz = -1;
              bool = 1;
              for (i=0; i<numtz; i++) {
                 j = (i+itz)%numtz;
		 if (!strcmp(field[0], timezones[j]->code)) {
		    locations[numloc]->tz = j;
		    itz = j;
		    bool = 0;
                    break;
		 }
	      }
	      if (bool) error_tz("peaks", field[0]);
	      locations[numloc]->name = strdup(field[1]);
	      locations[numloc]->region = strdup(field[2]);
	      locations[numloc]->rank = atoi(field[3]);
	      locations[numloc]->contrank = atoi(field[4]);
	      locations[numloc]->worldrank = atoi(field[5]);
	      locations[numloc]->lat = dms2decim(field[6]);
	      locations[numloc]->lon = dms2decim(field[7]);
	      locations[numloc]->alt = atoi(field[8]);
	      ++numloc;
	   }
	   else
           if (datatype==T_LOCATIONS) {
              locations = (Location **)
                  realloc(locations, (numloc+1)*sizeof(Location *));
	      locations[numloc] = malloc(sizeof(Location));
	      locations[numloc]->obj = 'l';
	      locations[numloc]->draw = 0;
	      locations[numloc]->name = strdup(field[0]);
	      locations[numloc]->status = field[3][0];
	      locations[numloc]->population = atoi(field[4]);
	      locations[numloc]->region = NULL;
	      locations[numloc]->alt = (int)(field[5][1]-'0');
	      locations[numloc]->lat = dms2decim(field[6]);
	      locations[numloc]->lon = dms2decim(field[7]);
	      locations[numloc]->contrank = 0;
	      locations[numloc]->worldrank = 0;
              if (strcmp(field[1],"-")) {
                 i = (field[1][0]-'A')*26+(field[1][1]-'A');
		 locations[numloc]->rank = country_table[i]; 
	      } else
	         locations[numloc]->rank = -1;
              locations[numloc]->tz = -1;
	      for (i=0; i<=5; i++) {
	          if (!strcasecmp(field[2], continent[i])) {
		     locations[numloc]->tz = i;
		     break;
		  }
	      }
	      ++numloc;
	   }
	   else
           if (datatype==T_PRESELECTED) {
	      char c;
	      double lat, lon;
              for (i=0; i<strlen(field[0]); i++) {
                 c = field[0][i];
	         if (c=='-') c=' ';
	         if (c>='A' && c<='Z') c += 32;
		 if (c>=(char)192) c=cvs[c-192];
	         field[0][i] = c;
	      }
	      lat = dms2decim(field[1]);
	      lon = dms2decim(field[2]);
	      for (i=0; i<numloc; i++) {
		 if (fabs(locations[i]->lat-lat)>0.01) continue;
		 if (fabs(locations[i]->lon-lon)>0.01) continue;
		 strcpy(field[3], locations[i]->name);
		 if (locations[i]->obj!='c') simplify_string(field[3]);
                 if (string_cmp(field[3], field[0])) {
                    presel_pointer = (int *)
                       realloc(presel_pointer, (numpresel+1)*sizeof(int));
	            presel_pointer[numpresel] = i;
                    ++numpresel;
		    break;
		 }
	      }
	   }
	}
	      
	fclose(f);

	if (ranking) {
	   char alt[20];
	   reordering((char)ranking);
	   for (i=0; i<numloc; i++) {
	      if (locations[i]->alt<=-30000)
		 strcpy(alt, "?");
	      else
		 sprintf(alt, "%d", locations[i]->alt);
	      decim2dms(locations[i]->lat, lat_str);
	      decim2dms(locations[i]->lon, lon_str);
	      if (locations[i]->obj=='c' && ranking==(int)'c')
		 printf("%s|%s|%c|%s|%d|%d|%d|%d|%s|%s|%s\n",
		    timezones[locations[i]->tz]->code,
		    locations[i]->name,
		    locations[i]->status,
		    locations[i]->region,
		    locations[i]->population,
		    locations[i]->rank,
		    locations[i]->contrank,
		    locations[i]->worldrank,
		    lat_str, lon_str,
		    alt);
	      else
	      if (locations[i]->obj=='p' && ranking==(int)'p')
		 printf("%s|%s|%s|%d|%d|%d|%s|%s|%d\n",
		    timezones[locations[i]->tz]->code,
		    locations[i]->name,
		    locations[i]->region,
		    locations[i]->rank,
		    locations[i]->contrank,
		    locations[i]->worldrank,
		    lat_str, lon_str,
		    locations[i]->alt);
	      else
	      if (locations[i]->obj=='l' && ranking==(int)'l')
		 printf("%s|%s|%c|%d|p%d|%s|%s\n",
		    locations[i]->name,
		    continent[locations[i]->tz],
		    locations[i]->status,
		    locations[i]->population,
		    locations[i]->rank,
		    lat_str, lon_str);
	   }
	}
}

void read_i18n_file(ImageLayout * scene)
{
FILE *fd;
char *ptr;
char buf[512];
char i18n_file[256];
int i, j, l, n;
 
    if (!*language) {
       if (getenv("LANG")) {
          strncpy(language, getenv("LANG"), 2);
	  language[2] = '\0';
       } else
          strcpy(language, "en"); 
    }
    sprintf(i18n_file, "%s/xrmap_msg.%s", I18NPATH, language);

    fd = fopen(i18n_file, "r");
    if (!fd) {
       fprintf(stderr, "Couldn't find %s !!\n", i18n_file);
     retry:
       strcpy(language, "en");
       sprintf(i18n_file, "%s/xrmap_msg.en", I18NPATH);
       fprintf(stderr, "Using instead default %s\n", i18n_file);
       fd = fopen(i18n_file, "r");      
    }
    if (!fd) {
       fprintf(stderr, "Cannot open language file %s !!\n", i18n_file);
       exit(-1);
    }

    if (msg) {
       for (i=0; i<num_msg; i++) free(msg[i]);
       free(msg);
       msg = NULL;
    }

    num_msg = 0;
    setup_change |= LANG_CHANGE;
    while ((ptr = fgets(buf, 510, fd))) {
       if (!strncmp(ptr, "#END_OF_I18N_FILE", 17)) break;
       if (*ptr=='#') continue;
       msg = (char **) realloc(msg, (num_msg+1)*sizeof(char *));
       l = strlen(ptr)-1;
       if (ptr[l]=='\n') {
          ptr[l] = '\0';
	  --l;
       }
       while(l>=0 && isspace(ptr[l])) {
	  ptr[l] = '\0';
	  --l;
       }
       if (l<0) continue;
       msg[num_msg] = strdup(ptr);
       ++num_msg;
    }
    fclose(fd);
    if (num_msg<END_OF_I18N_FILE) {
       fprintf(stderr, "Language dialog file %s incomplete !!\n", i18n_file);
       if (!strstr(i18n_file, "xrmap_msg.en")) goto retry;
       exit(-1);
    }

    n = END_LABELS_GENERALMENU-BEGIN_LABELS_GENERALMENU;
    spacing_generalmenu = atoi(msg[SPACING_GENERALMENU]);
    l = n * spacing_generalmenu + 20;
    if (labels_generalmenu) free(labels_generalmenu);
    labels_generalmenu = 
       (char *)malloc((l+1) * sizeof(char));
    for (i=0; i<l; i++) labels_generalmenu[i] = ' ';
    labels_generalmenu[l] = '\0';

    for (i=0; i<n; i++) {
        ptr = msg[BEGIN_LABELS_GENERALMENU+i];
        for (j=0; j<strlen(ptr); j++)
	    labels_generalmenu[i*spacing_generalmenu+j] = ptr[j];
    }

    n = END_LABELS_FILEMENU-BEGIN_LABELS_FILEMENU;
    spacing_filemenu = atoi(msg[SPACING_FILEMENU]);
    l = n * spacing_filemenu + 20;
    if (labels_filemenu) free(labels_filemenu);
    labels_filemenu = 
       (char *)malloc((l+1) * sizeof(char));
    for (i=0; i<l; i++) labels_filemenu[i] = ' ';
    labels_filemenu[l] = '\0';

    for (i=0; i<n; i++) {
        ptr = msg[BEGIN_LABELS_FILEMENU+i];
        for (j=0; j<strlen(ptr); j++)
	    labels_filemenu[i*spacing_filemenu+j] = ptr[j];
    }

    n = END_LABELS_OPTIONMENU-BEGIN_LABELS_OPTIONMENU;
    spacing_optionmenu = atoi(msg[SPACING_OPTIONMENU]);
    l = n * spacing_optionmenu + 20;
    if (labels_optionmenu) free(labels_optionmenu);
    labels_optionmenu = 
       (char *)malloc((l+1) * sizeof(char));
    for (i=0; i<l; i++) labels_optionmenu[i] = ' ';
    labels_optionmenu[l] = '\0';

    for (i=0; i<n; i++) {
        ptr = msg[BEGIN_LABELS_OPTIONMENU+i];
        for (j=0; j<strlen(ptr); j++)
	    labels_optionmenu[i*spacing_optionmenu+j] = ptr[j];
    }

    n = END_LABELS_COLORMENU-BEGIN_LABELS_COLORMENU;
    spacing_colormenu = atoi(msg[SPACING_COLORMENU]);
    l = n * spacing_colormenu + 20;
    if (labels_colormenu) free(labels_colormenu);
    labels_colormenu = 
       (char *)malloc((l+1) * sizeof(char));
    for (i=0; i<l; i++) labels_colormenu[i] = ' ';
    labels_colormenu[l] = '\0';

    for (i=0; i<n; i++) {
        ptr = msg[BEGIN_LABELS_COLORMENU+i];
        for (j=0; j<strlen(ptr); j++)
	    labels_colormenu[i*spacing_colormenu+j] = ptr[j];
    }

    n = END_LABELS_HELPMENU-BEGIN_LABELS_HELPMENU;
    spacing_helpmenu = atoi(msg[SPACING_HELPMENU]);
    l = n * spacing_helpmenu + 20;
    if (labels_helpmenu) free(labels_helpmenu);
    labels_helpmenu = 
       (char *)malloc((l+1) * sizeof(char));
    for (i=0; i<l; i++) labels_helpmenu[i] = ' ';
    labels_helpmenu[l] = '\0';

    for (i=0; i<n; i++) {
        ptr = msg[BEGIN_LABELS_HELPMENU+i];
        for (j=0; j<strlen(ptr); j++)
	    labels_helpmenu[i*spacing_helpmenu+j] = ptr[j];
    }

    l = END_PROJTYPES - BEGIN_PROJTYPES;
    if (projtype) free(projtype);
    projtype = (char **)malloc(l*sizeof(char *));
    for (i=0; i<l; i++) projtype[i] = msg[BEGIN_PROJTYPES+i];

    l = END_ITEMTYPES - BEGIN_ITEMTYPES;
    if (itemtype) free(itemtype);
    itemtype = (char **)malloc(l*sizeof(char *));
    for (i=0; i<l; i++) itemtype[i] = msg[BEGIN_ITEMTYPES+i];

    l = END_WINTITLE_DESCRIPTION - BEGIN_WINTITLE_DESCRIPTION;
    if (wintitle_descr) free(wintitle_descr);
    wintitle_descr = (char **)malloc(l*sizeof(char *));
    for (i=0; i<l; i++) wintitle_descr[i] = msg[BEGIN_WINTITLE_DESCRIPTION+i];

    l = END_DATAFILE_DESCRIPTION - BEGIN_DATAFILE_DESCRIPTION;
    if (datafile_descr) free(datafile_descr);
    datafile_descr = (char **)malloc(l*sizeof(char *));
    for (i=0; i<l; i++) datafile_descr[i] = msg[BEGIN_DATAFILE_DESCRIPTION+i];

    l = END_EXTERNAL_DESCRIPTION - BEGIN_EXTERNAL_DESCRIPTION;
    if (external_descr) free(external_descr);
    external_descr = (char **)malloc(l*sizeof(char *));
    for (i=0; i<l; i++) external_descr[i] = msg[BEGIN_EXTERNAL_DESCRIPTION+i];

    l = END_PRINTCFG_DESCRIPTION - BEGIN_PRINTCFG_DESCRIPTION;
    if (printcfg_descr) free(printcfg_descr);
    printcfg_descr = (char **)malloc(l*sizeof(char *));
    for (i=0; i<l; i++) printcfg_descr[i] = msg[BEGIN_PRINTCFG_DESCRIPTION+i];

    l = END_SAVE_DESCRIPTION - BEGIN_SAVE_DESCRIPTION;
    if (save_descr) free(save_descr);
    save_descr = (char **)malloc(l*sizeof(char *));
    for (i=0; i<l; i++) save_descr[i] = msg[BEGIN_SAVE_DESCRIPTION+i];

    l = END_SEARCHBY_DESCRIPTION - BEGIN_SEARCHBY_DESCRIPTION;
    if (searchby_descr) free(searchby_descr);
    searchby_descr = (char **)malloc(l*sizeof(char *));
    for (i=0; i<l; i++) searchby_descr[i] = msg[BEGIN_SEARCHBY_DESCRIPTION+i];

    l = END_PARAMETER_DESCRIPTION - BEGIN_PARAMETER_DESCRIPTION;
    if (parameter_descr) free(parameter_descr);
    parameter_descr = (char **)malloc(l*sizeof(char *));
    for (i=0; i<l; i++) parameter_descr[i] = msg[BEGIN_PARAMETER_DESCRIPTION+i];

    l = END_HIERARCHY_DESCRIPTION - BEGIN_HIERARCHY_DESCRIPTION;
    if (display_descr) free(display_descr);
    display_descr = (char **)malloc(l*sizeof(char *));
    for (i=0; i<l; i++) display_descr[i] = msg[BEGIN_HIERARCHY_DESCRIPTION+i];

    l = END_FONT_DESCRIPTION - BEGIN_FONT_DESCRIPTION;
    if (font_descr) free(font_descr);
    font_descr = (char **)malloc(l*sizeof(char *));
    for (i=0; i<l; i++) font_descr[i] = msg[BEGIN_FONT_DESCRIPTION+i];

    l = END_MARKS_DESCRIPTION - BEGIN_MARKS_DESCRIPTION;
    if (marks_descr) free(marks_descr);
    marks_descr = (char **)malloc(l*sizeof(char *));
    for (i=0; i<l; i++) marks_descr[i] = msg[BEGIN_MARKS_DESCRIPTION+i];

    l = END_CONTINENT_DESCRIPTION - BEGIN_CONTINENT_DESCRIPTION;
    if (continent_descr) free(continent_descr);
    continent_descr = (char **)malloc(l*sizeof(char *));
    for (i=0; i<l; i++) continent_descr[i] = msg[BEGIN_CONTINENT_DESCRIPTION+i];

    l = END_CATEGORY_DESCRIPTION - BEGIN_CATEGORY_DESCRIPTION;
    if (category_descr) free(category_descr);
    category_descr = (char **)malloc(l*sizeof(char *));
    for (i=0; i<l; i++) category_descr[i] = msg[BEGIN_CATEGORY_DESCRIPTION+i];

    for (i=BEGIN_COLOR_DESCRIPTION; i<END_COLOR_DESCRIPTION; i++) {
       ptr = msg[i];
       ptr[2] = '\0';
       l = atoi(ptr);
       if (l>=0 && l<C_ENDCOLOR)
          scene->color[l].comment = ptr+3;
    }
}

void load_city_filter(ImageLayout * scene, char *str)
{
     char ch;
     int j, k;

     *scene->ropt.city_filter ='\0';
     k = 0;
     for (j=0;j<strlen(str);j++) {
        ch = toupper(str[j]);
        if (index(scene->ropt.city_filter, ch)) continue;
	if (index(city_filter0, ch)) {
	   scene->ropt.city_filter[k] = ch;
	   ++k;
	   scene->ropt.city_filter[k] = '\0';
	}
     }
}

void load_loc_filter(ImageLayout * scene, char *str)
{
     char ch;
     int j, k;

     *scene->ropt.loc_filter ='\0';
     k = 0;
     for (j=0;j<strlen(str);j++) {
        ch = toupper(str[j]);
        if (index(scene->ropt.loc_filter, ch)) continue;
	if (index(loc_filter0, ch)) {
	   scene->ropt.loc_filter[k] = ch;
	   ++k;
	   scene->ropt.loc_filter[k] = '\0';
	}
     }
}

char * list_languages()
{
     int i;
     char dirname[256];
     char *ptr, *str;
     struct dirent *dirent;
     DIR *dir;

     sprintf(dirname, "%s/i18n", SHAREDIR);
     dir = opendir(dirname);
     if (dir == NULL) return "";
     
     i = 0;
     str = (char *)malloc((3+i)*sizeof(char));
     str[0] = '\0';

     for (dirent = readdir(dir); dirent != NULL; dirent = readdir(dir)) {
         ptr = dirent->d_name;
	 if (!strncmp(ptr, "xrmap_msg.", 10)) {
	    ptr = ptr+10;
	    if (i!=0) {
	       str[i] = ',';
	       str[++i] = '\0';
	    }
	    i += strlen(ptr);
	    str = realloc(str, (3+i)*sizeof(char));
	    strcat(str, ptr);
	 }
     }
     closedir(dir);
     return str;
}

int set_grid_coordinates(char c)
{
    if (toupper(c) == 'T') return 1;
    if (toupper(c) == 'L') return 1;
    if (toupper(c) == 'B') return 2;
    if (toupper(c) == 'R') return 2;
    if (c == '1') return 1;
    if (c == '2') return 2;
    return 0;
}

char get_grid_coordinates(int i, int mode)
{
   if (i==0) return '0';
   if (mode==0) {
      if (i==1) return 'L';
      if (i==2) return 'R';
   }
   if (mode==1) {
      if (i==1) return 'T';
      if (i==2) return 'B';
   }
   return '?';
}

void get_button_dimensions()
{
   int x, y;
   unsigned int b, d;
   Window root; 
 
   if (butpix[0]) {
      XGetGeometry(dpy, butpix[0], &root, &x, &y, 
	           &w_buttons, &h_button, &b, &d);
      w_buttons += 1;
      h_button += 1;
      w_button = (w_buttons-4)/NUM_BUTTONS;
   } else {
      w_buttons = 172;
      w_button = 28;
      h_button = 29;
   }
}

int parse_pixmaps(ImageLayout *scene, char *str)
{
   int i, ret = 0, bool;
   char name[256];
   
   bool = runlevel && !theming;

   if (!str || !index(str, '|')) {
      if (str) {
         if (datapix_name) free(datapix_name);
         if (cmdpix_name) free(cmdpix_name);
         if (explpix_name) free(explpix_name);
         datapix_name = strdup(str);
         cmdpix_name = strdup(str);
         explpix_name = strdup(str);
      }
      if (bool) {
	if (datapix) XFreePixmap(dpy, datapix);
        datapix = xim2pix(readIMG(scene, PIXMAPPATH, datapix_name, 0, 
                          &scene->color[C_BG_TEXT]));
	if (cmdpix) XFreePixmap(dpy, cmdpix);
        cmdpix = xim2pix(readIMG(scene, PIXMAPPATH, cmdpix_name, 0,
                                 &scene->color[C_BG_TEXT]));
	if (explpix) XFreePixmap(dpy, explpix);
        explpix = xim2pix(readIMG(scene, PIXMAPPATH, explpix_name, 0,
                                  &scene->color[C_BG_TEXT]));
	ret = 1;
      }
   }

   if (str && !strncmp(str, "data|", 5)) {
      if (datapix_name) free(datapix_name);
         ret = 1;
	 datapix_name = strdup(str+5);
	 if (bool) {
	    if (datapix) XFreePixmap(dpy, datapix);
            datapix = xim2pix(readIMG(scene, PIXMAPPATH, datapix_name, 0,
                                      &scene->color[C_BG_TEXT]));
	 }
   }

   if (str && !strncmp(str, "cmd|", 4)) {
      if (cmdpix_name) free(cmdpix_name);
         ret = 1;
	 cmdpix_name = strdup(str+4);
	 if (bool) {
  	    if (cmdpix) XFreePixmap(dpy, cmdpix);
            cmdpix = xim2pix(readIMG(scene, PIXMAPPATH, cmdpix_name, 0,
                             &scene->color[C_BG_TEXT]));
	 }
   }

   if (str && !strncmp(str, "exp|", 4)) {
      if (explpix_name) free(explpix_name);
         ret = 1;
	 explpix_name = strdup(str+4);
	 if (bool) {
  	    if (explpix) XFreePixmap(dpy, explpix);
            explpix = xim2pix(readIMG(scene, PIXMAPPATH, explpix_name, 0,
                                      &scene->color[C_BG_TEXT]));
	 }
   }

   for (i=0; i<=2; i++) {
      sprintf(name, "button%d|", i);
      if (!str || !strncmp(str, name, 8)) {
	 ret = 1;
	 if (str) {
	    if (butpix_name[i]) free(butpix_name[i]);
	    butpix_name[i] = strdup(str+8);
	 }
	 if (bool) {
 	    if (butpix[i])  XFreePixmap(dpy, butpix[i]);
	    if (butpix_name[i])
              strcpy(name, butpix_name[i]);
	   else
              sprintf(name, DEFAULTBUTTONS, i);
            butpix[i] = xim2pix(readIMG(scene, PIXMAPPATH, name, 0,
                                        &scene->color[C_BG_TEXT]));
	    get_button_dimensions();
	 }
      }
   }
   if (bool && ret) {
      set_auxil_win_background(scene);
      update_auxil_windows(scene);
   }
   return ret;
}

int parse_cmd_line(ImageLayout * scene, char *str, char *sep)
{
        char *string, *ptr, *ptr_err;
	int w0, h0;

	if (!str || !*str) return -1;
	string = strdup(str);

	w0 = scene->width;
	h0 = scene->height;

	while ((ptr = (char*) strtok(string, sep)) != NULL) {
	   ptr_err = ptr;
	   string = NULL;
	   if (!runlevel && !strpcmp(ptr, "help", 1)) {
	      usage();
	      exit(0);
	   } else
	   if (!runlevel && !strpcmp(ptr, "version", 1)) {
              printf(msg[VERSION_FORMAT], 
                     PACKAGE, VERSION, DATEPKG, "\n", COPYRIGHT);
	      printf("\n");
              exit(0);
	   }
           else
	   if (!runlevel && !strpcmp(ptr, "menu", 4)) {
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
              start_menu = (int)*ptr;
	   }
           else
	   if (!strpcmp(ptr, "language", 4)) {
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
              if (strcmp(ptr, language)) {
	         strncpy(language, ptr, 2);
	         language[2] = '\0';
	         read_i18n_file(scene);
	         fix_features_description(scene);
	      }
	   }
	   else
	   if (!strpcmp(ptr, "mapfile", 4)) {
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
	      if (!strcasecmp(ptr, "default"))
                 strncpy(scene->mapfile, MAPFILE, 255);
	      else
                 strncpy(scene->mapfile, ptr, 255);
	      scene->mapfile[255] = '\0';
	      expand_path(scene->mapfile);
	      free_data_buffers(scene);
	   } 
           else 
	   if (!strpcmp(ptr, "rcfile", 3)) {
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr || (ptr && *ptr == '\0') ||
                  (ptr && !strcasecmp(ptr, "null")) ||
                  (ptr && !strcasecmp(ptr, "none")))
		 *scene->rcfile = '\0';
	      else {
	         if (!strcasecmp(ptr, "default"))
                    strncpy(scene->rcfile, RCFILE, 255);
	         else
                    strncpy(scene->rcfile, ptr, 255);
		 scene->rcfile[255] = '\0';
		 expand_path(scene->rcfile);
	    	 if (runlevel) parse_rcfile(scene);
	      }
	   } 
           else
	   if (!strpcmp(ptr, "locfile", 4)) {
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr || (ptr && *ptr == '\0') ||
                  (ptr && !strcasecmp(ptr, "null")) ||
                  (ptr && !strcasecmp(ptr, "none")))
		 *scene->locfile = '\0';
	      else {
	         if (!strcasecmp(ptr, "default"))
                    strncpy(scene->locfile, LOCFILE, 255);
	         else
                    strncpy(scene->locfile, ptr, 255);
		 scene->locfile[255] = '\0';
		 expand_path(scene->locfile);
	         parse_locfile(scene);
	      }
	   }
           else
	   if (!strpcmp(ptr, "outfile", 4)) {
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr || (ptr && *ptr == '\0') ||
                  (ptr && !strcasecmp(ptr, "null")) ||
                  (ptr && !strcasecmp(ptr, "none")))
		 *scene->outfile = '\0';
	      else {
                 strncpy(scene->outfile, ptr, 255);
		 scene->outfile[255] = '\0';
	      }
	   }
           else
	   if (!strpcmp(ptr, "psmacros", 5)) {
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr || (ptr && *ptr == '\0') ||
                  (ptr && !strcasecmp(ptr, "null")) ||
                  (ptr && !strcasecmp(ptr, "none")))
		 *scene->macrofile = '\0';
	      else {
                 strncpy(scene->macrofile, ptr, 255);
		 scene->macrofile[255] = '\0';
	      }
	   }
           else
	   if (!strpcmp(ptr, "theme", 5)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr && *ptr) {
                 strncpy(scene->theme, ptr, 255);
		 scene->theme[255] = '\0';
		 expand_path(scene->theme);
	    	 if (runlevel) parse_theme(scene);
	      }
	   } else
#ifdef SEG_SELECT
	   if (!strpcmp(ptr, "segment", 3)) {
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
              if (!strncasecmp(ptr, "mode", 4)) {
		 ptr = index(ptr, '|');
	         if (!ptr) goto error;
		 ++ptr;
		 seg_mode = atoi(ptr);
		 if (seg_mode<0 || seg_mode>3) seg_mode = 0;
	      } else
              if (!strncasecmp(ptr, "mark", 4)) {
		 ptr = index(ptr, '|');
	         if (!ptr) goto error;
		 ++ptr;
		 ++seg_nummarked;
		 seg_specified = realloc(seg_specified, 
				    seg_nummarked *  sizeof(int));
		 seg_specified[seg_nummarked-1] = atoi(ptr);
	      } else
		 goto error;
	   } else
#endif
#ifdef ARCINFO
	   if (!strpcmp(ptr, "arcinfo", 3)) {
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
              if (!strncasecmp(ptr, "precision", 9)) {
		 int i;
		 ptr = index(ptr, '|');
	         if (!ptr) goto error;
		 i = atoi(ptr+1);
		 if (i<=2) i = 2;
		 if (i>=12) i = 12;
		 arc_precision = i;
	      }
              else
              if (!strncasecmp(ptr, "search", 6))
                 arc_search = 1;
	      else
              if (!strncasecmp(ptr, "lambert", 7))
                 arc_lambert = 1;
	      else
	      if (!strncasecmp(ptr, "lat", 3)) {
                 ptr = index(ptr, '|');
	         if (!ptr) goto error;
		 ++ptr;
                 arc_lat0 = atof(ptr);
              }
	      else
	      if (!strncasecmp(ptr, "lon", 3)) {
                 ptr = index(ptr, '|');
	         if (!ptr) goto error;
		 ++ptr;
                 arc_lon0 = atof(ptr);
              }
	      else
	      if (!strncasecmp(ptr, "scale", 5)) {
                 ptr = index(ptr, '|');
	         if (!ptr) goto error;
		 ++ptr;
                 arc_scale = atof(ptr);
              }
	      else
	      if (!strncasecmp(ptr, "transl", 6)) {
                 ptr = index(ptr, '|');
	         if (!ptr) goto error;
		 ++ptr;
                 arc_transl = atof(ptr);
              }
	      else
	      if (!strncasecmp(ptr, "read", 4)) {
                 ptr = index(ptr, '|');
	         if (!ptr) goto error;
		 ++ptr;
                 arc_file = strdup(ptr);
              }
	      else goto error;
	   } else
           if (!strpcmp(ptr, "dump", 4)) {
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
              if (!strncasecmp(ptr, "split", 5)) {
                 dump_split = 1;
	      } else
              if (!strncasecmp(ptr, "jpd", 3)) {
                 dump_format = DUMP_JPD;
	      } else
              if (!strncasecmp(ptr, "ascii", 5)) {
                 dump_format = DUMP_ASCII;
	      } else
              if (!strncasecmp(ptr, "stat", 4)) {
                 dump_format = DUMP_STAT;
	      } else
              if (!strncasecmp(ptr, "silent", 6)) {
                 dump_verbose = 0;
	      } else
              if (!strncasecmp(ptr, "precision", 9)) {
		 int i;
		 ptr = index(ptr, '|');
	         if (!ptr) goto error;
		 i = atoi(ptr+1);
		 if (i<=2) i = 2;
		 if (i>=12) i = 12;
		 sprintf(dump_precision, "%%.%df %%.%df\n", i, i);
	      } else
              if (!strncasecmp(ptr, "write", 5)) {
                 ptr = index(ptr, '|');
	         if (!ptr) goto error;
		 ++ptr;
		 img_output = OUT_DUMP;
                 dump_file = strdup(ptr);
              } else
		 goto error;
	   }
	   else
#endif /* ARCINFO */
	   if (!strpcmp(ptr, "pixmap", 6)) {
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
	      if (!parse_pixmaps(scene, ptr)) goto error;
	   }
	   else
	   if (!strpcmp(ptr, "+memory", 4)) {
              use_memory = 1;
	   } 
	   else
	   if (!strpcmp(ptr, "-memory", 4)) {
              use_memory = 0;
	      if (fullmap_buffer) {
                 free(fullmap_buffer);
	         fullmap_buffer = NULL;
		 segment_buffer = NULL;
	      }
	   } 
	   else
	   if (!runlevel && !strpcmp(ptr, "ppmout", 6)) {
              img_output = OUT_PPM;
	   } 
	   else
	   if (!runlevel && !strpcmp(ptr, "xpmout", 6)) {
              img_output = OUT_XPM;
	   } 
	   else
	   if (!runlevel && !strpcmp(ptr, "epsout", 6)) {
              img_output = OUT_EPS;
	   } 
	   else
	   if (!runlevel && !strpcmp(ptr, "psout", 5)) {
              img_output = OUT_PS;
	   } 
	   else
	   if (!runlevel && !strpcmp(ptr, "rcout", 5)) {
              img_output = OUT_RC;
	   } 
	   else
	   if (!runlevel && !strpcmp(ptr, "preview", 7)) {
              ptr = (char*) strtok(NULL, sep);
              if (ptr) preview = atof(ptr); else goto error;
              if (preview<0.0) goto error;
	   } 
	   else
	   if (!strpcmp(ptr, "psviewer", 3)) {
              ptr = (char*) strtok(NULL, sep);
              if (ptr) {
		 free(ps_viewer);
		 ps_viewer = strdup(ptr);
                 translate_string(ps_viewer);
	      } else goto error;
	   } 
	   else
	   if (!strpcmp(ptr, "imviewer", 3)) {
              ptr = (char*) strtok(NULL, sep);
              if (ptr) {
		 free(im_viewer);
		 im_viewer = strdup(ptr); 
                 translate_string(im_viewer);
	      } else goto error;
	   } 
	   else
	   if (!strpcmp(ptr, "svgviewer", 3)) {
              ptr = (char*) strtok(NULL, sep);
              if (ptr) {
		 free(svg_viewer);
		 svg_viewer = strdup(ptr);
                 translate_string(svg_viewer);
	      } else goto error;
	   }
	   else
	   if (!strpcmp(ptr, "svgconvert", 3)) {
              ptr = (char*) strtok(NULL, sep);
              if (ptr) {
		 free(svg_convert);
		 svg_convert = strdup(ptr);
                 translate_string(svg_convert);
	      } else goto error;
	   }	   
	   else
	   if (!strpcmp(ptr, "htmlviewer", 3)) {
              ptr = (char*) strtok(NULL, sep);
              if (ptr) {
		 free(html_viewer);
		 html_viewer = strdup(ptr); 
                 translate_string(html_viewer);
	      } else goto error;
	   } 
	   else
	   if (!strpcmp(ptr, "printcmd", 3)) {
              ptr = (char*) strtok(NULL, sep);
              if (ptr) {
		 free(print_cmd);
		 print_cmd = strdup(ptr); 
		 translate_string(print_cmd);
	      } else goto error;
	   } 
	   else
	   if (!strpcmp(ptr, "editor", 4)) {
              ptr = (char*) strtok(NULL, sep);
              if (ptr) {
		 free(editor_cmd);
		 editor_cmd = strdup(ptr);
                 translate_string(editor_cmd);
	      } else goto error;
	   } 
	   else
	   if (!strpcmp(ptr, "musicplayer", 5)) {
              ptr = (char*) strtok(NULL, sep);
              if (ptr) {
		 free(midi_cmd);
		 midi_cmd = strdup(ptr); 
                 translate_string(editor_cmd);
	      } else goto error;
	   } 
	   else
	   if (!strpcmp(ptr, "pswidth", 3)) {
              ptr = (char*) strtok(NULL, sep);
              if (ptr) ps_width = atof(ptr); else goto error;
	      if (ps_width<=0) goto error;
	   } 
	   else
	   if (!strpcmp(ptr, "psleftmargin", 3)) {
              ptr = (char*) strtok(NULL, sep);
              if (ptr) ps_lm = atof(ptr); else goto error;
	      if (ps_lm<0) goto error;
	   } 
	   else
	   if (!strpcmp(ptr, "psbottommargin", 3)) {
              ptr = (char*) strtok(NULL, sep);
              if (ptr) ps_bm = atof(ptr); else goto error;
	      if (ps_bm<0) goto error;
	   } 
	   else
	   if (!strpcmp(ptr, "psrotate", 3)) {
              ptr = (char*) strtok(NULL, sep);
              if (ptr) ps_rot = atoi(ptr); else goto error;
	      if (ps_rot<0) ps_rot = -90;
	      if (ps_rot>0) ps_rot = 90;
	   } 
	   else
	   if (!strpcmp(ptr, "pslinewidth", 4)) {
              ptr = (char*) strtok(NULL, sep);
              if (ptr) ps_lw = atof(ptr); else goto error;
	      if (ps_lw<=0) goto error;
	   } 
	   else
	   if (!strpcmp(ptr, "psframe", 5)) {
	      ps_frame = 1;
	   } 
	   else
	   if (!strpcmp(ptr, "psnoframe", 7)) {
	      ps_frame = 0;
	   } 
	   else
	   if (!strpcmp(ptr, "pscolor", 3)) {
              ps_grayscale = 0;
	   } 
	   else
	   if (!strpcmp(ptr, "psgrayscale", 3)) {
              ps_grayscale = 1;
	   } 
	   else
	   if (!strpcmp(ptr, "-dms", 3)) {
              dms = 0;
              if (runlevel) update_auxil_windows(scene);
	   } 
	   else
	   if (!strpcmp(ptr, "+dms", 3)) {
              dms = 1;
              if (runlevel) update_auxil_windows(scene);
	   } 
	   else
	   if (!strpcmp(ptr, "longitude", 2)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr)
                 scene->gopt.yrot = dms2decim(ptr); 
              else goto error;
	   }
	   else
	   if (!strpcmp(ptr, "latitude", 2)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr)
                 scene->gopt.xrot = dms2decim(ptr); 
              else goto error;
	   }
	   else
	   if (!strpcmp(ptr, "inclination", 3)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr)
                 scene->gopt.zrot = dms2decim(ptr); 
              else goto error;
	   }
	   else
	   if (!strpcmp(ptr, "search", 4)) {
    	      ptr = (char*) strtok(NULL, sep);
	      if (ptr) {
		 if (search_string) free(search_string);
		 search_string = strdup(ptr);
	         if (runlevel) {
		    search_city(scene);
		    search_output(scene, 1);
		 }
	      }
	   } 
	   else
	   if (!strpcmp(ptr, "field", 4)) {
    	      ptr = (char*) strtok(NULL, sep);
	      if (ptr) {
		 if (!strcasecmp(ptr, "name"))
		    search_by = 1;
		 else
		 if (!strcasecmp(ptr, "country"))
		    search_by = 2;
		 else
		 if (!strcasecmp(ptr, "region"))
		    search_by = 3;
                 else
		 if (!strcasecmp(ptr, "list"))
		    search_by = 4;
		 else {
                    search_by = atoi(ptr);
		    if (search_by<1 || search_by>4) goto error;
		 }
	      } else
		 goto error;
	   }
	   else
	   if (!strpcmp(ptr, "reverse", 1)) {
    	      reverse = 1 - reverse;
	      if (runlevel) get_all_colors(scene);
	   } 
	   else
	   if (!strpcmp(ptr, "resetcolors", 3)) {
	      if (runlevel && color_depth<=8) get_all_colors(scene);
	   } 
           else
	   if (!strpcmp(ptr, "font", 2)) {
	      int num;
	      char *ptr2;
              ptr = (char*) strtok(NULL, sep);
      	      if (!ptr) goto error;
	      if (!(ptr2=index(ptr,','))) goto error;
	      *ptr2 = '\0';
              num = atoi(ptr);
	      *ptr2 = ',';
	      if (num<0 || num>5) goto error;
	      if (!runlevel || !set_font(ptr2+1, num)) {
	         strncpy(scene->ropt.font[num], ptr2+1, 255);
	         scene->ropt.font[num][255] = '\0';
              } else goto error;
	   }
	   else
	   if (!strpcmp(ptr, "width", 1)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr) scene->width = atoi(ptr); else goto error;
	      if (scene->width < 16) goto error;
	   }
	   else
	   if (!strpcmp(ptr, "height", 1)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr) scene->height = atoi(ptr); else goto error;
	      if (scene->height < 16) goto error;
	   }
	   else
	   if (!strpcmp(ptr, "color", 3)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr) set_opt_color(scene, ptr, 0); else goto error;
	      set_bg_fg(scene);
	   }
	   else
	   if (!strpcmp(ptr, "category", 3)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr) {
                 if (set_continents(scene, ptr, 0))
		    goto error;
	      }
              else 
                 goto error;
	   }
	   else
	   if (!strpcmp(ptr, "continent", 3)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr) {
		 if (set_continents(scene, ptr, 1))
		    goto error;
	      }
              else 
                 goto error;
	   }
	   else
	   if (!strpcmp(ptr, "projection", 1)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr) scene->projection = set_proj(ptr); else goto error;
              if (runlevel) show_title(scene, mainwin);
	   }
	   else
	   if (!strpcmp(ptr, "aspect", 1)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr) scene->aspect = atof(ptr); else goto error;
	      if (scene->aspect<0.01) goto error;
	   }
	   else
	   if (!strpcmp(ptr, "accuracy", 5)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr) scene->accuracy = atof(ptr); else goto error;
	      if (scene->accuracy<=0.0) goto error;
	   }
	   else
	   if (!strpcmp(ptr, "zoom", 1)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr) scene->gopt.zoom = atof(ptr); else goto error;
	      if (scene->gopt.zoom<MINZOOM) goto error;
	      if (scene->gopt.zoom>MAXZOOM) goto error;
	   }
	   else
	   if (!strpcmp(ptr, "coordinates", 4)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr && strlen(ptr)==2) {
		 scene->ropt.latcoord = set_grid_coordinates(ptr[0]);
		 scene->ropt.loncoord = set_grid_coordinates(ptr[1]);
	      } else goto error;
	   }
	   else
	   if (!strpcmp(ptr, "gslat", 4)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr) scene->ropt.spacing_lat = dms2decim(ptr); 
                 else goto error;
	      check_spacing(scene);
	   }
	   else
	   if (!strpcmp(ptr,"gslon", 4)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr) scene->ropt.spacing_lon = dms2decim(ptr); 
                 else goto error;
	      check_spacing(scene);
	   }
	   else
	   if (!strpcmp(ptr, "gspacing", 3)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr) scene->ropt.spacing_lat = dms2decim(ptr); 
                 else goto error;
	      scene->ropt.spacing_lon = scene->ropt.spacing_lat;
	      check_spacing(scene);
	   } 
	   else
	   if (!strpcmp(ptr, "lineorder", 5)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr) {
		 strncpy(scene->gopt.lineorder, ptr, 5);
		 scene->gopt.lineorder[5] = '\0';
                 check_lineorder(scene);
	      } else
		 goto error;
	   }
	   else
	   if (!strpcmp(ptr, "ranking", 4)) {
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
              ranking = (int)*ptr;
	   }
	   else
	   if (!strpcmp(ptr, "marksteps", 3)) {
	      int i, j;
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
              if ((i=sscanf(ptr, "%d,%d,%d,%d,%d",
                            &scene->ropt.mark_step[0], &scene->ropt.mark_step[1], 
                            &scene->ropt.mark_step[2], &scene->ropt.mark_step[3], 
                            &scene->ropt.mark_step[4]))<5)
		 for (j=i; j<5; j++) 
                    scene->ropt.mark_step[j] = scene->ropt.mark_step[i-1];
	   }
           else
	   if (!strpcmp(ptr, "namesteps", 3)) {
	      int i, j;
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
              if ((i=sscanf(ptr, "%d,%d,%d,%d,%d",
                            &scene->ropt.name_step[0], &scene->ropt.name_step[1], 
                            &scene->ropt.name_step[2], &scene->ropt.name_step[3], 
                            &scene->ropt.name_step[4]))<5)
		 for (j=i; j<5; j++) 
                    scene->ropt.name_step[j] = scene->ropt.name_step[i-1];
	   }                          
	   else
	   if (!strpcmp(ptr, "airportmarks", 9)) {
	      int i, j;
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
              if ((i=sscanf(ptr, "%d,%d,%d,%d,%d",
                            &scene->ropt.airport_mark[0], &scene->ropt.airport_mark[1], 
                            &scene->ropt.airport_mark[2], &scene->ropt.airport_mark[3], 
                            &scene->ropt.airport_mark[4]))<5)
		 for (j=i; j<5; j++) 
                     scene->ropt.airport_mark[j] = scene->ropt.airport_mark[i-1];
	   }                          
	   else
	   if (!strpcmp(ptr, "airportsizes", 9)) {
	      int i, j;
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
              if ((i=sscanf(ptr, "%d,%d,%d,%d,%d",
                            &scene->ropt.airport_size[0], &scene->ropt.airport_size[1], 
                            &scene->ropt.airport_size[2], &scene->ropt.airport_size[3], 
                            &scene->ropt.airport_size[4]))<5)
		 for (j=i; j<5; j++) 
                    scene->ropt.airport_size[j] = scene->ropt.airport_size[i-1];
	   }                          
	   else
	   if (!strpcmp(ptr, "peakmarks", 7)) {
	      int i, j;
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
              if ((i=sscanf(ptr, "%d,%d,%d,%d,%d",
                            &scene->ropt.peak_mark[0], &scene->ropt.peak_mark[1], 
                            &scene->ropt.peak_mark[2], &scene->ropt.peak_mark[3], 
                            &scene->ropt.peak_mark[4]))<5)
		 for (j=i; j<5; j++) 
                     scene->ropt.peak_mark[j] = scene->ropt.peak_mark[i-1];
	   }                          
	   else
	   if (!strpcmp(ptr, "peaksizes", 7)) {
	      int i, j;
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
              if ((i=sscanf(ptr, "%d,%d,%d,%d,%d",
                            &scene->ropt.peak_size[0], &scene->ropt.peak_size[1], 
                            &scene->ropt.peak_size[2], &scene->ropt.peak_size[3], 
                            &scene->ropt.peak_size[4]))<5)
		 for (j=i; j<5; j++) 
                    scene->ropt.peak_size[j] = scene->ropt.peak_size[i-1];
	   }                          
	   else
	   if (!strpcmp(ptr, "citymarks", 7)) {
	      int i, j;
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
              if ((i=sscanf(ptr, "%d,%d,%d,%d,%d",
                            &scene->ropt.city_mark[0], &scene->ropt.city_mark[1], 
                            &scene->ropt.city_mark[2], &scene->ropt.city_mark[3], 
                            &scene->ropt.city_mark[4]))<5)
		 for (j=i; j<5; j++) 
                     scene->ropt.city_mark[j] = scene->ropt.city_mark[i-1];
	   }                          
	   else
	   if (!strpcmp(ptr, "citysizes", 7)) {
	      int i, j;
              ptr = (char*) strtok(NULL, sep);
	      if (!ptr) goto error;
              if ((i=sscanf(ptr, "%d,%d,%d,%d,%d",
                            &scene->ropt.city_size[0], &scene->ropt.city_size[1], 
                            &scene->ropt.city_size[2], &scene->ropt.city_size[3], 
                            &scene->ropt.city_size[4]))<5)
		 for (j=i; j<5; j++) 
                    scene->ropt.city_size[j] = scene->ropt.city_size[i-1];
	   }                          
           else
	   if (!strpcmp(ptr, "cityfilter", 7)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr)
		 load_city_filter(scene, ptr);
              else goto error;
	   }
           else
	   if (!strpcmp(ptr, "locfilter", 6)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr)
		 load_loc_filter(scene, ptr);
              else goto error;
	   }
           else
	   if (!strpcmp(ptr, "flagtypes", 7)) {
              ptr = (char*) strtok(NULL, sep);
              if (ptr) {
		 free(flag_descr);
                 flag_descr = strdup(ptr);
		 if (set_flag_dirs()) {
		    free_flag_data();
		    list_flag_dirs();
                    goto error;
		 }
	      } else goto error;
	   }
           else
	   if (!strpcmp(ptr, "define", 3)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr)  
                 parse_define(scene, ptr);
              else goto error;
	   }
           else
	   if (!strpcmp(ptr, "undefine", 5)) {
              ptr = (char*) strtok(NULL, sep);
	      if (ptr) 
                 feature_undefine(scene, atoi(ptr));
              else goto error;
	   }
	   else
	   if (!strpcmp(ptr, "+placename", 3)) 
	      scene->ropt.placetext = 1;
           else
	   if (!strpcmp(ptr, "-placename", 3)) 
	      scene->ropt.placetext = 0;
	   else
	   if (!strpcmp(ptr, "+smartlabels", 5)) 
	      scene->ropt.smartlabels = 1;
           else
	   if (!strpcmp(ptr, "-smartlabels", 5)) 
	      scene->ropt.smartlabels = 0;
           else
	   if (!strpcmp(ptr, "+compress", 5))
	      im_compress = 1;
           else
	   if (!strpcmp(ptr, "-compress", 5))
	      im_compress = 0;
           else
	   if (!strpcmp(ptr, "-secure", 4))
	      secure = 0;
           else
	   if (!strpcmp(ptr, "+secure", 4))
	      secure = 1;
           else
	   if (!strpcmp(ptr, "+cities", 3)) {
	      scene->color[C_CITY_CIRCLE].bool = ON;
	      scene->color[C_CITY_TEXT].bool = OFF;
	   }
           else
	   if (!strpcmp(ptr, "++cities", 4)) {
	      scene->color[C_CITY_CIRCLE].bool = ON;
	      scene->color[C_CITY_TEXT].bool = ON;
	   }
	   else
	   if (!strpcmp(ptr, "-cities", 2)) {
	      scene->color[C_CITY_CIRCLE].bool = OFF;
	      scene->color[C_CITY_TEXT].bool = OFF;
	   }
	   else
	   if (!strpcmp(ptr, "+airports", 4)) {
              scene->color[C_AIRPORT_SYMBOL].bool = ON;
              scene->color[C_AIRPORT_TEXT].bool = OFF;
	   }
	   else
	   if (!strpcmp(ptr, "++airports", 5)) {
              scene->color[C_AIRPORT_SYMBOL].bool = ON;
              scene->color[C_AIRPORT_TEXT].bool = ON;
	   }
	   else
	   if (!strpcmp(ptr, "-airports", 4)) {
              scene->color[C_AIRPORT_SYMBOL].bool = OFF;
              scene->color[C_AIRPORT_TEXT].bool = OFF;
	   }
	   else
	   if (!strpcmp(ptr, "+observatories", 5)) {
              scene->color[C_OBSERV_SYMBOL].bool = ON;
              scene->color[C_OBSERV_TEXT].bool = OFF;
	   }
	   else
	   if (!strpcmp(ptr, "++observatories", 6)) {
              scene->color[C_OBSERV_SYMBOL].bool = ON;
              scene->color[C_OBSERV_TEXT].bool = ON;
	   }
	   else
	   if (!strpcmp(ptr, "-observatories", 5)) {
              scene->color[C_OBSERV_SYMBOL].bool = OFF;
              scene->color[C_OBSERV_TEXT].bool = OFF;
	   }
	   else
	   if (!strpcmp(ptr, "+peaks", 3)) {
              scene->color[C_PEAK_TRIANGLE].bool = ON;
              scene->color[C_PEAK_TEXT].bool = OFF;
	   }
	   else
	   if (!strpcmp(ptr, "++peaks", 4)) {
              scene->color[C_PEAK_TRIANGLE].bool = ON;
              scene->color[C_PEAK_TEXT].bool = ON;
	   }
	   else
	   if (!strpcmp(ptr, "-peaks", 3)) {
              scene->color[C_PEAK_TRIANGLE].bool = OFF;
              scene->color[C_PEAK_TEXT].bool = OFF;
	   }
	   else
	   if (!strpcmp(ptr, "+locations", 2)) {
              scene->color[C_LOC_LAND].bool = ON;
              scene->color[C_LOC_WATER].bool = ON;
	   } 
           else
	   if (!strpcmp(ptr, "-locations", 2)) {
              scene->color[C_LOC_LAND].bool = OFF;
              scene->color[C_LOC_WATER].bool = OFF;
	   } 
	   else
	   if (!strpcmp(ptr, "+earthcontour", 2)) 
              scene->color[C_EARTH_CONTOUR].bool = ON;
	   else
	   if (!strpcmp(ptr, "-earthcontour", 2)) 
              scene->color[C_EARTH_CONTOUR].bool = OFF;
	   else
	   if (!strpcmp(ptr, "+gridlines", 2)) {
              scene->color[C_LAT_GRID].bool = ON;
              scene->color[C_LON_GRID].bool = ON;
	   }
	   else
	   if (!strpcmp(ptr, "-gridlines", 2)) {
              scene->color[C_LAT_GRID].bool = OFF;
              scene->color[C_LON_GRID].bool = OFF;
	   }
	   else
	   if (!strpcmp(ptr, "+tropics", 5))
              scene->color[C_MAIN_LINES].bool = ON;
	   else
	   if (!strpcmp(ptr, "-tropics", 5))
              scene->color[C_MAIN_LINES].bool = OFF;
	   else
	   if (!strpcmp(ptr, "+transparency", 5)) 
              scene->gopt.transparent = ON;
	   else
	   if (!strpcmp(ptr, "-transparency", 5)) 
              scene->gopt.transparent = OFF;
	   else {
	      char *errstr;
	      ptr_err = ptr;
	      free(string);
	   error:
	      errstr = (char *)malloc(strlen(ptr_err)+100);
              sprintf(errstr, msg[INVALID_OPTION], ptr_err);
	      *cmd_string = '\0';
	      caret_pos = 0;
	      if (runlevel) {
	         draw_win_string(scene, cmdwin, errstr, BOTTOM);
	         usleep(WARNING_TIME);
	      } else
		 fprintf(stderr, "%s\n", errstr);
	      free(errstr);
	      return 1;
	   }
	}
	free(string);
	if (runlevel) {
	   if (scene->width<=0) scene->width = w0;
	   if (scene->height<=0) scene->height = h0;
	   if (scene->width!=w0 || scene->height!=h0) { 
	      set_radius(scene);
              XResizeWindow(dpy, mainwin, scene->width, scene->height);
	      XFlush(dpy);
	   }
	}
	return 0;
}

void update_positions(ImageLayout *scene, int pos)
{
     int i;
     for (i=0; i<scene->num_positions; i++) {
         if (!memcmp(&scene->position[i], 
             &scene->gopt, 4*sizeof(double))) return;
     }
     ++scene->num_positions;
     i = scene->ind_position = scene->num_positions-1;
     scene->position = (XYZPosition *)realloc(scene->position, 
                       scene->num_positions*sizeof(XYZPosition));
     memcpy(&scene->position[i].xrot, &scene->gopt, 4*sizeof(double));
     scene->position[i].loc = pos;
}

void check_datachanges(ImageLayout * scene)
{
      ImageLayout *backup;
      backup = (ImageLayout *)scene->backup;
      if (strcmp(scene->rcfile, backup->rcfile))
         parse_rcfile(scene);
      if (strcmp(scene->locfile, backup->locfile))
         parse_locfile(scene);	   
      if (strcmp(scene->mapfile, backup->mapfile))
	 free_data_buffers(scene);
}


/* 
 *  SECTION 3 : I/O & FILE ROUTINES
 */

void close_outfile()
{
    if (out_fd) {
#ifdef ZLIB
       if (im_compress) 
          gzclose((gzFile *)out_fd);
       else
#endif
          fclose((FILE *)out_fd);
    }
    out_fd = NULL;
}

void open_outfile(ImageLayout * scene)
{
        int i;
	struct stat buf;
	char str[256], strgz[256];
	char *ptr;

	if (out_fd) return;

	if (!*scene->outfile) {
	   close_outfile();
	   overwrite = -1;
	   return;
	}

        i = strlen(scene->outfile)-3;
        if (strcmp(scene->outfile+i, ".gz")) {
	   sprintf(str,"%s", scene->outfile);
	   sprintf(strgz,"%s.gz", scene->outfile);
        } else {
	   strcpy(strgz, scene->outfile);
           strcpy(str, strgz);
	   str[i-3] = '\0';
        }
        if (overwrite==0) {
	   ptr = strdup(str);
	   buf.st_mode = 0;
           stat(ptr, &buf);
	   free(ptr);
	   if (S_ISREG(buf.st_mode)) overwrite = 1;
	   ptr = strdup(strgz);
	   buf.st_mode = 0;
           stat(ptr, &buf);
	   free(ptr);
           if (S_ISREG(buf.st_mode)) overwrite = 1;
	   if (overwrite==1) return;
	}
 
        #ifdef ZLIB
	if (im_compress) {
	   out_fd = (void *)gzopen(strgz, "wb6");
	   strcpy(str, strgz);
	} else
	#endif
	   out_fd = (void *)fopen(str, "w");

	if (!out_fd) {
	   fprintf(stderr, msg[OPENING_FAILED], str);
	   fprintf(stderr, "\n");
	}
	overwrite = -1;
}

void print_PS_prolog(ImageLayout *scene)
{
   char str[1024];

   /*  Real bounding box would be 0 0 width height. Take A4 instead */
   sprintf(str, "%%!PS-Adobe-2.0 EPSF-2.0\n"
                "%%%%Creator: xrmap (version %s)\n"
                "%%%%Title: %s\n"
                "%%%%Pages: 1\n"
                "%%%%BoundingBox: 0 0 "PAGEFORMAT"\n"
                "%%%%EndComments\n"
                "%%EndProlog\n"
                "%%Page: 1 1\n", 
                VERSION, 
	        (scene->outfile && *scene->outfile)? 
                    scene->outfile: "(stdout)");
   print_string(str);
}

void print_PS_scaling(ImageLayout *scene, int mode)
{
      char str[256];
      double fact, dx, dy, fx, fy, shift_x, shift_y;
      
      *str = '\0';
      fact = ps_width*PTPERMM/((double)scene->width);
      fx = fact*(double)scene->width;
      fy = fact*(double)scene->height;
      if (ps_rot) {
	 dx = ps_bm * PTPERMM;
	 dy = ps_lm * PTPERMM;
      } else {
         dx = ps_lm * PTPERMM;
         dy = ps_bm * PTPERMM;
      }
      if (ps_rot) {
	 shift_x = fy + dy;
	 shift_y = fx + dx;
      } else {
	 shift_x = fx + dx;
	 shift_y = fy + dy;
      }
      if (mode == 0) 
	 fx = fy = fact;

      print_string("gsave\n");
      if (ps_rot>0) {
	 dy = 0.0;
	 sprintf(str, "%.3f 0 translate 90 rotate\n", shift_x);
      }
      if (ps_rot<0) {
	 dx = 0.0;
	 sprintf(str, "0 %.3f translate -90 rotate\n", shift_y);
      }
      if (*str) print_string(str);
      sprintf(str, "%.3f %.3f translate\n%.3f %.3f scale\n", dx, dy, fx, fy);
      print_string(str);

      if (mode==0) {
	 sprintf(str, "/linewidth %.2f def\n", ps_lw * fact * 1.5);
	 print_string(str);
      }
      if (mode==2) {
         sprintf(str, "%% frame\n%.4f setlinewidth\n"
                      "0 0 moveto 1 0 lineto 1 1 lineto "
                      "0 1 lineto closepath stroke\n",
		      4.0/(fabs(fx)+fabs(fy)));
	 print_string(str);
      }
}

void print_PS_image(ImageLayout *scene, XImage *ximage)
{
   char str[1024];
   int i, j, x, y, numcolors, numindex;
   Pixel p;
   XColor xc;
   unsigned char *u=NULL, *v=NULL, *w=NULL;
   int *ind = NULL;

   if (color_depth<=8) {
      ind = (int *)malloc(256*sizeof(int));
      memset(ind, 0, 256*sizeof(int));
   } else
   if (color_depth<=16) {
      ind = (int *)malloc(65536*sizeof(int));
      memset(ind, 0, 65536*sizeof(int));
   }
   numcolors = 0;
   numindex = 256;
   u = (unsigned char *) malloc(numindex*sizeof(unsigned char));
   v = (unsigned char *) malloc(numindex*sizeof(unsigned char));
   w = (unsigned char *) malloc(numindex*sizeof(unsigned char));

   sprintf(str, "/line %d string def\n"
                "%d %d 8 [ %d 0 0 %d 0 %d ]\n"
                "{currentfile line readhexstring pop}\n"
                "false 3 colorimage\n",
                3*ximage->width,
                ximage->width, ximage->height,
                ximage->width, -ximage->height,
                ximage->height);
   print_string(str);   
   i = 0;
   j = 0;
   for (y=0; y<ximage->height; y++)
   for (x=0; x<ximage->width; x++) {
      p = XGetPixel(ximage, x, y);
      if (color_depth>=24) {
         u[i] = p>>16;
         v[i] = (p>>8)&255;
         w[i] = p&255;
      } else {
	 i = ind[p];
	 if (i==0) {
	    xc.pixel = p;
	    XQueryColor(dpy, cmap, &xc);
	    i = (++numcolors);
	    if (numindex<=numcolors) {
	       numindex += 256;
	       u = (unsigned char *) 
                   realloc(u, numindex*sizeof(unsigned char));
               v = (unsigned char *) 
                   realloc(v, numindex*sizeof(unsigned char));
               w = (unsigned char *) 
                   realloc(w, numindex*sizeof(unsigned char));
	    }
	    ind[p] = i;
	    u[i] = xc.red>>8;
	    v[i] = xc.green>>8;
	    w[i] = xc.blue>>8;
         }
      }
      if (ps_grayscale) {
         unsigned char c = (unsigned char)((50*u[i]+32*v[i]+18*w[i])/100);
         i = 0;
         u[i] = v[i] = w[i] = c;
      }
      sprintf(str, "%02x%02x%02x", u[i], v[i], w[i]);
      print_string(str);   
      j += 6;
      if (j>70 || x==scene->width-1) {
         j = 0;
	 if (!out_fd) {
            fputc('\n', stdout);
	    continue;
         }
#ifdef ZLIB
         if (im_compress)
            gzputc((gzFile *)out_fd, '\n');
         else
            fputc('\n', (FILE *)out_fd);
#else
         fputc('\n', (FILE *)out_fd);
#endif
      }
   }
   if (ind) free(ind);
   free(u); free(v); free(w); 
   print_string("\n");
}

void print_PPM_image(ImageLayout *scene, XImage *ximage)
{
   char str[1024];
   int i, x, y, numcolors, numindex;
   Pixel p;
   XColor xc;
   unsigned char *u=NULL, *v=NULL, *w=NULL;
   int *ind = NULL;

   if (color_depth<=8) {
      ind = (int *)malloc(256*sizeof(int));
      memset(ind, 0, 256*sizeof(int));
   } else
   if (color_depth<=16) {
      ind = (int *)malloc(65536*sizeof(int));
      memset(ind, 0, 65536*sizeof(int));
   }
   numcolors = 0;
   numindex = 256;
   u = (unsigned char *) malloc(numindex*sizeof(unsigned char));
   v = (unsigned char *) malloc(numindex*sizeof(unsigned char));
   w = (unsigned char *) malloc(numindex*sizeof(unsigned char));

   sprintf(str, "P6\n#Creator: xrmap (version %s)\n%d %d\n%d\n",
       VERSION, scene->width, scene->height, 255);
   print_string(str);   
   i = 0;
   for (y=0; y<ximage->height; y++)
   for (x=0; x<ximage->width; x++) {
      p = XGetPixel(ximage, x, y);
      if (color_depth>=24) {
         u[i] = p>>16;
         v[i] = (p>>8)&255;
         w[i] = p&255;
      } else {
	 i = ind[p];
	 if (i==0) {
	    xc.pixel = p;
	    XQueryColor(dpy, cmap, &xc);
	    i = (++numcolors);
	    if (numindex<=numcolors) {
	       numindex += 256;
	       u = (unsigned char *) 
                   realloc(u, numindex*sizeof(unsigned char));
               v = (unsigned char *) 
                   realloc(v, numindex*sizeof(unsigned char));
               w = (unsigned char *) 
                   realloc(w, numindex*sizeof(unsigned char));
	    }
	    ind[p] = i;
	    u[i] = xc.red>>8;
	    v[i] = xc.green>>8;
	    w[i] = xc.blue>>8;
         }
      }
      if (out_fd) {
#ifdef ZLIB
	 if (im_compress) {
            gzputc((gzFile *)out_fd, u[i]);
            gzputc((gzFile *)out_fd, v[i]);
            gzputc((gzFile *)out_fd, w[i]);
         } else {
            fputc(u[i], (FILE *)out_fd);
            fputc(v[i], (FILE *)out_fd);
            fputc(w[i], (FILE *)out_fd);
	 }
#else
         fputc(u[i], (FILE *)out_fd);
         fputc(v[i], (FILE *)out_fd);
         fputc(w[i], (FILE *)out_fd);
#endif
      } else {
         fputc(u[i], stdout);
	 fputc(v[i], stdout);
	 fputc(w[i], stdout);
      }
   }
   if (ind) free(ind);
   free(u); free(v); free(w); 
}

void print_image(ImageLayout * scene)
{
   char str[1024], lat[40], lon[40];
   XImage *ximage;
   int i, j;

   ximage = XGetImage(dpy, scene->pixmap, 0, 0, 
                      scene->width, scene->height,
		      AllPlanes, ZPixmap);

   if (img_output==OUT_PPM)
      print_PPM_image(scene, ximage);

   if (img_output==OUT_XPM)
      XpmWriteFileFromImage(dpy, (*scene->outfile)?
         scene->outfile : NULL, ximage, NULL, NULL);

   if (img_output==OUT_PS) {
      print_PS_prolog(scene);
      print_PS_scaling(scene, 1+ps_frame);
      print_PS_image(scene, ximage);
      print_string("%\ngrestore\nshowpage\n%%Trailer\n");

      if (runlevel) {
#ifdef ZLIB
         if (im_compress)
            gzflush((gzFile *)out_fd, Z_FINISH);
	 else
#endif
            fflush((FILE *)out_fd);
      }
   }

   if (img_output==OUT_RC) {
      int im_compress_save = im_compress;
      im_compress = 0;
      print_string(msg[TYPE_ALT_M_FROM_EMX]);
      print_string("\n\n<colors>\n");
      for (i=0; i<C_ENDCOLOR; i++) {
	  sprintf(str, "%02d %c %s\n", i, 
		  ((scene->color[i].bool)? '+':'-'),
                  scene->color[i].name);
          print_string(str);
      }
      print_string("\n<parameters>\n");
      sprintf(str, "-projection %d -zoom %.6f\n",
	 scene->projection, scene->gopt.zoom);
      print_string(str);
      sprintf(str, 
         "-width %d -height %d -aspect %.6f -accuracy %.6f\n",
	 scene->width, scene->height, scene->aspect, scene->accuracy);
      print_string(str);
      sprintf(str, "-latitude %.6f -longitude %.6f -inclination %.6f\n",
	  scene->gopt.xrot, scene->gopt.yrot, scene->gopt.zrot);
      print_string(str);
      strcpy(str, "-category ");
      j = 10;
      for (i=1; i<=4; i++) {
	 if (scene->gopt.desired_categories & (1<<(i-1))) {
	    if (j>10) str[j++] = ',';
	    str[j++] = '0'+i;
	 }
      }
      str[j++] = '\n';
      str[j++] = '\0';
      print_string(str);
      strcpy(str, "-continent ");
      j = 11;
      for (i=1; i<=5; i++) {
	 if (scene->gopt.desired_continents & (1<<(i-1))) {
	    if (j>11) str[j++] = ',';
	    str[j++] = '0'+i;
	 }
      }
      str[j++] = '\n';
      str[j++] = '\0';
      print_string(str);
      if (scene->projection==SPHERICAL && scene->gopt.transparent)
         print_string("+transparency\n");
      if (scene->ropt.smartlabels==0)
         print_string("-smartlabels\n");
      if (scene->ropt.placetext)
         print_string("+placename\n");
      if (im_compress)
         print_string("+compress\n");
      if (secure)
         print_string("+secure\n");
      for (i=0; i<6; i++) {
	 sprintf(str, "-font %d,%s\n", i, scene->ropt.font[i]);
         print_string(str);
      }
      if (datapix) {
         sprintf(str, "-pixmap data|%s\n", datapix_name);
	 print_string(str);
      }
      if (cmdpix) {
         sprintf(str, "-pixmap cmd|%s\n", cmdpix_name);
	 print_string(str);
      }
      for (i=0; i<=2; i++) if (butpix_name[i]) {
         sprintf(str, "-pixmap button%d|%s\n", i, butpix_name[i]);
	 print_string(str);
      }
      sprintf(str, "-gslat %.6f -gslon %.6f\n",
	 scene->ropt.spacing_lat, scene->ropt.spacing_lon);
      print_string(str);
      sprintf(str, "-coordinates %c%c\n",
	      get_grid_coordinates(scene->ropt.latcoord, 0),
	      get_grid_coordinates(scene->ropt.loncoord, 1));
      print_string(str);
      sprintf(str, "%cdms\n", (dms)? '+':'-');
      print_string(str);
      sprintf(str, "-lineorder %s\n", scene->gopt.lineorder);
      print_string(str);
      sprintf(str, "-marksteps %d,%d,%d,%d,%d\n",
	 scene->ropt.mark_step[0], scene->ropt.mark_step[1], 
         scene->ropt.mark_step[2], scene->ropt.mark_step[3], 
	 scene->ropt.mark_step[4]);
      print_string(str);
      sprintf(str, "-namesteps %d,%d,%d,%d,%d\n",
	 scene->ropt.name_step[0], scene->ropt.name_step[1], 
         scene->ropt.name_step[2], scene->ropt.name_step[3], 
	 scene->ropt.name_step[4]);
      print_string(str);
      sprintf(str, "-citymarks %d,%d,%d,%d,%d\n",
	 scene->ropt.city_mark[0], scene->ropt.city_mark[1], 
         scene->ropt.city_mark[2], scene->ropt.city_mark[3], 
	 scene->ropt.city_mark[4]);
      print_string(str);
      sprintf(str, "-citysizes %d,%d,%d,%d,%d\n",
	 scene->ropt.city_size[0], scene->ropt.city_size[1], 
         scene->ropt.city_size[2], scene->ropt.city_size[3], 
	 scene->ropt.city_size[4]);
      print_string(str);
      sprintf(str, "-airportmarks %d,%d,%d,%d,%d\n",
	 scene->ropt.airport_mark[0], scene->ropt.airport_mark[1], 
         scene->ropt.airport_mark[2], scene->ropt.airport_mark[3], 
	 scene->ropt.airport_mark[4]);
      print_string(str);
      sprintf(str, "-airportsizes %d,%d,%d,%d,%d\n",
	 scene->ropt.airport_size[0], scene->ropt.airport_size[1], 
         scene->ropt.airport_size[2], scene->ropt.airport_size[3], 
	 scene->ropt.airport_size[4]);
      print_string(str);
      sprintf(str, "-peakmarks %d,%d,%d,%d,%d\n",
	 scene->ropt.peak_mark[0], scene->ropt.peak_mark[1], 
         scene->ropt.peak_mark[2], scene->ropt.peak_mark[3], 
	 scene->ropt.peak_mark[4]);
      print_string(str);
      sprintf(str, "-peaksizes %d,%d,%d,%d,%d\n",
	 scene->ropt.peak_size[0], scene->ropt.peak_size[1], 
         scene->ropt.peak_size[2], scene->ropt.peak_size[3], 
	 scene->ropt.peak_size[4]);
      print_string(str);
      sprintf(str, "-flagtypes %s\n", flag_descr);
      print_string(str);
      sprintf(str, "-cityfilter %s\n", scene->ropt.city_filter);
      print_string(str);
      sprintf(str, "-locfilter %s\n", scene->ropt.loc_filter);
      print_string(str);
      if (strcmp(scene->locfile, LOCFILE)) {
	 print_string("-locfile DEFAULT\n");
         sprintf(str, "-locfile %s\n", scene->locfile);
         print_string(str);
      }

      if (scene->numdef || scene->numpoint) {
         print_string("\n<defines>\n");
         for (i=0; i<scene->numdef; i++) {
            print_string(scene->def[i]+1);
            print_string("\n");         
         }
	 if (scene->numpoint) {
	    print_string("input");
            j = dms;
            dms = -1;
            for (i=0; i<scene->numpoint; i++) {
	       decim2dms(scene->mempoint[2*i], lat);
	       decim2dms(scene->mempoint[2*i+1], lon);
               sprintf(str, "|%s,%s", lat, lon);
               print_string(str);         
            }
            dms = j;
	    print_string("\n");
	 }
      }
      if (runlevel) fflush((FILE *)out_fd);
      im_compress = im_compress_save;
   }

   XDestroyImage(ximage);
   close_outfile();
}


/* 
 *  SECTION 4 : GEODESIC ROUTINES
 */

static ScreenPt project(ImageLayout * s, Vector a) {
	Vector v;
	static ScreenPt iv;
        Matrix *b;
	int i;
	
        b = &s->rotation;
	if (s->projection==SPHERICAL) {
           v.coord[0] = a.coord[0]*b->comp[0] + a.coord[1]*b->comp[3] + a.coord[2]*b->comp[6];
	   v.coord[1] = a.coord[0]*b->comp[1] + a.coord[1]*b->comp[4] + a.coord[2]*b->comp[7];
	   v.coord[2] = a.coord[0]*b->comp[2] + a.coord[1]*b->comp[5] + a.coord[2]*b->comp[8];
	   if (v.coord[2]>=0) 
              visible = 1;
	   else
	      visible = s->gopt.transparent;
	} else {
           v.coord[0] = a.coord[0] - b->comp[0];
	   if (v.coord[0]>s->earth_radius) {
	      i = (int)(v.coord[0]/s->earth_radius);
	      i = (i+1)&(-2);
              v.coord[0] -= ((double)i)*s->earth_radius;
	   } else
	   if (v.coord[0]<-s->earth_radius) {
	      i = (int)(-v.coord[0]/s->earth_radius);
	      i = (i+1)&(-2);
              v.coord[0] += ((double)i)*s->earth_radius;
	   }
           v.coord[0] *= b->comp[2];
           v.coord[1] = (a.coord[1] - b->comp[1]) * b->comp[2];
           v.coord[2] = a.coord[2] * b->comp[2];	  
	}
	iv.coord[0] = v.coord[0]+s->shiftx;
	iv.coord[1] = v.coord[1]+s->shifty;
	return iv;
}

void elliptic(double *x)
{
int sign=0;
double t;
    if (*x<0) {
       t = -(*x);
       sign = 1;
    } else
       t = *x;
    if (t>=1.0) return; 
    if (t==0) return;
    /* with STRETCHING=4/3, this closely imitates the Mollweide projection,
       while being much simpler to calculate */
    *x = 1.0 - exp(STRETCHING*log(1-t));
    if (sign) *x = -(*x);
}

void mollweide(double *x)
{
int k, sign=0;
double d, t;

    if (*x<0) {
       t = -(*x);
       sign = 1;
    } else
       t = *x;
    if (t>=1.0) return; 
    if (t==0) return;
    d = PI_OVER_2 * sin(PI_OVER_2 * t);
    if (t<=0.625) 
       *x = PI_SQUARE_OVER_8 * t * (1.0 - 0.09*t);
    else
       *x = 1.0 - exp((PI_SQUARE_OVER_8+MOLLWEIDE_COEFF*t)*log(1-t));
    k = 0;
 iter:
    ++k;
    t = *x;
    *x = 0.5 * (t + (d-asin(t))/sqrt(1-t*t));
    if (fabs(*x-t)>1E-9 && k<=10) goto iter;
    if (sign) *x = - (*x);
}

void operate(ImageLayout * s, double *y)
{
        if (s->projection==CYLINDRICAL)
           *y = sin(PI_OVER_2 * (*y));
	else
        if (s->projection==MERCATOR) {
	   if (*y>0.0) {
              if (*y>0.99) 
                 *y = 3.10;
	      else
                 *y = TWO_OVER_PI*log(tan(PI_OVER_4*(*y+1.0)));
	   } else {
              if (*y<-0.99) 
                 *y = -3.10;
	      else
                 *y = -TWO_OVER_PI*log(tan(PI_OVER_4*(-*y+1.0)));
	   }
	} 
        else
	if (s->projection==MILLER)
           *y = FIVE_OVER_2PI*log(tan(PI_OVER_4*(0.8*(*y)+1.0)));
	else
	if (s->projection==ELLIPTIC)
	   elliptic(y);
	else
	if (s->projection==MOLLWEIDE)
	   mollweide(y);
}

void inverse_operate(ImageLayout * s, double *y)
{
double d;
int sign;
       if (s->projection==CYLINDRICAL) {
	  if (fabs(*y)>=1.0) return;
          *y = TWO_OVER_PI * asin(*y);
       } else
       if (s->projection==MERCATOR)
	  *y = atan(exp((*y)*PI_OVER_2))/PI_OVER_4-1.0;
       else
       if (s->projection==MILLER)
	  *y = 1.25*(atan(exp(*y/FIVE_OVER_2PI))/PI_OVER_4-1.0);
       else
       if (s->projection==ELLIPTIC) {
	  if (*y==0) return;
	  if (*y>0) 
	     sign = 0;
          else {
	     *y = -(*y);
	     sign = 1;
	  }
	  if (*y<1)
             *y = 1.0 - exp(log(1-(*y))/STRETCHING);
	  if (sign) *y = -(*y);
       }
       else
       if (s->projection==MOLLWEIDE) {
	  if (fabs(*y)>=1.0) return;
	  d = 2.0 * asin(*y);
	  *y = asin((d + sin(d))*ONE_OVER_PI)*TWO_OVER_PI;
       }
}

static Vector spher2cart(ImageLayout * scene, SpherePt s) {
        Vector v;
	double latrad, lonrad, y;

	if (scene->projection==SPHERICAL) {
	   latrad = s.sph[LATITUDE] * CONV;
	   lonrad = s.sph[LONGITUDE] * CONV;
	   y = scene->earth_radius * cos(latrad);

           v.coord[X] = y * sin(lonrad);
           v.coord[Y] = scene->earth_radius * sin(latrad);
           v.coord[Z] = y * cos(lonrad);
           return v;
	} else {
	   y = -s.sph[LATITUDE] / 90.0;
	   if (scene->projection==SINUSOIDAL) {
	      lonrad = cos(PI_OVER_2*y);
	      if (lonrad>0.1)
	         escape_length = (int)(scene->width * lonrad * 0.5);
	      v.coord[X] = s.sph[LONGITUDE] - scene->gopt.yrot ;
	      while (v.coord[X]<-180.0) v.coord[X] += 360.0;
	      while (v.coord[X]>180.0) v.coord[X] -= 360.0;
              v.coord[X] = v.coord[X]*lonrad + scene->gopt.yrot;
	      while (v.coord[X]<-180.0) v.coord[X] += 360.0;
	      while (v.coord[X]>180.0) v.coord[X] -= 360.0;
              v.coord[X] *= scene->earth_radius/180.0;
	   }
	   else
	   if (scene->projection>=ELLIPTIC) {
              operate(scene, &y);
	      lonrad = 1.0-y*y;
	      if (lonrad<0.0)
		 lonrad = 0.0;
	      else
	         lonrad = sqrt(lonrad);
	      if (lonrad>0.1)
	         escape_length = (int)(scene->width * lonrad * 0.5);
	      v.coord[X] = s.sph[LONGITUDE] - scene->gopt.yrot ;
	      while (v.coord[X]<-180.0) v.coord[X]+= 360.0;
	      while (v.coord[X]>180.0) v.coord[X]-= 360.0;
              v.coord[X] = v.coord[X]*lonrad + scene->gopt.yrot;
	      while (v.coord[X]<-180.0) v.coord[X]+= 360.0;
	      while (v.coord[X]>180.0) v.coord[X]-= 360.0;
              v.coord[X] *= scene->earth_radius/180.0;
	   } else {
              operate(scene, &y);
	      v.coord[X] = scene->earth_radius * s.sph[LONGITUDE] / 180.0;
	   }
	   v.coord[Y] = 0.5 * scene->earth_radius * y * scene->aspect ;
	   return v;
	}
}

static int inverse_coord(ImageLayout * s, 
                     int i, int j, double *x, double *y)
{
        double fact;
        Vector a, v;
	Matrix *b;
	if (i<0 || j<0 || i>=s->width || j>=s->height) return 0;
	fact = s->earth_radius*s->gopt.zoom;
        a.coord[X] = ((double)(i-s->width/2))/fact;
	if (s->projection==SPHERICAL) {
           a.coord[Y] = ((double)(j-s->height/2))/fact;
	   a.coord[Z] = 1-(a.coord[X])*(a.coord[X])-(a.coord[Y])*(a.coord[Y]);
	   if (a.coord[Z]<0) return 0;
	   a.coord[Z] = sqrt(a.coord[Z]);
	   b = &s->rotation;
           v.coord[0] = a.coord[0]*b->comp[0] + a.coord[1]*b->comp[1] + a.coord[2]*b->comp[2];
	   v.coord[1] = a.coord[0]*b->comp[3] + a.coord[1]*b->comp[4] + a.coord[2]*b->comp[5];
	   v.coord[2] = a.coord[0]*b->comp[6] + a.coord[1]*b->comp[7] + a.coord[2]*b->comp[8];

	   v.coord[0] /= s->gopt.zoom;
	   v.coord[1] /= s->gopt.zoom;
	   v.coord[2] /= s->gopt.zoom;
	   *x = atan2(v.coord[1], sqrt(v.coord[0]*v.coord[0]+v.coord[2]*v.coord[2]))
                     / CONV;
	   *y = atan2(v.coord[0] , v.coord[2]) / CONV;
	   return 1;
	} else {
           a.coord[Y] = 2.0 * (((double)(j-s->height/2))/(fact*s->aspect)
                       + s->rotation.comp[1]/(s->earth_radius * s->aspect) );

	   if (s->projection==SINUSOIDAL) {
	      fact = cos(PI_OVER_2*a.coord[Y]);
	      if (fabs(a.coord[X])>fact) return 0;
	      *y = a.coord[X]/fact;
	   } else
	   if (s->projection>=ELLIPTIC) {
	      fact = sqrt(1-a.coord[Y]*a.coord[Y]);
	      if (fabs(a.coord[X])>fact) return 0;
	      *y = a.coord[X]/fact;
	   } else {
              *y = a.coord[X];
	      if (fabs(*y)>1.0) return 0;
	   }
 
	   inverse_operate(s, &a.coord[Y]);
	   if (fabs(a.coord[Y])>1.0) return 0;

	   *x = -a.coord[Y] * 90.0;
           *y = (*y)*180.0 + s->gopt.yrot;
           while (*y>180.0) *y -= 360.0;
	   while (*y<=-180.0) *y += 360.0;

	   return 1;
	}
}

/*
static int str2toint(unsigned char *str)
{
   if (str[1]<=127)
      return (int) (str[1]<<8)|str[0];
   else
      return (int) (0xffff<<16)|(str[1]<<8)|str[0];
}
*/

static int str3toint(unsigned char *str)
{
   if (str[2]<=127)
      return (int) (str[2]<<16)|(str[1]<<8)|str[0];
   else
      return (int) (0xff<<24)|(str[2]<<16)|(str[1]<<8)|str[0];
}

static int str4toint(unsigned char *str)
{
   return (int) (str[3]<<24)|(str[2]<<16)|(str[1]<<8)|str[0];
}

/* This function will generate the proper transformation 
 * matrix (rotation and scaling) and copy the values 
 * to the ImageLayout struct
 */

void compute_matrix(ImageLayout *s) {
     double y, cosx, cosy, cosz, sinx, siny, sinz;

     if (s->projection==SPHERICAL) {
        /* generate the proper rotation & scale matrix */
        cosx = cos(s->gopt.xrot * CONV);
        cosy = cos(s->gopt.yrot * CONV);
        cosz = cos(s->gopt.zrot * CONV);

        sinx = sin(s->gopt.xrot * CONV);
        siny = sin(s->gopt.yrot * CONV);
        sinz = sin(s->gopt.zrot * CONV);

	s->rotation.comp[0] = s->gopt.zoom*(cosy*cosz + sinx*siny*sinz);
	s->rotation.comp[1] = s->gopt.zoom*(-cosy*sinz + sinx*siny*cosz);
	s->rotation.comp[2] = s->gopt.zoom*(cosx*siny);

	s->rotation.comp[3] = s->gopt.zoom*(-cosx*sinz);
	s->rotation.comp[4] = s->gopt.zoom*(-cosx*cosz);
	s->rotation.comp[5] = s->gopt.zoom*(sinx);

	s->rotation.comp[6] = s->gopt.zoom*(-siny*cosz + sinx*cosy*sinz);
	s->rotation.comp[7] = s->gopt.zoom*(siny*sinz + sinx*cosy*cosz);
	s->rotation.comp[8] = s->gopt.zoom*(cosx*cosy);

     } else {
        s->rotation.comp[0] = s->gopt.yrot * s->earth_radius / 180.0;
        y = s->gopt.xrot / 90.0;
	operate(s, &y);
        s->rotation.comp[1] = - 0.5 * s->earth_radius * y * s->aspect;
        s->rotation.comp[2] = s->gopt.zoom;
     }
     update_positions(s, city_found);
}
	
static int segment_in_scene(ImageLayout *s, Segment_index *ind){
	SpherePt min, max, mid;
	ScreenPt pt1, pt2, pt3;

	min.sph[LONGITUDE] = str3toint(ind->minlong)/3600.0;
	min.sph[LATITUDE] = str3toint(ind->minlat)/3600.0;

	max.sph[LONGITUDE] = str3toint(ind->maxlong)/3600.0;
	max.sph[LATITUDE] = str3toint(ind->maxlat)/3600.0;

	mid.sph[LONGITUDE] = 0.5 * (min.sph[LONGITUDE] + max.sph[LONGITUDE]);
	mid.sph[LATITUDE] = 0.5 * (min.sph[LATITUDE] + max.sph[LATITUDE]);

	pt1 = project(s, spher2cart(s, max));
        if (!visible) return NO;
	pt2 = project(s, spher2cart(s, min));
        if (!visible) return NO;
	pt3 = project(s, spher2cart(s, mid));
        if (!visible) return NO;

	/* Yeah, this is ugly, but my head hurts right now. I've got the flu
	   I'll try to figure it out later */

	if ( (pt1.coord[X] >= s->width && pt2.coord[X] >= s->width
	                               && pt3.coord[X] >= s->width) ||
	     (pt1.coord[Y] >= s->height && pt2.coord[Y] >= s->height
                                        && pt3.coord[Y] >= s->height) || 
	     (pt1.coord[X] < 0 && pt2.coord[X] < 0 && pt3.coord[X] < 0) ||
	     (pt1.coord[Y] < 0 && pt2.coord[Y] < 0 && pt3.coord[Y] < 0) ) {
		return NO;
	}
	
	/* See if the whole segment can fit into one point, 
           if so, then just draw the point! */
	if ( (int)pt1.coord[X] == (int)pt2.coord[X] && 
             (int)pt1.coord[Y] == (int)pt2.coord[Y] ) {
		return POINT_ONLY;
	}

	return YES;
}

void draw_circles(ImageLayout *s) {
        int i, j, b;
	double x, y; 
	SpherePt spt1, spt2;
	ScreenPt pt1, pt2;
	char line[80];
	double step; /* small step */
	double main_circles_lat[5] = { 0.0, 23.435, 66.565 };
        int prev_visible;

	step = sqrt(4.0/(1.0+s->gopt.zoom));
	b = (s->projection==SPHERICAL);

	if (s->color[C_LON_GRID].bool == ON)
	for (i=0; i<=1; i++)
	for (x=i*s->ropt.spacing_lon; x<180.001-i*b*(s->ropt.spacing_lon/5); 
             x+=s->ropt.spacing_lon) {
	        j = 0;
  	        if (img_output == OUT_EPS) {
	           sprintf(line, "s%d\n", C_LON_GRID);
                   print_string(line);
	        }
		spt1.sph[LONGITUDE] = (i==0)? x : -x;
		spt2.sph[LONGITUDE] = spt1.sph[LONGITUDE];
		y = -89.999999;
		while (y<90.0) {
		   if (j==0) {
		      spt1.sph[LATITUDE] = y;
		      pt1 = project(s, spher2cart(s, spt1));
		      if (visible &&
                          abs(pt1.coord[X])<=15000 && abs(pt1.coord[Y])<=15000)
                         ++j;
                      else {
			 y += step;
                         continue;
		      }
		      path_start = 1;
		   } else
		      pt1 = pt2;
		   y += step;
		   if (y>=90.0)
		      spt2.sph[LATITUDE] = 89.999999;
		   else
		      spt2.sph[LATITUDE] = y;
		   prev_visible = visible;
		   pt2 = project(s, spher2cart(s, spt2));
		   if (visible &&
                       abs(pt2.coord[X])<=15000 && abs(pt2.coord[Y])<=15000) {
	              escape_length = LARGE_INTEGER;
		      if (!prev_visible) path_start = 1;
		      draw_segment(s, pt1, pt2, s->color[C_LON_GRID].pix);
		   }
		}
		if (img_output == OUT_EPS)
                   print_string("k\n");
	}

	for (i=0; i<=6; i++)
	for (x=i*s->ropt.spacing_lat; x<90.0-s->ropt.spacing_lat/5 || i>=2; 
             x+=s->ropt.spacing_lat) {
                Pixel pix;
	        if (i<=1 && s->color[C_LAT_GRID].bool != ON) break;
	        if (i>1 && s->color[C_MAIN_LINES].bool != ON) break;
	        if (i>=2) {
                   x = main_circles_lat[(i-1)>>1];
		   pix = s->color[C_MAIN_LINES].pix;
  	           if (img_output == OUT_EPS) {
	              sprintf(line, "s%d\n", C_MAIN_LINES);
                      print_string(line);
	           }
		} else {
		   pix = s->color[C_LAT_GRID].pix;
  	           if (img_output == OUT_EPS) {
	              sprintf(line, "s%d\n", C_LAT_GRID);
                      print_string(line);
	           }
		}
	        j = 0;
		spt1.sph[LATITUDE]  = (i&1)? x : -x;
		spt2.sph[LATITUDE]  = spt1.sph[LATITUDE];
		y = -180;
		while (y<180.0) {
		   if (j==0) {
		      spt1.sph[LONGITUDE] = y;
		      pt1 = project(s, spher2cart(s, spt1));
		      if (visible &&
                          abs(pt1.coord[X])<=15000 && abs(pt1.coord[Y])<=15000)
                         ++j;
                      else {
                         y += step;
                         continue;
                      }
		      path_start = 1;
		   } else
		      pt1 = pt2;
		   y += step;
		   if (y>=180.0)
		      spt2.sph[LONGITUDE] = 180.0;
		   else
                      spt2.sph[LONGITUDE] = y;
		   prev_visible = visible;
		   pt2 = project(s, spher2cart(s, spt2));
		   if (visible &&
                       abs(pt2.coord[X])<=15000 && abs(pt2.coord[Y])<=15000) {
	              escape_length = LARGE_INTEGER;
 		      if (!prev_visible) path_start = 1;
		      draw_segment(s, pt1, pt2, pix);
		   }
		}
		if (img_output == OUT_EPS)
                   print_string("k\n");
		if (i>=2) break;
	}

	if (s->color[C_EARTH_CONTOUR].bool == ON &&
	    s->projection==SPHERICAL) {
	   y = s->earth_radius * s->gopt.zoom;
	   pt2.coord[X] = (int)(y+s->shiftx);
	   pt2.coord[Y] = (int)(s->shifty);
	   path_start = 1;
  	   if (img_output == OUT_EPS) {
	       sprintf(line, "s%d\n", C_EARTH_CONTOUR);
               print_string(line);
	   }
	   for (x=step; x<360.1-step; x+=step) {
	       pt1 = pt2;
	       pt2.coord[X] = (int) (y * cos(x*CONV)+s->shiftx);
	       pt2.coord[Y] = (int) (y * sin(x*CONV)+s->shifty);
	       draw_segment(s, pt1, pt2, s->color[C_EARTH_CONTOUR].pix);
	   }
  	   if (img_output == OUT_EPS)
               print_string("k\n");
	}
}

void
draw_circle_coordinates(ImageLayout *scene)
{
    int i, ip, j, k, kold, l, vshift, hshift, step, fontnum, text_w;
    double x, y;
    char number[30], text[256], format[20];

    if (scene->color[C_LAT_GRID].bool == OFF &&
        scene->color[C_LON_GRID].bool == OFF) return;
    if (scene->ropt.latcoord == 0 &&
        scene->ropt.loncoord == 0) return;

    fontnum = 5;
    XSetForeground(dpy, gc, scene->color[C_LAT_GRID].pix);
    XSetFont(dpy, gc, xfont[fontnum]->fid);
    vshift = xfont[fontnum]->max_bounds.descent + 3;
    hshift = 4;

    step = 0;
    k = 0;
    if (scene->ropt.latcoord == 1)
       i = ip = 3;
    else
       i = ip = scene->width - 3;
    if (scene->ropt.spacing_lat>=1.0) 
        strcpy(format, "%.0f°");
    else if (scene->ropt.spacing_lat>=0.1) 
        strcpy(format, "%.1f°");
    else
        strcpy(format, "%.2f°");

    if (scene->color[C_LAT_GRID].bool == ON && scene->ropt.latcoord)
    for (j=0; j<scene->height - vshift; j++) {
        if (inverse_coord(scene, i, j+vshift, &x, &y)) {
	    kold = k;
	    if (x>=0)
	       k = (int) (x/scene->ropt.spacing_lat);
	    else
	       k = -(int) (-x/scene->ropt.spacing_lat)-1;
            ++step;
	    if (step==1) {
               if (img_output == OUT_EPS) {
		  sprintf(text, "f%d c%d\n", fontnum, C_LAT_GRID);
		  print_string(text);
	       }
	       continue;
	    }
	    if (k==kold) continue;
	    if (k>kold) l = k; else l = kold;
	    sprintf(number, format, l*scene->ropt.spacing_lat);
	    text_w = XTextWidth(xfont[fontnum], number, strlen(number));
	    if (i>3) {
                ip = scene->width - text_w - 3; 
	    }
	    if (scene->ropt.smartlabels)
               PixmapDrawString(scene, ip, j, text_w, fonth[fontnum],
                                number, strlen(number));
	    else {
	       XDrawString(dpy, scene->pixmap, gc, ip, j,
			            number, strlen(number));
	       text_drawn = 1;
	    }
 	    if (img_output == OUT_EPS && text_drawn) {
                sprintf(text, "%d %d m (%s) %d %d %d %d SS\n", 
                   ip, scene->height - j - 1, number, 0, 0, 0, 0);
	        print_string(text);
	    }
	}
    }

    k = 0;
    step = 0;
    if (scene->ropt.loncoord == 1)
       j = fontasc[fontnum]+1;
    else
       j = scene->height - xfont[fontnum]->max_bounds.descent - 3;

    if (scene->ropt.spacing_lon>=1.0) 
        strcpy(format, "%.0f°");
    else if (scene->ropt.spacing_lon>=0.1) 
        strcpy(format, "%.1f°");
    else
        strcpy(format, "%.2f°");

    if (scene->color[C_LON_GRID].bool == ON && scene->ropt.loncoord)
    for (i=0; i<scene->width - hshift; i++) {
        if (inverse_coord(scene, i-hshift, j, &x, &y)) {
	    kold = k;
	    if (y>=0)
	       k = (int) (y/scene->ropt.spacing_lon);
	    else
	       k = -(int) (-y/scene->ropt.spacing_lon)-1;
	    ++step;
	    if (step==1) {
               if (img_output == OUT_EPS) {
		  sprintf(text, "f%d c%d\n", fontnum, C_LON_GRID);
		  print_string(text);
	       }
	       continue;
	    }
	    if (k==kold) continue;
	    if (k>kold) l = k; else l = kold;
	    sprintf(number, format, l*scene->ropt.spacing_lon);
	    if (scene->ropt.smartlabels) {
	       text_w = XTextWidth(xfont[fontnum], number, strlen(number));
               PixmapDrawString(scene, i, j, text_w, fonth[fontnum],
                   number, strlen(number));
	    } else {
	       XDrawString(dpy, scene->pixmap, gc, i, j,
			            number, strlen(number));
	       text_drawn = 1;
	    }
 	    if (img_output == OUT_EPS && text_drawn) {
                sprintf(text, "%d %d m (%s) %d %d %d %d SS\n", 
                   i, scene->height - j - 1, number, 1, 0, 0, 0);
	        print_string(text);
	    }
        }
    }
}

int size_of_object(ImageLayout *s, int *sizes, int n)
{
    int i;    
    for (i=0; i<5; i++) if (n>=sizes[i]) return i;
    return -1;
}

void draw_location(ImageLayout *s, Location * loc) {
	ScreenPt pt;
        SpherePt spt;
	int i, j, space=0, u, x, y, pos=0, ind=0, size=0, 
	    colmark=0, coltext=0;
        int boolmark=0, booltext=0;
	Pixel pix = black;
        unsigned short * bits;
	char name[128], line[256];
	char *ptr = NULL, *seatype = NULL;

        if (loc->draw & OBJ_HIDE) return;
	i = loc->tz;
	if (i<0) return;
	if (loc->obj=='l') {
	   i = 0x00000001<<(i-1);
	   if (!(s->gopt.desired_continents & i)) return;
	   seatype = index("BKOSTV", loc->status);
	   if (s->color[C_LOC_LAND].bool!=ON && !seatype) return;
	   if (s->color[C_LOC_WATER].bool!=ON && seatype) return;
	   booltext = 1;
           goto projpoint;
        } else {
	   i = 0x00000001<<timezones[i]->continent;
	   if (!(s->gopt.desired_continents & i)) return;
	}

	if (loc->obj=='c') {
	   if (!index(s->ropt.city_filter, loc->status)) return;
	   size = size_of_object(s, s->ropt.city_size, loc->population);
	   ind = s->ropt.city_mark[size]-1;
	   if (ind<0) return;
	   if (!(loc->draw & OBJ_SHOW) && s->ropt.mark_step[size] > 
              (int)(2*s->gopt.zoom*s->earth_radius)) return;
	   boolmark = s->color[C_CITY_CIRCLE].bool;
	   booltext = s->color[C_CITY_TEXT].bool;
	   colmark = C_CITY_CIRCLE;
	   coltext = C_CITY_TEXT;
        } else
        if (loc->obj=='a') {
	   size = size_of_object(s, s->ropt.airport_size, loc->population);
	   ind = s->ropt.airport_mark[size]+4;
	   if (ind<=4) return;
	   if (!(loc->draw & OBJ_SHOW) && s->ropt.mark_step[size] > 
              (int)(2*s->gopt.zoom*s->earth_radius)) return;
	   boolmark = s->color[C_AIRPORT_SYMBOL].bool;
	   booltext = s->color[C_AIRPORT_TEXT].bool;
	   colmark = C_AIRPORT_SYMBOL;
	   coltext = C_AIRPORT_TEXT;
        } else
        if (loc->obj=='p') {
	   size = size_of_object(s, s->ropt.peak_size, loc->alt);
	   ind = s->ropt.peak_mark[size]+9;
	   if (ind<=9) return;
	   if (!(loc->draw & OBJ_SHOW) && s->ropt.mark_step[size] > 
              (int)(2*s->gopt.zoom*s->earth_radius)) return;
	   boolmark = s->color[C_PEAK_TRIANGLE].bool;
	   booltext = s->color[C_PEAK_TEXT].bool;
	   colmark = C_PEAK_TRIANGLE;
	   coltext = C_PEAK_TEXT;
        } else
        if (loc->obj=='b') {
	   boolmark = s->color[C_OBSERV_SYMBOL].bool;
	   booltext = s->color[C_OBSERV_TEXT].bool;
	   colmark = C_OBSERV_SYMBOL;
	   coltext = C_OBSERV_TEXT;
	   ind = 15;
	}
	if (!boolmark && !booltext) return;

	/* calculate the point projection and check visibility */
   projpoint:
	spt.sph[LONGITUDE] = loc->lon;
	spt.sph[LATITUDE] = loc->lat;
	pt = project(s, spher2cart(s, spt));
	if (!visible) return;

	/* verify that the point is on the map, return if not */
	if (pt.coord[X] > s->width || pt.coord[X] < 0 || 
            pt.coord[Y] > s->height || pt.coord[Y] < 0) return;
	
	/* draw a mark around the point in question if it's not just
           a location name and boolmark is set */
        if (boolmark) {
	   bits = spot_bits[ind];
	   space = bits[0]/2;
	   pix = s->color[colmark].pix;
	   x = (int)pt.coord[X];
	   y = (int)pt.coord[Y];
	   if (img_output == OUT_EPS) {
              sprintf(line, "c%d %.2f %.2f m o%c%d\n",
		 colmark, pt.coord[X], s->height-1-pt.coord[Y],
		 loc->obj, size);
	      print_string(line);
	   }
	   for (j=0; j<bits[0]; j++) {
              if (pt.coord[Y]-space+j >= s->height) break;
              u = bits[j+1];
              for (i=0; i<bits[0]; i++) {
                 if (u&1) 
                   draw_pixel(s, x-space+i, y-space+j, pix);
                 u = u>>1;
	      }
	   }
	   loc->draw |= SPOT_DRAWN;
	}
        if (!booltext) return;

	/* determine the text position depending whether it's a location
           name or a label near a mark */
	if (loc->obj=='l') {
	   ind = loc->population;
	   pos = loc->alt;
	   strcpy(name, loc->name);
	   if (!ind) return;
           if (!index(s->ropt.loc_filter, loc->status)) return;
	   if (!(loc->draw & OBJ_SHOW) && s->ropt.name_step[ind-1] > 
              (int)(2*s->gopt.zoom*s->earth_radius)) return;
	   if (seatype)
	      coltext = C_LOC_WATER;
           else
	      coltext = C_LOC_LAND;
	} else {
	   ind = size;
           /* write also names of smaller capital cities... */
	   if (loc->status!= 'C' &&
               !(loc->draw & OBJ_SHOW) && s->ropt.name_step[size] > 
              (int)(2*s->gopt.zoom*s->earth_radius)) return;
	   if ((ptr=index(loc->name,'('))) {
	      strcpy(name, ptr+1);
	      ptr = index(name,')');
	      if (ptr) *ptr = '\0';
           } else
	      strcpy(name, loc->name);
	   ptr = name;
	   if (s->ropt.placetext) {
	      if (pt.coord[X] > s->width/2) pos = 4; else pos = 0;
              if (pt.coord[Y] < s->height/16) {
		 if (pos==0) pos = 7; else pos = 5;
	      }
              if (pt.coord[Y] > 15*s->height/16) {
		 if (pos==0) pos = 1; else pos = 3;
	      }
	   }
	}

	/* add text, taking possibly into account user defined modification */
	if ((i=(loc->draw & 0x0fffffff))) {
	   i = 2*(i-1);
	   pt.coord[X] += (double) s->modpos[i];
	   pt.coord[Y] += (double) s->modpos[i+1];
	}
	draw_string(s, &pt, name, ind, pos, space, coltext);
	if (text_drawn)
	   loc->draw |= TEXT_DRAWN;
}

void draw_feature(ImageLayout *scene, char * cmd) {
        int i, j, n, h;
	SpherePt spt;
        ScreenPt pt;
        char name[256];
	char line[256];
	char lat[256];
	char lon[256];
	char height[256];
        char *str = NULL, *ptr;

	/* first char of cmd string is feature type; skip it */
        ++cmd;

        if (!strncmp(cmd, "image|", 6)) {
           XImage *image = NULL;
	   str = strdup(cmd+6);
	   if ((ptr=index(str, ','))) {
	      *ptr = ' ';
	      ++ptr;
              if ((ptr=index(ptr, '|'))) *ptr = ' ';
              ++ptr;
              if ((ptr=index(ptr, '|'))) *ptr = ' ';
	   }
           n = sscanf(str, "%s %s %s %s", lat, lon, name, height);
           spt.sph[LATITUDE] = dms2decim(lat);
	   spt.sph[LONGITUDE] = dms2decim(lon); 
	   if (n>=3) {
	      if (n==4) h=atoi(height); else h = 32; /* why not ? */
              j = -1;
	      for (i=0; i<num_flag_dirs; i++) {
		if (strstr(name, flag_formats[i])) { j = i; break; }
	      }
              image = readIMG(scene, NULL, name, h, &scene->color[C_BG_MAP]);
              if (image != NULL) {
                 pt = project(scene, spher2cart(scene, spt));
                 XPutImage(dpy, scene->pixmap, gc, image, 0, 0, 
                    pt.coord[X]-image->width/2, pt.coord[Y]-image->height/2, 
                    image->width, image->height);
		 if (img_output == OUT_EPS) {
		    print_string("gsave\n");
		    sprintf(line, "%.2f %.2f translate\n%d %d scale",
                       pt.coord[X]-image->width/2, 
		       scene->height-1-pt.coord[Y]-image->height/2,
		       image->width, image->height);
		    print_string(line);
		    print_PS_image(scene, image);
		    print_string("grestore\n");
		 }
                 XDestroyImage(image);
	      }
	   }
           free(str);
	}

        if (!strncmp(cmd, "color|", 6)) {
	   XColor color, exact;
           if (XAllocNamedColor(dpy, cmap, cmd+6, &color, &exact)==(Status)1) {
	      scene->currentpixel = color.pixel;
	      scene->red_current = color.red;
	      scene->green_current = color.green;
	      scene->blue_current = color.blue;
	   } else {
	      scene->currentpixel = (reverse)?white:black;
	      scene->red_current = (reverse)?65535:0;
	      scene->green_current = scene->red_current;
	      scene->blue_current = scene->red_current;
	   }
	   if (img_output == OUT_EPS) {
	      sprintf(line, "%.4f %.4f %.4f RGB\n",
	         scene->red_current/65535.0, 
                 scene->green_current/65535.0, 
                 scene->blue_current/65535.0);
              print_string(line);
	   }
	}

        if (!strncmp(cmd, "font|", 5)) {
	   i = atoi(cmd+5);
           if (i<0) i=0;
           if (i>=5) i=5;
	   scene->currentfont = i;
	   if (img_output == OUT_EPS) {
	      sprintf(line, "f%d\n", scene->currentfont);
              print_string(line);
	   }
	}

        if (!strncmp(cmd, "label|", 6)) {
	   int pos;
	   str = strdup(cmd+6);
	   if ((ptr=index(str, '|'))) {
	      *ptr = ' ';
	      ++ptr;
              if ((ptr=index(ptr, ','))) {
		 *ptr = ' ';
	         ++ptr;
                 if ((ptr=index(ptr, '|'))) *ptr = ' ';
	      }
	   }
           n = sscanf(str, "%d %s %s %s", &pos, lat, lon, name);
	   if (n==4) {
              spt.sph[LATITUDE] = dms2decim(lat);
              spt.sph[LONGITUDE] = dms2decim(lon); 
	      for (i=0; i<strlen(name); i++) 
	         if (name[i]=='\037') name[i] = ' ';
	      if (str) free(str);
              pt = project(scene, spher2cart(scene, spt));
	      draw_string(scene, &pt, name, scene->currentfont, pos, 0, -1);
	   }
	}

        if (!strncmp(cmd, "ellipse|", 8)) {
	   int rx, ry;
	   str = strdup(cmd+8);
	   if ((ptr=index(str, ','))) {
	      *ptr = ' ';
	      ++ptr;
              if ((ptr=index(ptr, '|'))) {
		 *ptr = ' ';
	         ++ptr;
                 if ((ptr=index(ptr, ','))) *ptr = ' ';
	      }
	   }
           n = sscanf(str, "%d %d %s %s", &rx, &ry, lat, lon);
           spt.sph[LATITUDE] = dms2decim(lat);
           spt.sph[LONGITUDE] = dms2decim(lon); 
	   if (str) free(str);
	   if (n==4) {
              pt = project(scene, spher2cart(scene, spt));
	      XSetForeground(dpy, gc, scene->currentpixel);
              XFillArc(dpy, scene->pixmap, gc, 
                       pt.coord[X]-rx/2, pt.coord[Y]-ry/2, 
                       (unsigned) rx, (unsigned) ry, 0, 360*64);
	      if (img_output == OUT_EPS) {
                 sprintf(line, "%.2f %.2f %d %d ellipse fill\n", 
                       pt.coord[X]-rx/2, pt.coord[Y]-ry/2, 
                       (unsigned) rx, (unsigned) ry);
     	         print_string(line);
	      }
	   }
	}

        if (!strncmp(cmd, "polyline|", 9) || 
            !strncmp(cmd, "polygon|", 8) || 
            !strncmp(cmd, "region|", 7)) {
           char *strp;
	   int done, fill, npoints=0;
           XPoint *points = NULL;
	   if (*cmd=='r') {
	      str = strdup(cmd+7);
	      fill = 2;
	   } else 
           if (cmd[4]=='g') {
	      str = strdup(cmd+8);
	      fill = 1;
	   } else {
	      str = strdup(cmd+9);
	      fill = 0;
	   }
	   XSetForeground(dpy, gc, scene->currentpixel);
	   strp = (char *)strtok(str, ",");
	   done = 0;
	   if (strp) {
              spt.sph[LATITUDE] = dms2decim(strp);
	      strp = strtok(NULL, "|");
	      if (strp) {
                 spt.sph[LONGITUDE] = dms2decim(strp);
                 pt = project(scene, spher2cart(scene, spt));
		 done = 1;
		 points = (XPoint*) malloc(sizeof(XPoint));
		 points[0].x = double2short(pt.coord[X]);
		 points[0].y = double2short(pt.coord[Y]);
		 npoints = 1;
	      }
	   }
	   while (done) {
	      done = 0;
	      strp = strtok(NULL, ",");
	      if (strp) {
                 spt.sph[LATITUDE] = dms2decim(strp);
 	         strp = strtok(NULL, "|");
	         if (strp) {
                    spt.sph[LONGITUDE] = dms2decim(strp);
                    pt = project(scene, spher2cart(scene, spt));
		    done = 1;
		    points = (XPoint*) realloc(points, 
                                 (npoints+2)*sizeof(XPoint));
		    points[npoints].x = double2short(pt.coord[X]);
		    points[npoints].y = double2short(pt.coord[Y]);
		    ++npoints;
	         }
	      }
	   }
	   if (fill==1) {
	      points[npoints] = points[0];
              ++npoints;
	   }
	   if (fill==2)
              XFillPolygon(dpy, scene->pixmap, gc, points, npoints,
                                Complex, CoordModeOrigin);
	   else
              XDrawLines(dpy, scene->pixmap, gc, points, npoints,
                                CoordModeOrigin);
           if (img_output == OUT_EPS) {
	      sprintf(line, "%d %d m\n", 
                 points[0].x, scene->height-1-points[0].y);
	      print_string(line);
	      for (i=1; i<npoints; i++) {
	         sprintf(line, "%d %d l\n", 
                    points[i].x, scene->height-1-points[i].y);
	         print_string(line);
	      }
	      if (fill==2) 
		 print_string("fill\n");
	      else
		 print_string("stroke\n");
	   }
	   if (str) free(str);
	   if (points) free(points);
	}	   

        if (!strncmp(cmd, "modif|", 6)) {
	   int mode, dx, dy;
	   str = strdup(cmd+6);
	   if (search_string) free(search_string);
	   mode = -1;
	   if (!strncmp(str, "hide", 4)) {
	      mode = 0;
	      search_string = strdup(str+5);
	   } else
	   if (!strncmp(str, "show", 4)) {
	      mode = 1;
	      search_string = strdup(str+5);
	   } else
	   if (!strncmp(str, "position", 8)) {
	      mode = 2;
	      search_string = strdup(str+9);
              if (sscanf(str+9, "%d|%s", &dx, search_string)<2) 
                 mode = -1;
	   } else
	   if (!strncmp(str, "move", 4)) {
	      mode = 3;
	      search_string = strdup(str+5);
              if (sscanf(str+5, "%d,%d|%s", &dx, &dy, search_string)<3) 
                 mode = -1;
	   }
	   if (str) free(str);
	   for (i=0; i<strlen(search_string); i++) 
	      if (search_string[i]=='\037') search_string[i] = ' ';
	   if (mode>=0) 
	      search_city(scene);
	   else
	      num_found = 0;
	   if (num_found==1) {
	      i = loc_pointer[0];
	      if (mode==0) {
                 locations[i]->draw |= OBJ_HIDE;
                 locations[i]->draw &= ~OBJ_SHOW;
	      }
	      if (mode>=1) {
                 locations[i]->draw &= ~OBJ_HIDE;
                 locations[i]->draw |= OBJ_SHOW;
	      }
	      if (mode==2) {
                 locations[i]->alt = (char)dx;
	      } else
	      if (mode==3) {
		 int j = 2*scene->nummod;
		 ++scene->nummod;
		 locations[i]->draw &= 0xf0000000;
		 locations[i]->draw |= scene->nummod;
                 scene->modpos = (int*) 
                    realloc(scene->modpos, 2*scene->nummod*sizeof(int));
		 scene->modpos[j] = dx;
		 scene->modpos[j+1] = -dy;
	      }
	   }
	}
}

void set_sky(ImageLayout *scene, int c)
{
    int i, j, i1_0=0, i2_0=0, i1, i2, j1=0, j2=0, k, l, pixelset = 0;
    Pixel bg, sky, star;
    /* pixels for bigger stars */
    int dx[5] = { 0, 0, 0, 1, -1};
    int dy[5] = { 0, 1, -1, 0, 0};
    double R, R2=0, val, y;
    char line[256];

    bg = scene->color[C_BG_MAP].pix;
    if (scene->color[C_BG_SKY].bool) {
       sky = scene->color[C_BG_SKY].pix;
       if (scene->color[C_FG_STARS].bool)
          star = scene->color[C_FG_STARS].pix;
       else
	  star = sky;
    } else
       star = sky = bg;

    R = scene->earth_radius*scene->gopt.zoom;
    i = round2int(R);
    if (scene->projection==SPHERICAL) {
       j = i;
       j1 = scene->height/2 - j;
       j2 = scene->height/2 + j;
       R2 = R*R;
    } else {  
       i1_0 = scene->width/2 - i;
       i2_0 = scene->width/2 + i;
       if (scene->projection==RECTANGULAR ||
           scene->projection==SINUSOIDAL ||
           scene->projection>=ELLIPTIC) {
	  y = scene->gopt.xrot/90.0;
	  operate(scene, &y);
	  y *= 0.5;
          j1 = scene->height/2-(int)(R*scene->aspect*(0.5-y));
          j2 = scene->height/2+(int)(R*scene->aspect*(0.5+y));
       } else
       if (scene->projection==CYLINDRICAL) {
	  y = 0.5*sin(scene->gopt.xrot * CONV);
          j1 = scene->height/2-(int)(R*scene->aspect*(0.5-y));
          j2 = scene->height/2+(int)(R*scene->aspect*(0.5+y));
       } else
       if (scene->projection==MERCATOR) {
	  j1 = 0;
	  j2 = scene->height-1;
       } else
       if (scene->projection==MILLER) {
          y = scene->gopt.xrot/90.0;
	  operate(scene, &y);
	  y *= 0.5;
	  j1 = scene->height/2 - (int)(R*scene->aspect*(MAX_MILLER-y));
	  j2 = scene->height/2 + (int)(R*scene->aspect*(MAX_MILLER+y));
       }
    }

    for (j=0; j<scene->height; j++) {
       if (j<j1 || j>j2) 
	  i1 = i2 = scene->width;
       else {
          if (scene->projection==SPHERICAL) {
	     i = j - scene->height/2;
	     val = R2 - ((double)i*(double)i);
	     if (val<=0) 
                val = 0.0;
	     else
	        val = sqrt(val);
	     i = round2int(val);
             i1 = scene->width/2 - i;
             i2 = scene->width/2 + i;
	  }
          else 
          if (scene->projection==SINUSOIDAL) {
	     k = j-scene->height/2-(int)(R*scene->aspect*y);
	     k = (int)(R*cos((M_PI*k)/(R*scene->aspect)));
	     i1 = scene->width/2 - k;
	     i2 = scene->width/2 + k;
	  } 
          else 
          if (scene->projection>=ELLIPTIC) {
	     k = j-scene->height/2-(int)(R*scene->aspect*y);
	     val = (2.0*(double)k)/(R*scene->aspect);
             val = 1-val*val;
	     if (val<=0) 
                val = 0;
	     else
	        val = sqrt(val);
	     k = round2int(R*val);
	     i1 = scene->width/2 - k;
	     i2 = scene->width/2 + k;
	  } 
          else {
             i1 = i1_0;
             i2 = i2_0;
	  }
       }
       for (i=0; i<scene->width; i++) {
	  if (i>=i1 && i<i2)
	     draw_pixel(scene, i, j, bg);
	  else {
	     if ((i<i1-2 || i>i2+2) && (i*i+j)%971 == (j*j*j+i)%593 + c) {
	        pixelset = 1;
		if (((9*i+j*j)%7) == 0) l=4; else l=0;
		for (k=0; k<=l; k++)
	           draw_pixel(scene, i+dx[k], j+dy[k], star);
	        } else
	           draw_pixel(scene, i, j, sky);
	  }
       }
    }

    if (img_output == OUT_EPS) {
       /* initialize */
       if (!pixelset)
          print_string("/draw_sky false def\n");
       sprintf(line, 
          "draw_sky { c%d  0 0 m %d 0 l %d %d l 0 %d l 0 0 l fill\n"
          "           c%d  %d %d %d stars } if\n",
          C_BG_SKY, scene->width, scene->width, scene->height, scene->height,
          C_FG_STARS, c, scene->width, scene->height);
       print_string(line);
       /* fill according to projection */
       if (scene->projection==SPHERICAL)
	  sprintf(line, 
             "draw_sky { c%d %.2f %.2f %.2f 0 360 arc fill } if\n",
	     C_BG_MAP, 0.5*scene->width, 0.5*scene->height, R);
       else
       if (scene->projection>=RECTANGULAR && scene->projection<=MILLER) 
	  sprintf(line, 
             "draw_sky { c%d %d %d m %d %d l %d %d l %d %d l clp fill } if\n",
	     C_BG_MAP,
	     i1_0, scene->height-1-j1, i2_0, scene->height-1-j1, 
             i2_0, scene->height-1-j2, i1_0, scene->height-1-j2);
       else
       if (scene->projection>=SINUSOIDAL)
	  sprintf(line,
             "draw_sky { gsave c%d %.2f %.2f translate\n"
             "           1 %.4f scale 0 0 %.2f %s fill\n"
             "           grestore } if\n",
	     C_BG_MAP, 0.5*(i1_0+i2_0), scene->height-1-0.5*(j1+j2), 
             0.5*scene->aspect, R, 
             (scene->projection==SINUSOIDAL)? "sinusoidal" : "0 360 arc fill");
       print_string(line);
       /* set PS rectangle clip */
       sprintf(line,
          "0 0 m %d 0 l %d %d l 0 %d l 0 0 l clip newpath\n"
          "2 slj\n\n",
          scene->width, scene->width, scene->height, scene->height);
       print_string(line);
    }
}

void initialize_EPS(ImageLayout * scene, int c)
{
    FILE *fini;
    char line[256];
    int i;
    double lw;

    open_outfile(scene);
    print_PS_prolog(scene);
    print_string("gsave\n");    

    fini = fopen(SHAREDIR"/postscript/macros.ps", "r");
    if (fini) {
       while (fgets(line, 254, fini)) print_string(line);
           fclose(fini);
    }
    print_string("\n");
    print_PS_scaling(scene, 0);
    print_string("% Set frame linewidth and color here\n");
    sprintf(line, "/frame_style { 0 slj  1 lw c%d } def\n", C_BG_SKY);
    print_string(line);
    sprintf(line, "%s %s %s\n", 
            "/draw_frame", (ps_frame)?"true":"false", "def");
    print_string(line);
    print_string("/draw_sky true def\n");
    print_string("\n%% font sizes and types\n");
    for (i=0; i<=5; i++) {
       sprintf(line, 
              "/fs%d %d def /f%d {fs%d /Times-Roman-ISO fontdef} def\n",
          i, 12-i, i, i);
       print_string(line);
    }
    print_string("\n%% colors\n");
    for (i=0; i<C_ENDCOLOR; i++) {
       sprintf(line, "/c%d {%.4f %.4f %.4f RGB} def\n", i,
          scene->color[i].r/65535.0,
          scene->color[i].g/65535.0,
          scene->color[i].b/65535.0);
       print_string(line);
    }
    print_string(
           "\n%% line styles (color, linewidth, dash style)\n");
    for (i=0; i<C_ENDCOLOR; i++) {
       lw = 0.5;
       if (i==0) lw = 0.8;
       if (i>=3 && i<=5) lw = 0.6;
       if (i==16) lw = 1.0;
           sprintf(line, "/s%d {c%d %.2f clw [] 0 ds} def\n", i, i, lw);
       print_string(line);
    }
    print_string("\n");
    if (*scene->macrofile) {
       fini = fopen(scene->macrofile, "r");
       if (fini) {
          while (fgets(line, 254, fini)) print_string(line);
          fclose(fini);
       }
    }
}

int essential_change(ImageLayout *scene1, ImageLayout *scene2)
{
    return 
      memcmp(scene1, scene2, 
        3*sizeof(int)+5*sizeof(double)+sizeof(Matrix)
	+sizeof(GeomOptions)) ||
      memcmp(scene1->color, scene2->color, C_MAIN_LINES*sizeof(Colordata));
}

#ifdef ARCINFO

void fpr3(FILE * f, int n)
{
    fprintf(f, "%c%c%c", n&255, (n>>8)&255, (n>>16)&255);
}

void fpr4(FILE * f, int n)
{
    fprintf(f, "%c%c%c%c", n&255, (n>>8)&255, (n>>16)&255, n>>24);
}

void spr3(char * st, int n)
{
    st[0] = n&255;
    st[1] = (n>>8)&255;
    st[2] = (n>>16)&255;
}

void spr4(char * st, int n)
{
    st[0] = n&255;
    st[1] = (n>>8)&255;
    st[2] = (n>>16)&255;
    st[3] = n>>24;
}

int check_cat_and_cont(ImageLayout *scene, int u)
{
    int i, k;
    i = u/28; /* number of continent */
    if ( !((1<<i) & scene->gopt.desired_continents) ) return 0;

    /* type of item, INT=0, NAT=1, RIV=2 or CIL=3 */
    i = u%28; 
    if (!scene->color[i].bool) return 0;

    if (i <= 2) 
       k = 0;
    else
    if (i <= 4) 
       k = 1;
    else
    if (i <= 15) 
       k = 2;
    else
       k = 3;
    if ( !((1<<k) & scene->gopt.desired_categories) ) return 0;

    return 1;
}

void arcinfo_lines(ImageLayout *scene) {
    void *fd;
    char buf[512];
    char sep;
    char *ptr;
    char **seg;
    double a, b, c, d;
    int i, j, k, u, n, p, i0;
    int new_arc=0, ind, indpr, num_mod = -1, nstrokes, xi, yi;
    SpherePt sp;
    ScreenPt pt1, pt2;
    Pixel pix;
    double cotan_lat0, conv_lat0;

void next_segment(double x, double y)
{
    double u, v, w, t;
    int i, j, dx, dy, dxp, dyp, epsx, epsy;

    if (arc_lambert) {
       /* Inverse Lambert projection */
       u = x * arc_scale;
       v = y * arc_scale - arc_transl;
       w = atan(u/(-v));
       t = v/cos(w);
       x = arc_lon0 + conv_lat0 * w;
       y = atan(cotan_lat0 + t)/CONV + arc_lat0;
    }
    sp.sph[LONGITUDE] = x;
    sp.sph[LATITUDE]  = y;

    if (arc_start==1 && fabs(x-arc_x)+fabs(y-arc_y)<0.05)
       arc_start = 2;
    if (arc_start==3)
       printf("%.6f %.6f\n", x, y);

    pt2 = project(scene, spher2cart(scene, sp));
 
 split_arc:
    if (new_arc) {
       if (num_mod!= -1) {
	  i = (++arc_numseg[num_mod]);
          arc_index[num_mod] = (char **)
             realloc(arc_index[num_mod], i * sizeof(char *));
	  nstrokes = 0;
	  seg = (char **)&arc_index[num_mod][i-1];
	  *seg = (char *) malloc(10);
	  spr4(*seg, nstrokes);
	  xi = round2int(3600.0 * x);
          yi = round2int(3600.0 * y);
	  spr3(*seg+4, xi);
	  spr3(*seg+7, yi);
       } else
	  seg = NULL;
       path_start = 1;
       pt1 = pt2;
       new_arc = 0;
    } else {
       if (visible &&
           abs(pt2.coord[X])<=15000 && abs(pt2.coord[Y])<=15000) {
	  escape_length = LARGE_INTEGER;
	  if (arc_start==3)
	     draw_segment(scene, pt1, pt2, scene->color[C_FG_TICKS].pix);
	  else
	     draw_segment(scene, pt1, pt2, scene->color[C_LON_GRID].pix);
       }
       if (path_start) {
	  new_arc = 1;
	  goto split_arc;
       }
       pt1 = pt2;
       if (seg) {
	  dx = xi;
	  dy = yi;
	  xi = round2int(3600.0 * x);
          yi = round2int(3600.0 * y);
	  dx = xi - dx;
	  dy = yi - dy;
	  if (dx || dy) {
             if (dx<0) {
	        epsx = -1;
	        dx = -dx;
	     } else
	        epsx = 1;
             if (dy<0) {
	        epsy = -1;
	        dy = -dy;
	     } else
	        epsy = 1;
	     dxp = (dx+126)/127;
	     dyp = (dy+126)/127;
	     if (dxp>dyp) n = dxp; else n = dyp;
	     nstrokes += n;
             *seg = (char *)realloc(*seg, 10+2*nstrokes);
             spr4(*seg, nstrokes);
	     for (j=0; j<n; j++) {
                dxp = epsx * ((dx*(j+1))/n - (dx*j)/n);
		dyp = epsy * ((dy*(j+1))/n - (dy*j)/n);
		i = 10 + 2 * (nstrokes-n+j);
		(*seg)[i] =  (char)(dxp&255);
		(*seg)[i+1] =  (char)(dyp&255);
	     }
	  }
       }
    }
}

    if (!arc_file) return; 

    i0 = -1;
    if (arc_numseg) {
       for (u=0; u<140; u++) {
 	  if (check_cat_and_cont(scene, u)) {
	     for (i=0; i<arc_numseg[u]; i++) {
	        pix = scene->color[u%28].pix;
	     redraw:
	        ptr = arc_index[u][i];
	        nstrokes = str4toint(ptr);
		xi = str3toint(ptr+4);
		yi = str3toint(ptr+7);
                sp.sph[LONGITUDE] = ((double)xi)/3600.00;
                sp.sph[LATITUDE]  = ((double)yi)/3600.00;
                pt2 = project(scene, spher2cart(scene, sp));
                for (j=0; j<nstrokes; j++) {
		   k = 10+2*j;
		   xi = xi + (int)((signed char)ptr[k]);
		   yi = yi + (int)((signed char)ptr[++k]);
		   pt1 = pt2;
                   sp.sph[LONGITUDE] = ((double)xi)/3600.00;
                   sp.sph[LATITUDE]  = ((double)yi)/3600.00;
		   if (arc_search && i!=i0) {
                      if (fabs(sp.sph[LONGITUDE]-arc_x)+
                          fabs(sp.sph[LATITUDE]-arc_y)<0.05) {
         	         pix = scene->color[C_FG_TICKS].pix;
			 fprintf(stderr, 
			   "section %d, arc # %d\n", u, i);
		         i0 = i;
                         goto redraw;
		      }
		   }
                   pt2 = project(scene, spher2cart(scene, sp));
	           draw_segment(scene, pt1, pt2, pix);
		}
	     }
	  }
       }
       return;
    }

    pix = scene->color[C_FG_TICKS].pix;
#ifdef ZLIB
    fd = (void *) gzopen(arc_file, "r");
#else
    fd = (void *) fopen(arc_file, "r");
#endif
    if (!fd) return;

    arc_numseg = (int *)malloc(140*sizeof(int));
    bzero(arc_numseg, 140*sizeof(int));
    arc_index = (char ***)malloc(140*sizeof(char **));
    bzero(arc_index, 140*sizeof(char **));
    
    if (arc_lambert) {
       cotan_lat0 = tan((90.0-arc_lat0) * PI / 180.0);
       conv_lat0 = 180.0/(PI * sin(arc_lat0 * PI / 180.0));
    }
    ind = 0;
#ifdef ZLIB
    while ((ptr=gzgets((gzFile *)fd, buf, 510))) {
#else
    while ((ptr=fgets(buf, 510, (FILE *)fd))) {
#endif
       ind = ind + strlen(ptr);
       if (!strncasecmp(ptr, "arc", 3)) break;
    }

    indpr = ind;
#ifdef ZLIB
    while ((ptr=gzgets((gzFile *)fd, buf, 510))) {
#else
    while ((ptr=fgets(buf, 510, (FILE *)fd))) {
#endif
       ind = ind+strlen(ptr);
       if (*ptr == '%') continue;
       if (!strncasecmp(ptr, "typ =", 5)) {
	  num_mod = atoi(ptr+5);
	  if (num_mod<0 || num_mod>=140) num_mod = -1;
	  if (num_mod == -1)
             pix = scene->color[C_FG_TICKS].pix;
	  else
             pix = scene->color[num_mod%28].pix;
	  continue;
       }
       if (arc_start == 2) {
#ifdef ZLIB
	  gzseek((gzFile *)fd, indpr, SEEK_SET);
#else
	  fseek((FILE *)fd, indpr, SEEK_SET);
#endif
	  ind = indpr;
	  printf("new = %d\n", ind);
#ifdef ZLIB
	  ptr = gzgets((gzFile *)fd, buf, 510);
#else
	  ptr = fgets(buf, 510, (FILE *)fd);
#endif
	  ind = ind + strlen(ptr);
	  arc_start = 3;
	  new_arc = 1;
       } 
       if (!strncmp(ptr, "     ", 5) || !strncasecmp(ptr, "new =", 5)) {
	  new_arc = 1;
	  if (num_mod == -1)
             pix = scene->color[C_FG_TICKS].pix;
	  else
             pix = scene->color[num_mod%28].pix;
	  indpr = ind;
	  if (arc_start) fprintf(stderr, "      ind = %d\n", ind);
	  if (arc_start >= 2) arc_start = 1;
	  continue;
       }

       if (ptr[0]>='A' && ptr[0]<='Z') break;
       if (!strncasecmp(ptr, "end", 3)) break;

       if (arc_precision<=6 && strlen(ptr)>28) {
          sep = ptr[28];
          ptr[28] = '\0';
          n = sscanf(ptr, "%lg %lg", &a, &b);
	  if (n<2) continue;
          next_segment(a, b);
          ptr[28] = sep;
          p = sscanf(ptr+28, "%lg %lg", &c, &d);
          if (p>=2) next_segment(c, d);
       } else {
          n = sscanf(ptr, "%lg %lg", &a, &b);
	  if (n<2) continue;
	  next_segment(a, b);
       }
    }
#ifdef ZLIB
    gzclose((gzFile *)fd);
#else
    fclose((FILE *)fd);
#endif
}

void warning_output(char *name)
{
    fprintf(stderr, msg[COULDNT_OPEN_OUTPUT_FILE_FOR_ASCII_DUMP], name);
    fprintf(stderr, "\n");
    exit(0);
}

#ifdef SEG_SELECT
int seg_select(int i)
{
   int answer;
   if (seg_mode<=1 || !seg_marked) return 1;
   answer = seg_mode-2;
   if (seg_marked[i]) 
      return answer;
   else
      return !answer;
}

void mark_segments(int numseg)
{
    int i, j;
    if (!seg_marked && numseg>0) {
        seg_marked = malloc(numseg*sizeof(char));
        bzero(seg_marked, numseg);
        if (seg_nummarked) {
            for (i=0; i<seg_nummarked; i++) {
       	        j = seg_specified[i];
	        if (j>=0 && j<numseg) seg_marked[j] = 1;
	    }
	}
    }
}

#endif /* SEG_SELECT */

void dump_arcs(ImageLayout *scene)
{
    FILE *fd;
    char * seg;
    char magic[16];
    char filename[280];
    int mem_numseg[140];
    int i, j, k, u, numseg, maxlength, nstrokes, bool_write;
    int xi, yi, minlong, maxlong, minlat, maxlat;
    int index1 = 0, index2 = 0;
    int address0, address1, address2, count = 0;
    int total_numseg, total_address0, total_address2;

    if (!dump_file) return;

    if (dump_format != DUMP_ASCII) dump_split = 0;
    
    fd =  NULL;
    if (!strcasecmp(dump_file, "-")) {
       if (dump_split) {
	  fprintf(stderr, "%s\n", msg[CANNOT_SPLIT_STDOUT_OUTPUT]);
	  dump_split = 0;
       }
       fd = stdout;
    } else
      if (!dump_split) {
          fd = fopen(dump_file, "w");
          if (!fd) warning_output(dump_file);
      }

    /* Compute index table and maxlength of segments */
    if (use_memory)
       numseg = str4toint(&header->index[556]);
    else
       numseg = 0;

#ifdef SEG_SELECT
    mark_segments(numseg);
#endif

    address0 = sizeof(Header) + numseg*sizeof(Segment_index);
    maxlength = 0;
    total_numseg = 0;
    for (u=0; u<140; u++) {
       mem_numseg[u] = 0;
       if (check_cat_and_cont(scene, u)) {
          if (use_memory) {
	     if (u==0)
                index1 = 0;
	     else
	        index1 = str4toint(&header->index[4*(u-1)]);
	     index2 = str4toint(&header->index[4*u]);
	     j = index2 - index1;
             if (index1>0)
                address2 = str4toint(segment_index[index1-1].address);
             else
                address2 = address0;
	     for (i=index1; i<index2; i++) {
	        address1 = address2;
                address2 = str4toint(segment_index[i].address);
#ifdef SEG_SELECT
                if (!seg_select(i)) {
		   --j; 
                   continue;
		}
#endif
                nstrokes = (address2-address1-6)/2;
		if (nstrokes>maxlength) maxlength = nstrokes;
	     }
	     mem_numseg[u] = j;
	  }
          if (arc_numseg) {
	     for (i=0; i<arc_numseg[u]; i++) {
	        seg = arc_index[u][i];
	        nstrokes = str4toint(seg);
		if (nstrokes>maxlength) maxlength = nstrokes;
	     }
	  }
       }
       total_numseg += mem_numseg[u] + ((arc_numseg)? arc_numseg[u] : 0);
    }
    total_address0 = sizeof(Header) + total_numseg*sizeof(Segment_index);

    if (dump_format == DUMP_ASCII) {
       k = 0;
       index2 = 0;
       for (u=0; u<140; u++) {
	  if (use_memory) {
             index1 = index2;
             index2 = str4toint(&header->index[4*u]);
	  }
          if (!check_cat_and_cont(scene, u)) continue;
	  if (dump_split) {
	     if (fd) fclose(fd);
	     sprintf(filename, "%s.%03d", dump_file, u);
	     if (dump_verbose) {
                fprintf(stderr, msg[OPENING_FILE], filename);
                fprintf(stderr, "\n");
	     }
             fd = fopen(filename, "w");
             if (!fd) warning_output(filename);
	  }	     
	  if (u==0 || dump_split) {
             fprintf(fd, "%s",
                "%% Coordinate output (lon,lat) "
                "of arc strokes in vector map data\n");
             fprintf(fd, "\narcinfo\n");
	  }
	  if (dump_verbose && (mem_numseg[u] || 
		((arc_numseg)? arc_numseg[u] : 0)) ) {
	     fprintf(stderr, msg[WRITING_ARCS_OF_TYPE], 
		     u, continent_name[u/28], u%28);
	     fprintf(stderr, "\n");
	  }
	  bool_write = 0;
          if (use_memory) {
             if (mem_numseg[u]) {
	        bool_write = 1;
		fprintf(fd, "\n%%%% %s/%d\n", continent_name[u/28], u%28);
	        fprintf(fd, "typ = %d\n", u);
	     }
	     if (index1)
                address2 = str4toint(segment_index[index1-1].address);
	     else
	        address2 = address0;
             for (i=index1; i<index2; i++) {
	        address1 = address2;
	        address2 = str4toint(segment_index[i].address);
#ifdef SEG_SELECT
                if (!seg_select(i)) continue;
#endif
	        nstrokes = (address2-address1-6)/2;
                seg = &fullmap_buffer[address1 - address0];
		xi = str3toint(seg);
		yi = str3toint(seg+3);
		fprintf(fd, "new = %d\n", k);
		fprintf(fd, dump_precision,
			    ((double)xi)/3600.0, ((double)yi)/3600.0);
		++k;
                for (j=0; j<nstrokes; j++) {
		   xi = xi + (int)((signed char)seg[6+2*j]);
		   yi = yi + (int)((signed char)seg[7+2*j]);
		   fprintf(fd, dump_precision,
			    ((double)xi)/3600.0, ((double)yi)/3600.0);
		}
	     }
          }
          if (arc_numseg) {
             if (arc_numseg[u]>0 && !bool_write) {
		fprintf(fd, "\n%%%% %s/%d\n", continent_name[u/28], u%28);
	        fprintf(fd, "typ = %d\n", u);
	     }
	     for (i=0; i<arc_numseg[u]; i++) {
	        seg = arc_index[u][i];
	        nstrokes = str4toint(seg);
		xi = str3toint(seg+4);
		yi = str3toint(seg+7);
		fprintf(fd, "new = %d\n%.5f %.5f\n", count,
			    ((double)xi)/3600.0, ((double)yi)/3600.0);
		++count;
                for (j=0; j<nstrokes; j++) {
		   xi = xi + (int)((signed char)seg[10+2*j]);
		   yi = yi + (int)((signed char)seg[11+2*j]);
		   fprintf(fd, "%.5f %.5f\n",
			    ((double)xi)/3600.0, ((double)yi)/3600.0);
		}
	     }
	  }
       }
       fprintf(fd, "end\n\n");
       goto dump_finish;
    }

    /* This is the DUMP_JPD case */
    /* Write Magic header (12 bytes) + maxlength (4 bytes) */
    bzero(magic, 16);
    strcpy(magic, HEADER_MAGIC);
    for (u=0; u<12; u++) fprintf(fd, "%c", magic[u]);
    fpr4(fd, maxlength);
    if (dump_verbose) {
       fprintf(stderr, msg[WROTE_JPD_MAGIC_STRING], maxlength); 
       fprintf(stderr, "\n");
    }

    /* Write segment counts for the 5*28=140 continents * types
     * 560 bytes in total
     */
    k = 0;
    for (u=0; u<140; u++) {      
       k += mem_numseg[u] + ((arc_numseg)? arc_numseg[u] : 0);
       fpr4(fd, k);
    }
    if (dump_verbose) {
       fprintf(stderr, msg[WROTE_JPD_INDEX_TABLE]);
       fprintf(stderr, "\n");
    }

    /* Write numseg headers of 16 bytes; 
     * the segments themselves will start at address  576+numseg*16
     */
    index2 = 0;
    total_address2 = total_address0;
    for (u=0; u<140; u++) {
       if (use_memory) {
	  index1 = index2;
          index2 = str4toint(&header->index[4*u]);
          if (!check_cat_and_cont(scene, u)) continue;
	  if (index1>0)
	     address2 = str4toint(segment_index[index1-1].address);
	  else
	     address2 = address0;
          for (i=index1; i<index2; i++) {
	     address1 = address2;
	     address2 = str4toint(segment_index[i].address);
#ifdef SEG_SELECT
             if (!seg_select(i)) continue;
#endif
	     total_address2 += address2 - address1;
             fpr3(fd, str3toint(segment_index[i].minlong));
             fpr3(fd, str3toint(segment_index[i].maxlong));
             fpr3(fd, str3toint(segment_index[i].minlat));
             fpr3(fd, str3toint(segment_index[i].maxlat));
             fpr4(fd, total_address2);
	  }
       }
       if (arc_numseg) {
          if (!check_cat_and_cont(scene, u)) continue;
	  for (i=0; i<arc_numseg[u]; i++) {
	     seg = arc_index[u][i];
	     nstrokes = str4toint(seg);
             xi = str3toint(seg+4);
             yi = str3toint(seg+7);
	     minlong = maxlong = xi;
	     minlat = maxlat = yi;
	     for (j=0; j<nstrokes; j++) {
	       xi = xi + (int)((signed char)seg[10+2*j]);
	       yi = yi + (int)((signed char)seg[11+2*j]);
	       if (xi<minlong) minlong = xi;
	       if (xi>maxlong) maxlong = xi;
	       if (yi<minlat) minlat = yi;
	       if (yi>maxlat) maxlat = yi;
	     }
	     total_address2 += 6+2*nstrokes;
             fpr3(fd, minlong);
             fpr3(fd, maxlong);
             fpr3(fd, minlat);
             fpr3(fd, maxlat);
             fpr4(fd, total_address2);
	  }
       }
    }
    if (dump_verbose) {
       fprintf(stderr, msg[WROTE_JPD_SEGMENT_HEADERS], total_numseg);
       fprintf(stderr, "\n");
    }

    index2 = 0;
    for (u=0; u<140; u++) {
       if (use_memory) {
          index1 = index2;
          index2 = str4toint(&header->index[4*u]);
          if (!check_cat_and_cont(scene, u)) continue;
	  if (index1>0)
	     address2 = str4toint(segment_index[index1-1].address);
	  else
	     address2 = address0;
          for (i=index1; i<index2; i++) {
	     address1 = address2;
	     address2 = str4toint(segment_index[i].address);
#ifdef SEG_SELECT
             if (!seg_select(i)) continue;
#endif
             seg = &fullmap_buffer[address1 - address0];
             for (j=0; j<address2-address1; j++)
                fprintf(fd, "%c", seg[j]);
          }
       }
       if (arc_numseg) {
          if (!check_cat_and_cont(scene, u)) continue;
	  for (i=0; i<arc_numseg[u]; i++) {
	     seg = arc_index[u][i];
	     nstrokes = str4toint(seg);
             for (j=0; j<6+2*nstrokes; j++)
                fprintf(fd, "%c", seg[j+4]);
	  }
       }
    }

 dump_finish:
    if (dump_verbose) {
       fprintf(stderr, msg[WROTE_SEGMENT_STROKES_IN_TOTAL], total_numseg);
       fprintf(stderr, "\n\n");
    }

    fflush(fd);
    if (strcasecmp(dump_file, "-")) fclose(fd);

    if (!runlevel)
       exit(0);
}

#define SEG_SCAN
#ifdef SEG_SCAN

int seg_scan(ImageLayout *scene)
{
#define MAXNUM 7000
    int ind[MAXNUM];
    int x0[MAXNUM];
    int y0[MAXNUM];
    int x1[MAXNUM];
    int y1[MAXNUM];
    int ns[MAXNUM];
    int sh[MAXNUM];
    int b[MAXNUM];
    int e[MAXNUM];
    int num[MAXNUM];
    int length[MAXNUM];
    int closed[MAXNUM];
    int *group[MAXNUM];
    int *marked;
    char *seg;
    int i, j, k, g, l, n, u;
    int max, i0, count = 50, numseg, nstrokes, NUM;
    int xi, yi, xi0, yi0;
    int index1 = 0, index2 = 0;
    int address0, address1, address2;

    NUM = 0;
    numseg = str4toint(&header->index[556]);
    marked = malloc(numseg * sizeof(int));
    bzero(marked, numseg * sizeof(int));

    address0 = sizeof(Header) + numseg*sizeof(Segment_index);
    for (u=0; u<140; u++) {
       if (u==0)
          index1 = 0;
       else
	  index1 = str4toint(&header->index[4*(u-1)]);
       index2 = str4toint(&header->index[4*u]);
       i = u%28;
       if (i<16 || i>21) continue;
       if (index1>0)
          address2 = str4toint(segment_index[index1-1].address);
       else
          address2 = address0;
       for (i=index1; i<index2; i++) {
	  address1 = address2;
          address2 = str4toint(segment_index[i].address);
          nstrokes = (address2-address1-6)/2;
          seg = &fullmap_buffer[address1 - address0];
          xi = xi0 = str3toint(seg);
	  yi = yi0 = str3toint(seg+3);
          for (j=0; j<nstrokes; j++) {
  	     xi = xi + (int)((signed char)seg[6+2*j]);
	     yi = yi + (int)((signed char)seg[7+2*j]);
	  }
	  if (xi!=xi0 || yi!=yi0) {
	     ind[NUM] = i;
	     marked[i] = 1;
	     x0[NUM] = xi0;
	     y0[NUM] = yi0;
	     x1[NUM] = xi;
	     y1[NUM] = yi;
	     ns[NUM] = nstrokes;
	     sh[NUM] = abs(xi-xi0)+abs(yi-yi0);
	     ++NUM;
	  }
       }
    }
    printf("Number of non closed segments %d\n", NUM);
    fprintf(stderr, "\nNumber of non closed segments %d\n", NUM);
    fprintf(stderr, "Examining loops of such segments\n");

    for (i=0; i<NUM; i++) {
       b[i] = -1;
       e[i] = -1;
       num[i] = -1;
    }

    n = 0;
    l = 0;
    while (n<=count) {
    fprintf(stderr, " [%d]", n);
    ++l;
    if (l==10) {
       fprintf(stderr, "\n");
       l = 0;
    }
    for (i=0; i<NUM; i++) {
        if (b[i]>=0 && e[i]>=0) continue;
	if (abs(x1[i]-x0[i])+abs(y1[i]-y0[i])<=n) {
	   b[i] = i;
	   e[i] = i;
	   num[i] = n;
	   continue;
        }
        for (j=i+1; j<NUM; j++) {
	   if (b[j]>=0 && e[j]>=0) continue;
	   if (e[i]<0 && b[j]<0 && abs(x0[j]-x1[i])+abs(y0[j]-y1[i])<=n) {
	      e[i] = j;
	      b[j] = i;
	      num[i] = n;
	      if (b[i]>=0) j=NUM;
	   } else
	   if (b[i]<0 && e[j]<0 && abs(x1[j]-x0[i])+abs(y1[j]-y0[i])<=n) {
	      b[i] = j;
	      e[j] = i;
	      num[j] = n;
	      if (e[i]>=0) j=NUM;
	   } else
	   if (b[i]<0 && b[j]<0 && abs(x0[j]-x0[i])+abs(y0[j]-y0[i])<=n) {
	      b[i] = j;
	      b[j] = i;
	      if (e[i]>=0) j=NUM;
	   } else
	   if (e[i]<0 && e[j]<0 && abs(x1[j]-x1[i])+abs(y1[j]-y1[i])<=n) {
	      e[i] = j;
	      e[j] = i;
	      num[i] = n;
	      num[j] = n;
	      if (b[i]>=0) j=NUM;
	   }
	}
    }
    ++n;
    }
    fprintf(stderr, "\n");

    for (i=0; i<NUM; i++) {
        printf("%05d / %d %d (%d): %d %d %d %d ; %d %d (%d)\n", 
               sh[i], i, ind[i], ns[i],
	       x0[i], y0[i], x1[i], y1[i], b[i], e[i], num[i]);
    }

    for (i=0; i<NUM; i++) group[i] = NULL;
    for (i=0; i<NUM; i++) length[i] = 0;
    for (i=0; i<NUM; i++) closed[i] = 0;

    g = 0;

 iter1:
    i = 0;
    while(i<NUM && (e[i] == -1 || !marked[ind[i]])) {
       ++i;
       if (i==NUM) goto finished;
    }
    l = 0;
    length[g] = 1;
    printf("Group %d\n", g);
    group[g] = malloc(sizeof(int));
    group[g][0] = i;
    marked[ind[i]] = 0;
    i0 = i;
    printf(" %d", i);
    ++l;
    if (e[i] == i) {
       if (num[i]<=count) closed[g] = 1;
       printf(" closed [%d]\n\n", num[i]);
       ++g;
       goto iter1;
    }

 iter2:
    i = e[i];
    if (i == -1) {
       printf("  open\n\n");
       ++g;
       goto iter1;
    }
    if (!marked[ind[i]]) {
       printf("  open\n\n");
       ++g;
       goto iter1;
    }
    printf(" %d", i);
    ++l;
    if (l>=10) {
       l=0;
       printf("\n");
    }
    k = length[g];
    length[g] = k+1;
    group[g] = (int *) realloc(group[g], length[g]*sizeof(int));
    group[g][k] = i;
    marked[ind[i]] = 0;
    if (e[i] == i0) {
       max = 0;
       for (k=0; k<length[g]; k++) {
	  j = group[g][k];
          if (num[j]>max) max = num[j];
       }
       if (max<=count) closed[g] = 1;
       printf("  closed [%d]\n\n", max);
       ++g;
       goto iter1;
    }
    goto iter2;

 finished:
    for (i=0; i<NUM; i++) if (marked[ind[i]] && e[i] == -1) {
       marked[ind[i]] = 0;
       e[i] = -2;
       printf("isolated : %d\n", i);
    }

    seg_mode = 3;
    img_output = OUT_DUMP;
    dump_format = DUMP_JPD;

    /* select only the almost closed ones... */
    for (i=0; i<numseg; i++) seg_marked[i] = 0;
    for (g=0; g<NUM; g++) if (length[g]>0 && closed[g]>0) {
       for (i=0; i<length[g]; i++) {
	  j = group[g][i];
	  k = ind[j];
	  seg_marked[k] = 1;
       }
    }
    dump_file = strdup("closed");
    dump_arcs(scene);

    /* select the open ones... */
    for (i=0; i<numseg; i++) seg_marked[i] = 0;
    for (g=0; g<NUM; g++) if (length[g]>0 && closed[g]==0) {
       for (i=0; i<length[g]; i++) {
	  j = group[g][i];
	  k = ind[j];
	  seg_marked[k] = 1;
       }
    }
    dump_file = strdup("open");
    dump_arcs(scene);

    /* select the isolated ones... */
    for (i=0; i<numseg; i++) seg_marked[i] = 0;
    for (i=0; i<NUM; i++) if (e[i] == -2) {
       j = ind[i];
       seg_marked[j] = 1;
    }
    dump_file = strdup("isolated");
    dump_arcs(scene);
    
    for (i=0; i<numseg; i++) 
       if (marked[i] != 0) printf("!! %d (%d)\n", i, marked[i]);
    exit(0);
}
#endif /* SEG_SCAN */

void writeout_stat(ImageLayout *scene, int numseg)
{
    int i, u;
    i = 0;
    if (arc_file) {
       dump_file = strdup("-");
       arcinfo_lines(scene);
       if (arc_numseg)
          for (u=0; u<140; u++) i += arc_numseg[u];
    }
    printf("JPD=%d ARC=%d\n", numseg, i);
    exit(0);
}

#endif /* ARCINFO */

void generate(ImageLayout *scene) {
        /* misc variables */
	SpherePt sp;
	ScreenPt pt1, pt2;
	int u, i, j, k, l, m, n, ret, lon, lat, jump=0;
	int numseg, maxlength, nstrokes, address0 = 0;
	int address1, address2, index1, index2;
	Pixel pix=0;
	/* filehandles */
        void *fh = NULL;
	char line[80];

	cmd_string = realloc(cmd_string, 2);
	*cmd_string = '\0';
	cmd_killed_char = '\0';
	caret_pos = 0;
	setup_change = 0;

	if (textboxes) {
	    free(textboxes);
	    textboxes = NULL;
	}

	if (scene->prepixmap && scene->gopt.lineorder[0]=='0' &&
            !essential_change(scene, scene->backup) &&
            img_output!= OUT_EPS) {
	   l = 0;

           XCopyArea(dpy, scene->prepixmap, scene->pixmap, gc,
                    0, 0, scene->width, scene->height, 0, 0);
	   goto direct2;
	}

	/* initialize the image stuff */
	image_init(scene);

	/* compute the rotation matrix */
	compute_matrix(scene);

	/* Random seed for position of stars */
        u = random() % 191; 

	/* Initialize PostScript right now if OUT_EPS */
        if (img_output == OUT_EPS) initialize_EPS(scene, u);

	/* set the background color or starry sky */
	set_sky(scene, u);

#ifdef DEBUG
	fprintf(stderr,"-- GENERATE --\n");
	fprintf(stderr,"o Options\n");
	fprintf(stderr,"  - slatitude   [%g]\n", scene->ropt.spacing_lat);
	fprintf(stderr,"  - slongitude  [%g]\n", scene->ropt.spacing_lon);
	fprintf(stderr,"  - zoom        [%g]\n", scene->gopt.zoom);
	fprintf(stderr,"  - aspect      [%g]\n", scene->aspect);
	fprintf(stderr,"  - latitude    [%g]\n", scene->gopt.xrot);
	fprintf(stderr,"  - longitude   [%g]\n", scene->gopt.yrot);
	fprintf(stderr,"  - inclination [%g]\n", scene->gopt.zrot);
	fprintf(stderr,"  - projection  [%d]\n", scene->projection);
	fprintf(stderr,"  - mapfile     [%s]\n", scene->mapfile);
        fprintf(stderr,"  - rcfile      [%s]\n", scene->rcfile);
	fprintf(stderr,"  - locfile     [%s]\n", scene->locfile);
	fprintf(stderr,"  - des_cat     [%X]\n", scene->gopt.desired_categories);
	fprintf(stderr,"  - des_cont    [%X]\n", scene->gopt.desired_continents);
	fprintf(stderr,"o ImageLayout (Scene)\n");
	fprintf(stderr,"  - height      [%d]\n", scene->height);
	fprintf(stderr,"  - width       [%d]\n", scene->width);
	fprintf(stderr,"  - transp.     [%d]\n", scene->gopt.transparent);
	fprintf(stderr,"o Colormap\n");
	for (i=0; i<C_ENDCOLOR; i++) 
			if (scene->color[i].bool != INACTIVE)
				fprintf(stderr,"    - (%2d) [%s]  %s\n",i , (scene->color[i].bool)? "on":"off", scene->color[i].name);
	fprintf(stderr, "o Rotation Matrix\n");
	for (i=0; i<3; i++) 
		fprintf(stderr,"    [%10.5f]  [%10.5f]  [%10.5f]\n", 
                    scene->rotation.comp[3*i],  
		    scene->rotation.comp[3*i+1], 
                    scene->rotation.comp[3*i+2]);
	fprintf(stderr,"-- -------- --\n");
#endif /* DEBUG */

        if (scene->mapfile[0] == '\0' ||
            !strcasecmp(scene->mapfile, "none") ||
	    !strcasecmp(scene->mapfile, "null")) {
	   free_data_buffers(scene);
	   use_memory = -1;
	}

	/* Open the mapfile and find graph of the appropriate sectors */
	if (!fullmap_buffer) {
	   if (use_memory >= 0) {
#ifdef ZLIB
 	      fh = (void *)gzopen(scene->mapfile, "r");
              if (fh == NULL) {
	         char *name;
	         name = scene->mapfile+strlen(scene->mapfile)-3;
		 if (strcmp(name, ".gz")) {
	            name = (char *)malloc(512);
		    strcpy(name, scene->mapfile);
		    strcat(name, ".gz");
		    fh = gzopen(name, "r");
		    free(name);
		 }
	      }
#else
              fh = (FILE *)fopen(scene->mapfile, "r");
#endif
              if (use_memory>=0 && fh == NULL) {
	         char *err_msg = malloc(512);
	         sprintf(err_msg, msg[COULDNT_OPEN_VECTOR_MAP],
                                  scene->mapfile);
                 fprintf(stderr, "%s\n", err_msg);
	         if (runlevel) {
                    XSetWindowBackgroundPixmap(dpy, mainwin, scene->pixmap);
                    XClearWindow(dpy, mainwin);
                    draw_win_string(scene, mainwin, err_msg, BOTTOM);
		    XFlush(dpy);
		    usleep(WARNING_TIME);
	         }
	         free(err_msg);
	      }
	   } else
              use_memory = 0;
        cannotuse:
	   if (fh == NULL) {
	      if (index(scene->gopt.lineorder, '0'))
                 strcpy(scene->gopt.lineorder, "0");
	      else
		 *scene->gopt.lineorder = '\0';
#ifdef ARCINFO
 	      if (dump_format == DUMP_STAT) writeout_stat(scene, 0);
#endif
	      goto direct1;
	   }
	}

	/* read the header */
	if (!header) {
            header = (Header *) malloc(sizeof(Header));
#ifdef ZLIB
	    gzread((gzFile *)fh, header, sizeof(Header));
#else
	    fread(header, 1, sizeof(Header), (FILE *)fh);
#endif
	    if (strcmp(header->magic, HEADER_MAGIC)) {
		fprintf(stderr, msg[MAGIC_INFORMATION1],
                        scene->mapfile, header->magic);
		fprintf(stderr, "\n\n");
		fprintf(stderr, msg[MAGIC_INFORMATION2], HEADER_MAGIC);
		fprintf(stderr, "\n%s\n", msg[MAGIC_INFORMATION3]);
		if (fh)
#ifdef ZLIB
		   gzclose((gzFile *)fh);
#else
                   fclose((FILE *)fh);
#endif		
		fh = NULL;
		free(header);
		header = NULL;
		goto cannotuse;
	    }
	}

        numseg = str4toint(&header->index[556]);
#ifdef SEG_SELECT
        mark_segments(numseg);
#endif

#ifdef ARCINFO
	if (dump_format == DUMP_STAT) writeout_stat(scene, numseg);
#endif

	if (!segment_index) {
#ifdef TRACE
           fprintf(stderr, 
               "Allocating index buffer of size %d (%d headers)\n",
               numseg * sizeof(Segment_index), numseg);
#endif	   
	   segment_index = (Segment_index *)
                    malloc(numseg * sizeof(Segment_index));
#ifdef ZLIB
	   gzseek((gzFile *)fh, sizeof(Header), SEEK_SET);
	   gzread((gzFile *)fh, segment_index, 
                      numseg * sizeof(Segment_index));
#else
	   fseek((FILE *)fh, sizeof(Header), SEEK_SET);
	   fread(segment_index, 1,
                    numseg * sizeof(Segment_index), (FILE *)fh);
#endif
	}

	address0 = sizeof(Header) + numseg*sizeof(Segment_index);

	if (use_memory && !fullmap_buffer) {
	   i = str4toint(segment_index[numseg-1].address) - address0;
#ifdef TRACE
	   fprintf (stderr, 
	        "Addresses %d + %d = %d\n", address0, i, address0+i);
           fprintf(stderr, 
               "Allocating index fullmap buffer of size %d (%d segments)\n",
               i * sizeof(Segment_index), numseg);
#endif	   
	   fullmap_buffer = (signed char *) malloc(i);
#ifdef ZLIB
           gzseek((gzFile *)fh, address0, SEEK_SET);
           gzread((gzFile *)fh, fullmap_buffer, i);
	   gzclose((gzFile *)fh);
#else
           fseek((FILE *)fh, address0, SEEK_SET);
           fread(fullmap_buffer, 1, i, (FILE *)fh);
	   fclose((FILE *)fh);
#endif
	   fh = NULL;
	   segment_buffer = fullmap_buffer;
        }

	if (!segment_buffer) {
	   maxlength = str4toint(header->maxlength);
#ifdef TRACE
           fprintf(stderr, 
               "Allocating segment buffer of size %d (max %d strokes)\n",
               6+2*maxlength, maxlength);
#endif	   
	   segment_buffer = (char *) malloc(6+2*maxlength);
	}

        jump = (int)(scene->earth_radius*scene->accuracy/
                     (20.0*scene->gopt.zoom));
	if (jump==0) jump=1;

        direct1:
	/* open output file if needed */
	if (img_output!=OUT_NONE && img_output!=OUT_DUMP) open_outfile(scene);

	/* draw gridlines and segments with appropriate lineorder ordering */
	for (l=strlen(scene->gopt.lineorder)-1; l>=0; l--)
	if (scene->gopt.lineorder[l]=='0') {
	   if (l==0)
              XCopyArea(dpy, scene->pixmap, scene->prepixmap, gc,
			     0, 0, scene->width, scene->height, 0, 0);
	   direct2:
	   /* draw grid and contour */
           draw_circles(scene);
	   draw_circle_coordinates(scene);

 	   /* iterate through locations and show spot/texts */
	   scene->currentpixel = (reverse)?white:black;
	   scene->red_current = (reverse)?65535:0;
           scene->green_current = scene->red_current;
           scene->blue_current = scene->red_current;
	   scene->currentfont = 0;
	   for (i=0; i<scene->numdef; i++)
	      if (scene->def[i][0]==(char)1) {
                 draw_feature(scene, scene->def[i]);
		 scene->def[i][0] = (char)255;
	      }
	   if (img_output == OUT_EPS)
	      print_string("%% locations\n[] 0 ds\n");

	   /* draw first large cities and high peaks, and then smaller ones */
	   /* this is just a very ugly hack to do this ... */
	   if (scene->ropt.smartlabels) {
	      ret = 30;
	      index1 = 3000000; 
	      address1 = 8000;
	   } else {
	      ret = 1;
	      index1 = 0; 
	      address1 = 0;
	   }
           index2 = 1000000000;
           address2 = 100000;

           for (u=0; u<ret; u++) {
	      for (i=0; i<numloc; i++) {
		 if (locations[i]->obj == 'c') {
	            m = locations[i]->population;
	            if (m>=index1 && m<index2) {
	               locations[i]->draw &= 0x3fffffff;
	               draw_location(scene, locations[i]);
	            }
		 } else
		 if (locations[i]->obj == 'p') {
                    m = locations[i]->alt;
	            if (m>=address1 && m<address2) {
	               locations[i]->draw &= 0x3fffffff;
	               draw_location(scene, locations[i]);
	            }
                 } else {
		     if (u>0) {
		        locations[i]->draw &= 0x3fffffff;
	                draw_location(scene, locations[i]);
		     }
		 }
	      }
	      index2 = index1;
	      index1 = (5*index1)/6;
	      if (index1<16000) index1 = 0;
	      address2 = address1;
	      address1 = (11*address1)/12;
	      if (address1<650) address1 = 0;
	   }

	   if (img_output == OUT_EPS && scene->numdef>0)
	      print_string("0 0 0 RGB 1.0 clw\n");
	   for (i=0; i<scene->numdef; i++)
	      if (!scene->def[i][0])
                 draw_feature(scene, scene->def[i]);
	}
	else
	for (u=0; u<140; u++) {
	    i = u/28; /* number of continent */
	    if ( !((1<<i) & scene->gopt.desired_continents) ) continue;

            /* number of item */
	    j = u%28; 

            /* type of item, INT=0, NAT=1, RIV=2 or CIL=3 */
	    if (j <= 2) 
               k = 0;
            else
	    if (j <= 4) 
               k = 1;
	    else
	    if (j <= 15) 
               k = 2;
	    else
	       k = 3;
	    if (k!=scene->gopt.lineorder[l]-'1') continue;

	    if ( !((1<<k) & scene->gopt.desired_categories) ) continue;

	    if (scene->color[j].bool!=ON) {
#ifdef TRACE
	       fprintf(stderr, "Skipping u = %d (type = %d)\n", u, j);
#endif
               continue;
	    }

	    /* initialize escape length */
	    escape_length = scene->width/2;

#ifndef SEG_SELECT
            pix = scene->color[j].pix;
#endif

  	    if (img_output == OUT_EPS) {
	       sprintf(line, "%%%% continent: %s\ns%d\n", 
		       continent_name[i], j);
	       print_string(line);
	    }

#ifdef TRACE
	    fprintf(stderr, "Section u = %d (type = %d)\n", u, j);
#endif
            if (u==0)
	       index1 = 0;
	    else
               index1 = str4toint(&header->index[4*(u-1)]);
	    index2 = str4toint(&header->index[4*u]);
#ifdef TRACE
	    fprintf(stderr, "ind1 = %d, ind2 = %d\n", index1, index2);
#endif

	    for (i=index1; i<index2; i++) {
#ifdef SEG_SELECT
               if (seg_mode) {
		  if (!seg_select(i)) continue;
	       }
#endif
	       ret = segment_in_scene(scene, &segment_index[i]);

	       if (ret == YES) {
		  if (i)
 	              address1 = str4toint(segment_index[i-1].address);
                  else
		      address1 = address0;
		  address2 = str4toint(segment_index[i].address);
		  nstrokes = (address2-address1-6)/2;

		  if (fullmap_buffer) {
                      segment_buffer = &fullmap_buffer[address1 - address0];
		  } else {
#ifdef ZLIB
	              gzseek((gzFile *)fh, address1, SEEK_SET);
	              gzread((gzFile *)fh, segment_buffer, address2-address1);
#else
	              fseek((FILE *)fh, address1, SEEK_SET);
	              fread(segment_buffer, 1, address2-address1, (FILE *)fh);
#endif
		  }
#ifdef SEG_SELECT
	       seg_repeat:
#endif
                  lon = str3toint(segment_buffer);
		  lat = str3toint(&segment_buffer[3]);
	          sp.sph[LONGITUDE] = ((double)lon)/3600.0;
	          sp.sph[LATITUDE]  = ((double)lat)/3600.0;
                  pt2 = project(scene, spher2cart(scene, sp));

#ifdef SUPERTRACE
	          fprintf(stderr, "i = %d  addr1 = %d, addr2 = %d  n = %d\n"
			          "  orig_lat = %g  orig_lon = %g\n",
                       i, address1, address2, nstrokes, 
                       s2.sph[LATITUDE], s2.sph[LONGITUDE]);
#endif  	

		  path_start = 1;
#ifdef SEG_SELECT
                  if (seg_marked[i]) 
		     pix = scene->color[C_FG_TICKS].pix;
		  else
                     pix = scene->color[j].pix;
#endif
	          for (n=0; n<nstrokes; n++) {
		     /* iterate and draw all the appropriate points */
		     pt1 = pt2;
		     m = 6+2*n;
		     lon += (int)segment_buffer[m];
		     lat += (int)segment_buffer[m+1];
#ifdef SUPERTRACE
                     fprintf(stderr, "dx = %d, dy = %d\n",
			     (int)segment_buffer[m],
                             (int)segment_buffer[m+1]);
#endif
		     if (n<nstrokes-1 && n%jump>0) continue;
	             sp.sph[LONGITUDE] = ((double)lon)/3600.0;
	             sp.sph[LATITUDE]  = ((double)lat)/3600.0;
#ifdef SEG_SELECT
		     if (seg_mode>=1 && !seg_marked[i]) {
                        if (fabs(sp.sph[LONGITUDE]-arc_x)+
			    fabs(sp.sph[LATITUDE]-arc_y)<0.05) {
                              printf("index %d\n", i);
			      seg_marked[i] = 1;
			      goto seg_repeat;
			}
		     }
#endif
	             pt2 = project(scene, spher2cart(scene, sp));
	             draw_segment(scene, pt1, pt2, pix);
		  }
		  if (img_output == OUT_EPS) {
		     sprintf(line, "k\n");
		     print_string(line);
		  }
	       } else 
               if (ret == POINT_ONLY) {
		  /* the whole segment amounts to a point 
                     based on the perspective of the scene, 
                     so just draw a point	*/
		  sp.sph[LONGITUDE] = 
                     str3toint(segment_index[i].maxlong)/3600.0;
		  sp.sph[LATITUDE] = 
                     str3toint(segment_index[i].maxlat)/3600.0;
		  pt1 = project(scene, spher2cart(scene, sp));
                  draw_pointseg(scene, pt1.coord[X], pt1.coord[Y], pix);
	       }
	    }
	}

        if (fh)
#ifdef ZLIB
	   gzclose((gzFile *)fh);
#else
	   fclose((FILE *)fh);
#endif

#ifdef ARCINFO
	if (arc_file) arcinfo_lines(scene);
	if (dump_file) dump_arcs(scene);
#endif
        XSetWindowBackgroundPixmap(dpy, mainwin, scene->pixmap);
        XClearWindow(dpy, mainwin);

	if (cmdwin_on) {
	   if (memcmp(scene, scene->backup, sizeof(ImageLayout)))
	      draw_win_cmd(scene, 0);
	}
	memcpy(scene->backup, scene, sizeof(ImageLayout));

	if (img_output != OUT_NONE) {
	   if (img_output == OUT_EPS) {
              sprintf(line, 
                 "frame_style\n"
                 "draw_frame { 0 0 m %d 0 l %d %d l 0 %d l 0 0 l k } if\n"
                 "2 slj\n\n",
                 scene->width, scene->width, scene->height, scene->height);
              print_string(line);
              print_string("%\ngrestore\nshowpage\n%%Trailer\n");
              close_outfile();
	   } else
	      print_image(scene);
	}
	if (textboxes) {
	    free(textboxes);
	    textboxes = NULL;
	}
}

/* 
 *  SECTION 5 : USER INTERFACE ROUTINES
 */

void search_city(ImageLayout * scene)
{
int i, l;
char *needle;
char *ptr = NULL;
char fieldname[256];
unsigned char c;
double lat = 0.0, lon=0.0, delta, deltax, deltay, deltamin = 1E20;
char lat_str[80], lon_str[80];
 
    if (search_by==6) {
       num_found = scene->num_positions;
       return;
    }
    l = strlen(search_string); 
    needle = (char *)malloc(sizeof(char)*(l+2));

    for (i=0; i<=l; i++) {
       c = search_string[i];
       if (ptr) {
	 if (c == ',' || c == '|')
            needle[i] = ' ';
	 else
            needle[i] = c;
       }
       else
       if (c<='Z') {
	 if (c=='-') c=' ';
	 if (c>='A' && c<='Z') c += 32;
	 needle[i] = c;
       } else
       if (c>=192)
	 needle[i] = cvs[c-192];
       else {
	 if (c=='|') {
            needle[i] = '\0';
	    ptr = needle+i+1;
	 } else
            needle[i] = c;
       }
    }
    if (search_by>4) ptr = NULL;
    if (ptr) {
       if (sscanf(ptr, "%s %s", lat_str, lon_str)<2) 
          ptr = NULL;
       else {
          lat = dms2decim(lat_str);
          lon = dms2decim(lon_str);
       }
    }
    num_found = 0;
    start_list = 0;
    for (i=0; i<numloc; i++) {
       if (search_by==1) {
          strcpy(fieldname, locations[i]->name);
	  if (locations[i]->obj!='c') simplify_string(fieldname);
       } else
       if (search_by==2) {
	  if (locations[i]->obj!='c') continue;
          strcpy(fieldname, 
                 countries[timezones[locations[i]->tz]->country]->name);
       }
       else
       if (search_by==3) {
	  if (locations[i]->obj!='c') continue;
          strcpy(fieldname, locations[i]->region);
       }
       else
       if (search_by==4) {
	  if (locations[i]->obj!='l' || locations[i]->rank==-1) continue;
          strcpy(fieldname, locations[i]->name); 
	  if (l==0) {
	     strcpy(needle, "*");
	     l = 1;
	  }
	  simplify_string(fieldname);
       }
       else
       if (search_by==5) {
	  if (l==0) {
	     strcpy(needle, "*");
	     l = 1;
	  }
          if (i>=numpresel) break;
       }
       if (!string_cmp(fieldname, needle)) {
	  if (ptr) {
	     if (!num_found) {
	        loc_pointer = (int *)realloc(loc_pointer, sizeof(int));
	        ++num_found;
	     }
	     deltax = fabs(lat-locations[i]->lat);
	     deltay = fabs(lon-locations[i]->lon);
	     delta = deltax*deltax + deltay*deltay;	     
	     if (delta<deltamin) {
	        deltamin = delta;
		loc_pointer[0] = i;
	     }
	  } else {
	     loc_pointer=(int*)realloc(loc_pointer,(num_found+1)*sizeof(int));
	     loc_pointer[num_found] = (search_by<=4)? i : presel_pointer[i];
             ++num_found;
	  }
       }
    }
    if (num_found==1) 
       search_index = loc_pointer[0];
    else
       search_index = -1;
    free(needle);
}

void twist_string(ImageLayout *scene, int i, char *str)
{
    if (scene->color[i].bool == OFF)
       strcpy(str, "-");
    else
    if (scene->color[i].bool == ON &&
        scene->color[i+1].bool == OFF) 
       strcpy(str, "+");
    else
    if (scene->color[i].bool == ON &&
        scene->color[i+1].bool == ON)
       strcpy(str, "++");
}

void value2str(ImageLayout * scene, int i, char * str, int mode)
{
        int j;
	char c;

        *str = '\0';   

	if (cmd_mode==MODE_FILE) {
	   if (cmd_type==M_FILE_DATA) {
	      switch(i) {
		 case 1:  strcpy(str, scene->rcfile); break;
		 case 2:  strcpy(str, scene->mapfile); break;
		 case 3:  strcpy(str, (dump_file)? dump_file : ""); break;
		 case 4:  strcpy(str, scene->locfile); break;
		 case 5:  strcpy(str, scene->theme); break;
		 case 6:  if (datapix_name) 
		             strcpy(str, datapix_name); 
		          else
			     *str = '\0';
		          break;
                 default: break;
	      }
	   }
	   if (cmd_type==M_FILE_EXTERNAL) {
	      switch(i) {
	         case 1:  strcpy(str, ps_viewer); break;
	         case 2:  strcpy(str, im_viewer); break;
	         case 3:  strcpy(str, html_viewer); break;
	         case 4:  strcpy(str, svg_viewer); break;		 
	         case 5:  strcpy(str, svg_convert); break; 
	         case 6:  strcpy(str, editor_cmd); break;
	         case 7:  strcpy(str, midi_cmd); break;
	         default: break;
	      }
	   }
	   if (cmd_type==M_FILE_PRINTCFG) {
	      switch(i) {
		 case 1:  sprintf(str, "%.1f", ps_width); break;
		 case 2:  sprintf(str, "%.1f", ps_lm); break;
		 case 3:  sprintf(str, "%.1f", ps_bm); break;
		 case 4:  sprintf(str, "%d", ps_rot); break;
		 case 5:  sprintf(str, "%.2f", ps_lw); break;
		 case 6:  str[0] = (ps_frame)? '+':'-'; str[1] = '\0'; 
                          break;
		 case 7:  str[0] = (ps_grayscale)? '+':'-'; str[1] = '\0'; 
                          break;
		 case 8:  str[0] = (im_compress)? '+':'-'; str[1] = '\0'; 
                          break;
	         case 9:  strcpy(str, scene->macrofile); break;
	         case 10:  strcpy(str, print_cmd); break;
                 default: break;
	      }
	   }
	   if (cmd_type==M_FILE_SAVE && i==1)
	      strcpy(str, scene->outfile);
        }
	if (cmd_mode==MODE_OPTION) {
	   if (cmd_type==M_OPTION_PARAM) {
	      switch(i) {
		 case 1:  if (mode) 
                             sprintf(str, "%d = %s", scene->projection,
                                  projtype[scene->projection]); 
                          else
                             sprintf(str, "%d", scene->projection);
                          break;
		 case 2:  sprintf(str, "%.3f", scene->accuracy); break;
		 case 3:  sprintf(str, "%d", scene->width); break;
		 case 4:  sprintf(str, "%d", scene->height); break;
		 case 5:  sprintf(str, "%.3f", scene->gopt.zoom); break;
		 case 6:  sprintf(str, "%.3f", scene->aspect); break;
		 case 7:  sprintf(str, "%.3f", scene->gopt.xrot); break;
		 case 8:  sprintf(str, "%.3f", scene->gopt.yrot); break;
		 case 9:  sprintf(str, "%.3f", scene->gopt.zrot); break;
		 case 10: sprintf(str, "%.3f", scene->ropt.spacing_lat); break;
		 case 11: sprintf(str, "%.3f", scene->ropt.spacing_lon); break;
	         case 12: sprintf(str, "%c%c", 
                             get_grid_coordinates(scene->ropt.latcoord, 0), 
			     get_grid_coordinates(scene->ropt.loncoord, 1));
		          break;
	         case 13: sprintf(str, "%c", (dms)? '+' : '-'); break;
  	         case 14: if (scene->gopt.transparent)
                             strcpy(str, "+"); 
                          else 
                             strcpy(str, "-");
		          break;
  	         case 15: if (secure)
                             strcpy(str, "+"); 
                          else 
                             strcpy(str, "-");
		          break;
	         default: break;
	      }
	   }
	   if (cmd_type==M_OPTION_HIERARCHY) {
	      switch(i) {
		 case 1: sprintf(str, "%s (mrk=0, int=1, nat=2, riv=3, cil=4)",
                                 scene->gopt.lineorder);
		         break;
		 case 2: sprintf(str, "%d,%d,%d,%d,%d", 
			    scene->ropt.mark_step[0], scene->ropt.mark_step[1], 
                            scene->ropt.mark_step[2], scene->ropt.mark_step[3], 
                            scene->ropt.mark_step[4]); 
                         break;
		 case 3: sprintf(str, "%d,%d,%d,%d,%d", 
			    scene->ropt.name_step[0], scene->ropt.name_step[1], 
                            scene->ropt.name_step[2], scene->ropt.name_step[3], 
                            scene->ropt.name_step[4]); 
                         break;
		 case 4: sprintf(str, "%d,%d,%d,%d,%d", 
			    scene->ropt.airport_mark[0], scene->ropt.airport_mark[1], 
                            scene->ropt.airport_mark[2], scene->ropt.airport_mark[3], 
                            scene->ropt.airport_mark[4]); 
                         break;
		 case 5: sprintf(str, "%d,%d,%d,%d,%d", 
			    scene->ropt.airport_size[0], scene->ropt.airport_size[1], 
                            scene->ropt.airport_size[2], scene->ropt.airport_size[3], 
                            scene->ropt.airport_size[4]); 
                         break;
		 case 6: sprintf(str, "%d,%d,%d,%d,%d", 
			    scene->ropt.peak_mark[0], scene->ropt.peak_mark[1], 
                            scene->ropt.peak_mark[2], scene->ropt.peak_mark[3], 
                            scene->ropt.peak_mark[4]); 
                         break;
		 case 7: sprintf(str, "%d,%d,%d,%d,%d", 
			    scene->ropt.peak_size[0], scene->ropt.peak_size[1], 
                            scene->ropt.peak_size[2], scene->ropt.peak_size[3], 
                            scene->ropt.peak_size[4]); 
                         break;
		 case 8: sprintf(str, "%d,%d,%d,%d,%d", 
			    scene->ropt.city_mark[0], scene->ropt.city_mark[1], 
                            scene->ropt.city_mark[2], scene->ropt.city_mark[3], 
                            scene->ropt.city_mark[4]); 
                         break;
		 case 9: sprintf(str, "%d,%d,%d,%d,%d", 
			    scene->ropt.city_size[0], scene->ropt.city_size[1], 
                            scene->ropt.city_size[2], scene->ropt.city_size[3], 
                            scene->ropt.city_size[4]); 
                         break;
	         case 10: strcpy(str, scene->ropt.city_filter);
		          break;
	         case 11: strcpy(str, scene->ropt.loc_filter);
		          break;
	         case 12: if (scene->ropt.smartlabels) 
                             strcpy(str, "+"); 
                          else 
                             strcpy(str, "-");
		          break;
	         case 13: if (scene->ropt.placetext) 
                             strcpy(str, "+"); 
                          else 
                             strcpy(str, "-");
		          break;
	         case 14: sprintf(str, "%s", flag_descr);
		          break;		 
	         case 15: sprintf(str, "%s (%s)", language, list_lang);
		          break;
	         default: break;
	      }
	   }

	   if (cmd_type==M_OPTION_FONT) {
              if (i>=1 && i<=6)
	         strcpy(str, scene->ropt.font[i-1]);
	   }

	   if (cmd_type==M_OPTION_MARKS) {
	      switch(i) {
              case 1: twist_string(scene, C_CITY_CIRCLE, str);
                      break;

              case 2: twist_string(scene, C_AIRPORT_SYMBOL, str);
                      break;

              case 3: twist_string(scene, C_OBSERV_SYMBOL, str);
                      break;

              case 4: twist_string(scene, C_PEAK_TRIANGLE, str);
                      break;

              case 5: j = scene->color[C_LOC_LAND].bool;
                      strcpy(str, (j)? "+":"-"); break;

              case 6: j = scene->color[C_LOC_WATER].bool;
                      strcpy(str, (j)? "+":"-"); break;

              case 7: j = scene->color[C_LON_GRID].bool;
                      strcpy(str, (j)? "+":"-"); break;

              case 8: j = scene->color[C_LAT_GRID].bool;
                      strcpy(str, (j)? "+":"-"); break;

              case 9: j = scene->color[C_MAIN_LINES].bool;
                      strcpy(str, (j)? "+":"-"); break;

              case 10: j = scene->color[C_EARTH_CONTOUR].bool;
                      strcpy(str, (j)? "+":"-"); break;

              case 11: j = scene->color[C_BG_SKY].bool;
                      strcpy(str, (j)? "+":"-"); break;

              case 12: j = scene->color[C_FG_STARS].bool;
                       strcpy(str, (j)? "+":"-"); break;

	      default: break;
	      }
	   }

	   if (cmd_type==M_OPTION_CONTIN) {
	      if ((1<<(i-1)) & scene->gopt.desired_continents)
		 strcpy(str, "+");
	      else
		 strcpy(str, "-");
	   }
	   if (cmd_type==M_OPTION_CAT) {
	      if ((1<<(i-1)) & scene->gopt.desired_categories)
		 strcpy(str, "+");
	      else
		 strcpy(str, "-");
	   }
	}
        if (cmd_mode==MODE_COLOR) {
	   j = feature_index[cmd_type-1]+i-1;
	   c = (scene->color[j].bool)? '+' : '-';
	   sprintf(str, "%c%s", c, scene->color[j].name);
        }
}

void twist_value(ImageLayout *scene, int i, char *str)
{
    if (!strcmp(str, "-"))
       scene->color[i].bool = OFF;
    else
    if (!strcmp(str, "+")) {
       scene->color[i].bool = ON;
       scene->color[i+1].bool = OFF; 
    } else
    if (!strcmp(str, "++")) {
       scene->color[i].bool = ON;
       scene->color[i+1].bool = ON; 
    }
}

void str2value(ImageLayout * scene, int i, char * str)
{
        int j;
	double f;

	if (cmd_mode==MODE_FILE) {
	   if (cmd_type==M_FILE_DATA) {
	      switch(i) {
		 case 1:  strcpy(scene->rcfile, str); 
		          expand_path(scene->mapfile); break;
		 case 2:  strcpy(scene->mapfile, str); 
		          expand_path(scene->mapfile); break;
		 case 3:  dump_file = realloc(dump_file, 256);
                          strncpy(dump_file, str, 255); 
			  dump_file[255]= '\0';
		          expand_path(dump_file); 
			  if (*dump_file) {
			     img_output = OUT_DUMP;
			     dump_arcs(scene);
			     img_output = OUT_NONE;
			  }
			  break;
		 case 4:  strcpy(scene->locfile, str); 
		          expand_path(scene->locfile); break;
		 case 5:  strcpy(scene->theme, str); 
                          expand_path(scene->theme); 
			  parse_theme(scene); 
			  break;
                 case 6:  parse_pixmaps(scene, str); break;
                 default: break;
	      }
	   }
	   if (cmd_type==M_FILE_EXTERNAL) {
	      switch(i) {
		 case 1:  if (*str) {
                             free(ps_viewer); 
			     ps_viewer = strdup(str);
		          }
                          break;
		 case 2:  if (*str) {
                             free(im_viewer); 
			     im_viewer = strdup(str);
		          }
                          break;
		 case 3:  if (*str) {
                             free(html_viewer); 
			     html_viewer = strdup(str);
		          }
                          break;
		 case 4:  if (*str) {
                             free(svg_viewer); 
			     svg_viewer = strdup(str);
		          }
                          break;		 
		 case 5:  if (*str) {
                             free(svg_convert); 
			     svg_convert = strdup(str);
		          }
                          break;		 
	         case 6: if (*str) {
                             free(editor_cmd);
                             editor_cmd = strdup(str);
	                  }
                          break;
	         case 7: if (*str) {
                             free(midi_cmd);
                             midi_cmd = strdup(str);
	                  }
                          break;
                 default: break;
	      }
	   }
	   if (cmd_type==M_FILE_PRINTCFG) {
	      switch(i) {
		 case 1:  if (atof(str)>0) ps_width = atof(str); break;
		 case 2:  if (atof(str)>0) ps_lm = atof(str); break;
		 case 3:  if (atof(str)>0) ps_bm = atof(str); break;
		 case 4:  ps_rot = (int)atof(str); 
                          if (ps_rot>0) ps_rot = 90; 
                          if (ps_rot<0) ps_rot = -90; 
                          break;
		 case 5:  if (atof(str)>0) ps_lw = atof(str); break;
		 case 6:  ps_frame = (*str=='+'); break;
		 case 7:  ps_grayscale = (*str=='+'); break;
		 case 8:  im_compress = (*str=='+'); break;
		 case 9:  strncpy(scene->macrofile, str, 255);
		          scene->macrofile[255] = '\0';
			  break;
		 case 10:  if (*str) {
                             free(print_cmd); 
			     print_cmd = strdup(str);
		          }
                          break;
                 default: break;
	      }
	      return;
	   }
	   if (cmd_type==M_FILE_SAVE && i==1)
	      strcpy(scene->outfile, str);
	}
	if (cmd_mode==MODE_OPTION) {
	   if (cmd_type==M_OPTION_PARAM) {
	      switch(i) {
		 case 1:  scene->projection = set_proj(str); 
                          show_title(scene, mainwin);
                          break;
	         case 2:  f = atof(str); 
		          if (f<=0.0) break;
			  scene->accuracy = f;
		          break;
		 case 3:  j = atoi(str); 
		          if (j<16) break;
			  scene->width = j;
			  XResizeWindow(dpy, mainwin, 
                                        scene->width, scene->height);
			  XFlush(dpy);
		          break;
		 case 4:  j = atoi(str); 
		          if (j<16) break;
			  scene->height = j; 
			  XResizeWindow(dpy, mainwin, 
                                        scene->width, scene->height);
			  XFlush(dpy);
                          break;
		 case 5:  f = atof(str); 
		          if (f<MINZOOM) break;
		          if (f>MAXZOOM) break;
			  scene->gopt.zoom = f;
		          break;
		 case 6:  f = atof(str); 
		          if (f<0.01) break;
                          scene->aspect = f; 
                          break;
		 case 7:  scene->gopt.xrot = atof(str); break;
		 case 8:  scene->gopt.yrot = atof(str); break;
		 case 9:  scene->gopt.zrot = atof(str); break;
		 case 10: scene->ropt.spacing_lat = atof(str); break;
		 case 11: scene->ropt.spacing_lon = atof(str); break;
	         case 12: if (strlen(str) != 2) break;
		          scene->ropt.latcoord = set_grid_coordinates(str[0]);
                          scene->ropt.loncoord = set_grid_coordinates(str[1]);
		          break;
	         case 13: dms = (*str=='+'); 
                          update_auxil_windows(scene);
                          break;
	         case 14: scene->gopt.transparent = (*str == '+'); break;
	         case 15: secure= (*str == '+') ; break;
		 default: break;
	      }
	   }
	   if (cmd_type==M_OPTION_HIERARCHY) {
	      switch(i) {
                 case 1: strncpy(scene->gopt.lineorder, str, 5);
		         scene->gopt.lineorder[5] = '\0';
			 check_lineorder(scene);
                         break;
		 case 2: if ((j=sscanf(str, "%d,%d,%d,%d,%d",
                            &scene->ropt.mark_step[0], &scene->ropt.mark_step[1], &scene->ropt.mark_step[2],
                            &scene->ropt.mark_step[3], &scene->ropt.mark_step[4]))<5)
		             while(j<5) { scene->ropt.mark_step[j]=scene->ropt.mark_step[j-1]; ++j; }
                         break;
		 case 3: if ((j=sscanf(str, "%d,%d,%d,%d,%d",
                            &scene->ropt.name_step[0], &scene->ropt.name_step[1], &scene->ropt.name_step[2],
                            &scene->ropt.name_step[3], &scene->ropt.name_step[4]))<5)
		             while(j<5) { scene->ropt.name_step[j]=scene->ropt.name_step[j-1]; ++j; }
                         break;
		 case 4: if ((j=sscanf(str, "%d,%d,%d,%d,%d",
                            &scene->ropt.airport_mark[0], &scene->ropt.airport_mark[1], 
                            &scene->ropt.airport_mark[2], &scene->ropt.airport_mark[3], 
                            &scene->ropt.airport_mark[4]))<5)
		         while(j<5) { 
                            scene->ropt.airport_mark[j] = scene->ropt.airport_mark[j-1]; 
                            ++j; 
                         }
                         break;
		 case 5: if ((j=sscanf(str, "%d,%d,%d,%d,%d",
                            &scene->ropt.airport_size[0], &scene->ropt.airport_size[1], &scene->ropt.airport_size[2],
                            &scene->ropt.airport_size[3], &scene->ropt.airport_size[4]))<5)
		             while(j<5) { scene->ropt.airport_size[j]=scene->ropt.airport_size[j-1]; ++j; }
                         break;
		 case 6: if ((j=sscanf(str, "%d,%d,%d,%d,%d",
                            &scene->ropt.peak_mark[0], &scene->ropt.peak_mark[1], 
                            &scene->ropt.peak_mark[2], &scene->ropt.peak_mark[3], 
                            &scene->ropt.peak_mark[4]))<5)
		         while(j<5) { 
                            scene->ropt.peak_mark[j] = scene->ropt.peak_mark[j-1]; 
                            ++j; 
                         }
                         break;
		 case 7: if ((j=sscanf(str, "%d,%d,%d,%d,%d",
                            &scene->ropt.peak_size[0], &scene->ropt.peak_size[1], &scene->ropt.peak_size[2],
                            &scene->ropt.peak_size[3], &scene->ropt.peak_size[4]))<5)
		             while(j<5) { scene->ropt.peak_size[j]=scene->ropt.peak_size[j-1]; ++j; }
                         break;
		 case 8: if ((j=sscanf(str, "%d,%d,%d,%d,%d",
                            &scene->ropt.city_mark[0], &scene->ropt.city_mark[1], 
                            &scene->ropt.city_mark[2], &scene->ropt.city_mark[3], 
                            &scene->ropt.city_mark[4]))<5)
		         while(j<5) { 
                            scene->ropt.city_mark[j] = scene->ropt.city_mark[j-1]; 
                            ++j; 
                         }
                         break;

		 case 9: if ((j=sscanf(str, "%d,%d,%d,%d,%d",
                            &scene->ropt.city_size[0], &scene->ropt.city_size[1], &scene->ropt.city_size[2],
                            &scene->ropt.city_size[3], &scene->ropt.city_size[4]))<5)
		             while(j<5) { scene->ropt.city_size[j]=scene->ropt.city_size[j-1]; ++j; }
                         break;
	         case 10: load_city_filter(scene, str);
			 break;
	         case 11: load_loc_filter(scene, str);
			 break;
	         case 12: scene->ropt.smartlabels = (*str == '+'); break;
	         case 13: scene->ropt.placetext = (*str == '+'); break;
	         case 14: free(flag_descr); flag_descr = strdup(str);
		          if (set_flag_dirs()) {
			     free_flag_data();
                             list_flag_dirs();
			  }
		          break;		 
	         case 15: strncpy(language, str, 2);
		         language[2] = '\0';
	                 read_i18n_file(scene);
     	                 fix_features_description(scene);
			 break;
		 default: break;
	      }
	   }
	   if (cmd_type==M_OPTION_FONT) { 
              if (i>=1 && i<=6) {
		 i -= 1;
		 str[255] = '\0';
	         if (!set_font(str, i))
	            strcpy(scene->ropt.font[i], str);
	      }
	   }

	   if (cmd_type==M_OPTION_MARKS) {
	      switch(i) {
              case 1: twist_value(scene, C_CITY_CIRCLE, str);
                      break;

              case 2: twist_value(scene, C_AIRPORT_SYMBOL, str);
                      break;

              case 3: twist_value(scene, C_OBSERV_SYMBOL, str);
                      break;

              case 4: twist_value(scene, C_PEAK_TRIANGLE, str);
                      break;

              case 5: scene->color[C_LOC_LAND].bool = !strcmp(str, "+");
                      break;

              case 6: scene->color[C_LOC_WATER].bool = !strcmp(str, "+");
                      break;

              case 7: scene->color[C_LON_GRID].bool = !strcmp(str, "+");
                      break;

              case 8: scene->color[C_LAT_GRID].bool = !strcmp(str, "+");
                      break;

              case 9: scene->color[C_MAIN_LINES].bool = !strcmp(str, "+");
                      break;

              case 10: scene->color[C_EARTH_CONTOUR].bool = !strcmp(str, "+");
                      break;

              case 11: scene->color[C_BG_SKY].bool = !strcmp(str, "+");
                      break;

              case 12: scene->color[C_FG_STARS].bool = !strcmp(str, "+");
                       break;

	      default: break;
	      }
	   }

	   if (cmd_type==M_OPTION_CONTIN) {
              j = 1<<(i-1);
	      if (!strcmp(str, "+")) scene->gopt.desired_continents |= j;
	      if (!strcmp(str, "-")) scene->gopt.desired_continents &= ~j;
	   }
	   if (cmd_type==M_OPTION_CAT) {
              j = 1<<(i-1);
	      if (!strcmp(str, "+")) scene->gopt.desired_categories |= j;
	      if (!strcmp(str, "-")) scene->gopt.desired_categories &= ~j;
	   }
	}

        if (cmd_mode==MODE_COLOR) {
	   j = feature_index[cmd_type-1]+i-1;
	   if (cmd_type==M_COLOR_WIDGETS || j==C_BG_MAP) {
	      scene->color[j].bool = 1;	      
	      if (*str=='-') *str = '+';
	   }
           get_color(str, scene, j);
	   if (color_depth<=8)
	      get_all_colors(scene);
	   if (j==C_BG_TEXT || j==C_FG_TEXT) set_bg_fg(scene);
	   setup_change |= COLOR_CHANGE;
        }
}

void show_brief_menu(ImageLayout * scene)
{
   int i, m = 0;
   static int old_brief_menu = -1;
   char *str;

   if (brief_menu != old_brief_menu) 
      XClearWindow(dpy, mainwin);
   if (!brief_menu) return;
   
   XSetForeground(dpy, gc, scene->color[C_BG_TEXT].pix);

   if (brief_menu == 1) m = BEGIN_MAP_FEATURES - BEGIN_LIST_SHORTCUTS + 1;
   if (brief_menu == 2) m = END_MAP_FEATURES - BEGIN_MAP_FEATURES + 1;
   if (brief_menu == 3) m = 1; 
   if (brief_menu == 4) {
      draw_win_string(scene, mainwin, error_msg, BOTTOM);
      return;
   }

   XFillRectangle(dpy, mainwin, gc, 14, 0, 
                  scene->width-28, (m+1)*(fonth[0]+12) + 26);
   XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix);
   for (i=0; i<=m; i++) {
      if (i == 0) {
	 str = msg[BRIEF_MENU_SHORTCUTS+brief_menu];
      } else {
         if ((brief_menu==1 || brief_menu==2) && i==m) {
	    str = "<<<<>>>>";
         } else {
            XDrawRectangle(dpy, mainwin, gc, 
                  29, i * (fonth[0]+12) + 19,
                  62, fonth[0]+7);
            XDrawRectangle(dpy, mainwin, gc, 
                  30, i * (fonth[0]+12) + 20, 
                  60, fonth[0]+5);      
            if (brief_menu==2)
	       str = msg[BEGIN_MAP_FEATURES+i-1];
	    else
               str = msg[BEGIN_LIST_SHORTCUTS+i-1];
         }
      }
      XDrawString(dpy, mainwin, gc, 
                  38, i * (fonth[0]+12) + fontasc[0] + ((i==0)? 13:23),
                  str, strlen(str));
   }
}

void draw_rect_cmd(ImageLayout * scene, char **paramstr, 
                 int n, int position, int level)
{
        int i, l, m, y;
	char str[256];
	char *ptr;

	box_width = 0;
	box_height = fonth[0]+6;
	box_spacing = fonth[0]+((level<0)?5:10);
	box_numitems = n;
	box_x = 6;
	box_y = (position-TOP+1)*(fonth[0]+16)-box_spacing/2+1;
        y = box_y+box_spacing/2-1; 
	if (level<=1 && n>0) {
           XSetForeground(dpy, gc, scene->color[C_BG_TEXT].pix);
           XFillRectangle(dpy, cmdwin, gc, 0, y, cmdwin_width, (n+1)*box_spacing);
	}
	if (n>0) y += (n+1)*box_spacing;
	if (cmdwin_height-y-fonth[0]-6>0)
           XClearArea(dpy, cmdwin, 0, y, 
                      cmdwin_width, cmdwin_height-y-fonth[0]-6, False);

        for (i=1; i<=n; i++) {
	   ptr = paramstr[i-1];
	   if (!ptr) ptr = "(null)";
	   l = strlen(ptr);
           XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix);
	   XDrawImageString(dpy, cmdwin, gc, 
                            box_x+6, box_y+i*box_spacing+fontasc[0]+3,
	                    ptr, l);
           m = XTextWidth(xfont[0], ptr, l) + 12;
	   if (m>box_width) box_width = m;
	}
        for (i=1; i<=n; i++) {
	   if (level>=0) {
              XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix);
	      XDrawRectangle(dpy, cmdwin, gc, box_x, box_y+i*box_spacing,
		               box_width, box_height);
	   }
	   if (line_clicked==i) {
	      XSetForeground(dpy, gc, scene->color[C_BG_TEXT].pix);
	      XFillRectangle(dpy, cmdwin, gc, 
                               box_x+box_width+1, box_y+i*box_spacing,
		               cmdwin_width-box_x-box_width-1, box_height);
	      XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix);
	      XDrawRectangle(dpy, cmdwin, gc, box_x+1, box_y+i*box_spacing+1,
		               box_width-2, box_height-2);
	   } else {
	      XSetForeground(dpy, gc, scene->color[C_BG_TEXT].pix);
	      XDrawRectangle(dpy, cmdwin, gc, box_x+1, box_y+i*box_spacing+1,
		               box_width-2, box_height-2);
	   }
	   value2str(scene, i, str, 1);
	   if (*str) {
	      XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix);
	      XDrawImageString(dpy, cmdwin, gc, 
                               box_x+box_width+5*char_width, 
                               box_y+i*box_spacing+fontasc[0]+3,
	                       str, strlen(str));

	   }
	}
	XFlush(dpy);
}

void show_manual()
{
int i=0, j, k, l, c, cp;
char cmd[256];
char tmpname[80];
struct stat buf;
char *ptr, *text;
FILE *man;

     secure_tmpnam(tmpname);
     strcat(tmpname, "_xrmap.man");
     sprintf(cmd, "man xrmap > %s", tmpname);
     system(cmd);
     man = fopen(tmpname, "r");
     if (!man) {
        unlink(tmpname);
	return;
     }
     ptr = strdup(tmpname);
     buf.st_mode = 0;
     stat(ptr, &buf);
     free(ptr);
     text = malloc(buf.st_size+2);
     if (!text) {
        fclose(man);
        return;
     }
     while ((c=fgetc(man))!=EOF) {
       iter:
        if (c=='_') {
	   cp = fgetc(man);
	   if (cp==EOF) break;
	   if (cp==8) continue;
	   text[i++] = (char)c;
	   c = cp;
           goto iter;
	} else
	if (c==8) {
	   c = fgetc(man);
	   if (c==EOF) break;
	} else
	   text[i++] = (char)c;
     }
     text[i] = '\0';
     fclose(man);
     man = fopen(tmpname, "w");
     if (!man) {
        free(text);
        return;
     }
     for (j=0; j<i; j++) {
         if (text[j]=='\n' && !strncmp(text+j+1, "Xrmap-", 6)) {
	    k = j;
	    while (isspace(text[k])) k--;
	    while (text[k]!='\n') k++;
	    ptr = strstr(text+j+1, "xrmap(1x)");
	    if (ptr) ptr = strstr(ptr+2, "xrmap(1x)");
	    if (ptr) {
               j = ptr-text+1;
	       while (text[j]!='\n') j++;
	       while (isspace(text[j])) j++;
	       while (text[j]!='\n') j--;
	       for (l=k; l<j; l++) text[l] = '\0';
	    } else
	       for (l=k+3; l<j; l++) text[l] = '\0';
	 }
     }
     for (j=0; j<i; j++) {
         if (text[j]) fputc(text[j], man);
     }
     free(text);
     fflush(man);
     fclose(man);
     chmod(tmpname, 0555);
     if (!strcmp(editor_cmd, "emx"))
        sprintf(cmd, "(emx -edit 0 %s ; rm -f %s ) &", tmpname, tmpname);
     else
        sprintf(cmd, "(%s %s ; rm -f %s ) &", editor_cmd, tmpname, tmpname);
     system(cmd);
}

void show_version(ImageLayout * scene, Window win)
{
char str[512];

     sprintf(str, msg[VERSION_FORMAT],
	          PACKAGE, VERSION, DATEPKG, " ", COPYRIGHT);
     draw_win_string(scene, win, str, BOTTOM);
}
		
void draw_win_cmd(ImageLayout * scene, int level)
{
        int i, j;
	char str[256], name[128], lat[40], lon[40];

        if (!cmdwin_on && cmd_mode>MODE_RUN) {
           XSizeHints xsh;
	   cmdwin_on = 1;
           if (cmdwin_x>-100000) {
              xsh.flags = USPosition | PSize;
              xsh.x = cmdwin_x;
              xsh.y = cmdwin_y;
              xsh.width = cmdwin_width;
              xsh.height = cmdwin_height;
              XSetNormalHints(dpy, cmdwin, &xsh);
           }
	   XMapWindow(dpy, cmdwin);
	   XFlush(dpy);
	   usleep(10000);
	}

	if (cmd_mode>MODE_RUN && level==0) {
	   strcpy(str, labels_generalmenu);
	   draw_win_string(scene, cmdwin, str, TOP);
	   for (i=1;i<END_LABELS_GENERALMENU-BEGIN_LABELS_GENERALMENU;i++) {
	      j = XTextWidth(xfont[0], str, spacing_generalmenu*i-1);
	      draw_separator(scene, j, TOP);
	   }
	   if (cmd_mode==MODE_MENU && cmd_type==M_MENU_START) {
	      XClearArea(dpy, cmdwin, 0, fonth[0]+6, 
                 cmdwin_width, cmdwin_height, False);
	      draw_win_string(scene, cmdwin, msg[BRIEF_MENU_SHORTCUTS], BOTTOM);
	   }
	}

        if (cmd_mode==MODE_CMD) {
	   if (level<=1)
	      draw_tick(scene, MODE_MENU, M_MENU_CMD, TOP);
           for (j=0; j<=1; j++)
              draw_win_string(scene, cmdwin, msg[LIST_OF_MAIN_COMMANDS+j], TOP+j+1);
	}

        if (cmd_mode==MODE_FILE) {
	   if (level<=1)
	      draw_tick(scene, MODE_MENU, M_MENU_FILE, TOP);
	   strcpy(str, labels_filemenu);
	   draw_win_string(scene, cmdwin, str, TOP+1);
	   for (i=1; i<END_LABELS_FILEMENU-BEGIN_LABELS_FILEMENU; i++) {
	      j = XTextWidth(xfont[0], str, spacing_filemenu*i-1);
	      draw_separator(scene, j, TOP+1);
	   }
	   if (level<=1) {
	      draw_tick(scene, MODE_FILE, cmd_type, TOP+1);
	   }
           if (cmd_type==M_FILE_DATA)
              draw_rect_cmd(scene, datafile_descr, NUM_DATAFILE, TOP+1, level);
	   else
           if (cmd_type==M_FILE_EXTERNAL)
              draw_rect_cmd(scene, external_descr, NUM_EXTERNAL, TOP+1, level);
	   else
           if (cmd_type==M_FILE_PRINTCFG)
              draw_rect_cmd(scene, printcfg_descr, NUM_PRINTCFG, TOP+1, level);
	   else
           if (cmd_type==M_FILE_SAVE) {
	      draw_rect_cmd(scene, save_descr, NUM_SAVE, TOP+1, level);
	   }
	   if (cmd_type==M_FILE_SAVE) {  
	      if (overwrite==1) {
   	         sprintf(str, msg[OUTPUT_FILE_ALREADY_EXISTS], 
                              scene->outfile);
	         draw_win_string(scene, cmdwin, str, BOTTOM);  
	      }
	   }
	}

        if (cmd_mode==MODE_MENU) {
	   if (level<=1)
              draw_tick(scene, MODE_MENU, cmd_type, TOP);
           if (cmd_type==M_MENU_SEARCH) {
	      line_clicked = search_by;
              draw_win_string(scene, cmdwin, msg[SPECIFY_STRING_TO_SEARCH], TOP+1);
              draw_rect_cmd(scene, searchby_descr, 
                          END_SEARCHBY_DESCRIPTION-BEGIN_SEARCHBY_DESCRIPTION,
                          TOP+1, level);
	   } else
           if (cmd_type==M_MENU_LIST) {
	      char ** cityname_descr;
	      if (search_by<=5) {
                 strcpy(str, msg[LIST_OF_MATCHING_LOCATIONS]);
                 line_clicked = -1;
	      } else {
                 strcpy(str, msg[LIST_OF_PREVIOUS_POSITIONS]);
                 num_found = scene->num_positions;
	         loc_pointer = (int *)realloc(loc_pointer, 
                     num_found*sizeof(int));
	         for (i=0; i<num_found; i++)
	             loc_pointer[i] = scene->position[i].loc;
	      }
              draw_win_string(scene, cmdwin, str, TOP+1);
	      num_listed = cmdwin_height/(fonth[0]+10)-4;
	      if (num_listed>num_found) num_listed = num_found;
	      cityname_descr = (char **)malloc((num_listed+1)*sizeof(char *));
	      for (i=0; i<num_listed; i++) {
		  j = loc_pointer[i+start_list];
		  if (i==0 && start_list>0)
		     strcpy(str, GO_UP);
		  else
		  if (i==num_listed-1 && start_list+num_listed<num_found)
		     strcpy(str, GO_DOWN);
		  else {
       		     if (j==search_index) line_clicked = i+1;
                     if (search_by==6) {
		        if (j>=0)
			   sprintf(name, "   %s", locations[j]->name);
			else
			   *name = '\0';
			j = i+start_list;
			if (j==search_index) line_clicked = i+1;
			decim2dms(scene->position[j].xrot, lat);
			decim2dms(scene->position[j].yrot, lon);
		        sprintf(str, "lat = %s,  lon = %s,  zoom = %.3f%s",
                           lat, lon, scene->position[j].zoom, name);
		     } else
		     if (locations[j]->obj=='c') {
			decim2dms(locations[j]->lat, lat);
			decim2dms(locations[j]->lon, lon);
		        sprintf(str, "%s, %s, %s  (lat = %s  lon = %s)",
                           locations[j]->name, 
                         countries[timezones[locations[j]->tz]->country]->name,
                           locations[j]->region,
                           lat, lon);
		     } else 
		     if (locations[j]->obj=='a' ||
                         locations[j]->obj=='b' ||
                         locations[j]->obj=='p') {
			decim2dms(locations[j]->lat, lat);
			decim2dms(locations[j]->lon, lon);
		        sprintf(str, "%s, %s (lat = %s  lon = %s)", 
                           locations[j]->name, 
                      countries[timezones[locations[j]->tz]->country]->name,
                           lat, lon);
		     } else 
		     if (locations[j]->obj=='l') {
                        strcpy(name, locations[j]->name);
			simplify_string(name);
			decim2dms(locations[j]->lat, lat);
			decim2dms(locations[j]->lon, lon);
		        sprintf(str, "%s, %s (lat = %s  lon = %s)", name, 
                           msg[BEGIN_CONTINENT_DESCRIPTION+locations[j]->tz],
                           lat, lon);
		     }
		  }
		  cityname_descr[i] = strdup(str);
	      }
              draw_rect_cmd(scene, cityname_descr, num_listed, 
                            TOP+1, level);
	      j = box_y+box_spacing/2-1+(num_listed+1)*box_spacing;
              XClearArea(dpy, cmdwin, 0, j, 
                         cmdwin_width, cmdwin_height-j, False);

	      for (i=0; i<num_listed; i++) free(cityname_descr[i]);
	      free(cityname_descr);
	   }
	}

        if (cmd_mode==MODE_OPTION) {
	   if (level<=1)
	      draw_tick(scene, MODE_MENU, M_MENU_OPTION, TOP);
	   strcpy(str, labels_optionmenu);
	   draw_win_string(scene, cmdwin, str, TOP+1);
	   for (i=1;i<END_LABELS_OPTIONMENU-BEGIN_LABELS_OPTIONMENU;i++) {
	       j = XTextWidth(xfont[0], str, spacing_optionmenu*i-1);
	       draw_separator(scene, j, TOP+1);
	   }
	   if (level<=1)
	      draw_tick(scene, cmd_mode, cmd_type, TOP+1);
	   if (cmd_type==M_OPTION_PARAM)
              draw_rect_cmd(scene, parameter_descr, NUM_PARAM, TOP+1, level);
	   if (cmd_type==M_OPTION_HIERARCHY)
              draw_rect_cmd(scene, display_descr, NUM_HIERARCHY, TOP+1, level);
	   if (cmd_type==M_OPTION_FONT)
              draw_rect_cmd(scene, font_descr, NUM_FONTS, TOP+1, level);
	   if (cmd_type==M_OPTION_MARKS)
              draw_rect_cmd(scene, marks_descr, NUM_MARKS, TOP+1, level);
           if (cmd_type==M_OPTION_CONTIN)
              draw_rect_cmd(scene, continent_descr, NUM_CONTIN, TOP+1, level);
           if (cmd_type==M_OPTION_CAT)
              draw_rect_cmd(scene, category_descr, NUM_CAT, TOP+1, level);
	}

        if (cmd_mode==MODE_COLOR) {
	   if (level<=1)
	      draw_tick(scene, MODE_MENU, M_MENU_COLOR, TOP);
	   strcpy(str, labels_colormenu);             
	   draw_win_string(scene, cmdwin, str, TOP+1);
	   for (i=1; i<END_LABELS_COLORMENU-BEGIN_LABELS_COLORMENU; i++) {
	      j = XTextWidth(xfont[0], str, spacing_colormenu*i-1);
	      draw_separator(scene, j, TOP+1);
	   }
	   if (level<=1)
	      draw_tick(scene, cmd_mode, cmd_type, TOP+1);
	   if (cmd_type>M_COLOR_START)
	      draw_rect_cmd(scene, feature_descr[cmd_type-1], 
                       feature_length[cmd_type-1], TOP+1, level);
	}

        if (cmd_mode==MODE_HELP) {
	   if (level<=1)
	      draw_tick(scene, MODE_MENU, M_MENU_HELP, TOP);
	   strcpy(str, labels_helpmenu);             
	   draw_win_string(scene, cmdwin, str, TOP+1);
	   for (i=1; i<END_LABELS_HELPMENU-BEGIN_LABELS_HELPMENU; i++) {
	      j = XTextWidth(xfont[0], str, spacing_helpmenu*i-1);
	      draw_separator(scene, j, TOP+1);
	   }
	   if (level<=1)
	      draw_tick(scene, cmd_mode, cmd_type, TOP+1);

	   if (cmd_type==M_HELP_SHORTCUTS) {
	      char *ptr1, *ptr2, n;
	      n = (cmdwin_height-2*(fonth[0]+16)-13)/(fonth[0]+5);
	      if (n>END_LIST_SHORTCUTS-BEGIN_LIST_SHORTCUTS)
		 n = END_LIST_SHORTCUTS-BEGIN_LIST_SHORTCUTS;
              if (BEGIN_LIST_SHORTCUTS+start_shortcut+n>=END_LIST_SHORTCUTS)
		 start_shortcut = END_LIST_SHORTCUTS-BEGIN_LIST_SHORTCUTS-n;
              ptr1 = msg[BEGIN_LIST_SHORTCUTS+start_shortcut];
	      ptr2 = msg[BEGIN_LIST_SHORTCUTS+start_shortcut+n-1];
	      if (start_shortcut)
                 msg[BEGIN_LIST_SHORTCUTS+start_shortcut] = GO_UP;
              if (BEGIN_LIST_SHORTCUTS+start_shortcut+n<
		  END_LIST_SHORTCUTS)
                 msg[BEGIN_LIST_SHORTCUTS+start_shortcut+n-1] = GO_DOWN;
	      draw_rect_cmd(scene, 
                 msg+BEGIN_LIST_SHORTCUTS+start_shortcut, n, TOP+1, -1);
              msg[BEGIN_LIST_SHORTCUTS+start_shortcut] = ptr1;
              msg[BEGIN_LIST_SHORTCUTS+start_shortcut+n-1] = ptr2;
	   }

	   if (cmd_type==M_HELP_ABOUT) 
              show_version(scene, cmdwin);

	   if (cmd_type==M_HELP_DOC || cmd_type==M_HELP_EXTRA) {
	      DIR *dir = NULL;
	      struct dirent *dirent = NULL;
	      num_doc = 0;
	      if (cmd_type==M_HELP_DOC)
		 dir = opendir(DOCPATH);
	      else
	      if (cmd_type==M_HELP_EXTRA)
		 dir = opendir(CIAEXTRAPATH);
              if (dir) {
	         if (doc_descr) {
                    for (i=0; i<num_doc; i++) 
                       if (doc_descr[i]) free(doc_descr[i]);
		    free(doc_descr);
		    doc_descr = NULL;
	         }
                 for (dirent = readdir(dir); dirent != NULL; 
                     dirent = readdir(dir)) 
		 if (strcmp(dirent->d_name, ".") &&
		     strcmp(dirent->d_name, "..")) {  
		    doc_descr = (char **)realloc(doc_descr, 
                                   (num_doc+2)*sizeof(char *));
                    doc_descr[num_doc] = strdup(dirent->d_name);
                    ++num_doc;
	         }
                 closedir(dir);
                 if (cmd_type==M_HELP_DOC) {
                    doc_descr[num_doc] = strdup(msg[MANUAL_PAGE]);
	            ++num_doc;
		 }
	      }
              num_listed = cmdwin_height/(fonth[0]+10)-4;
              if (num_listed>num_doc) {
		 num_listed = num_doc;
		 start_list = 0;
	      }
	      if (start_list + num_listed < num_doc)
		 doc_descr[start_list+num_listed-1] = strdup(GO_DOWN);
	      else
		 start_list = num_doc - num_listed;
              if (start_list)
		 doc_descr[start_list] = strdup(GO_UP);		 
	      if (doc_descr)
                 draw_rect_cmd(scene, 
                     doc_descr + start_list, num_listed, TOP+1,level);
	   }

	   if (cmd_type==M_HELP_EDIT) {
	      char **data_descr = NULL;
	      num_listed = cmdwin_height/(fonth[0]+10)-4;
              if (num_listed>scene->numpoint) num_listed = scene->numpoint;
              data_descr = (char**) malloc((num_listed+1)*sizeof(char*));
	      for (i=0; i<num_listed; i++) {
		  if (i==0 && start_list>0)
		     strcpy(str, GO_UP);
		  else
		  if (i==num_listed-1 && start_list+num_listed<scene->numpoint)
		     strcpy(str, GO_DOWN);
		  else {
		     sprintf(str, "%s = %.6f  %s = %.6f",
		        msg[LATITUDE_ABBREVIATED],
			scene->mempoint[2*(i+start_list)],
		        msg[LONGITUDE_ABBREVIATED],
                        scene->mempoint[2*(i+start_list)+1]);
		  }
		  data_descr[i] = strdup(str);
	      }
              draw_rect_cmd(scene, data_descr, 
                            num_listed, TOP+1,level);
	      for (i=0; i<num_listed; i++) 
		 if (data_descr[i]) free(data_descr[i]);
	      if (data_descr) free(data_descr);
	   }
	}

	/* Draw bottom text bar only when needed, i.e. when
	   user has to enter text input */
        if (text_input_mode())
           draw_win_string(scene, cmdwin, cmd_string, BOTTOM);
	XFlush(dpy);
}

void fix_features_description(ImageLayout * scene)
{
int i, j, n;

   for (i=0; i<6; i++) {
      if (feature_descr[i]) free(feature_descr[i]);
      feature_descr[i] = (char **) 
         malloc(feature_length[i]*sizeof(char **));
      for (n=0; n<feature_length[i]; n++) {
	 j = feature_index[i]+n;
         if (scene->color[j].bool != INACTIVE) {
            feature_descr[i][n] = scene->color[j].comment;
	 }
      }
   }
   show_title(scene, mainwin);
   show_title(scene, datawin);
   show_title(scene, cmdwin);
   if (cmdwin_on) draw_win_cmd(scene, 0);
}

void explain_tz(char *out, char *data)
{
   char *ptr, *ptrp;
   char explan[256], compl[80];
   int month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
   int i, j, k, l;

   ptr = data;
   while (*ptr>='A' && *ptr<='Z') ++ptr;
   strncpy(explan, data, ptr-data);
   explan[ptr-data] = '\0';
   strcat(out, explan);

   ptrp = ptr;
   while (*ptrp && *ptrp<'A') ++ptrp;
      if (*ptr=='-') {
      strncpy(explan, ptr, ptrp-ptr);
      explan[0] = '+';
      explan[ptrp-ptr] = '\0';
   } else
   if (*ptr=='+') {
      strncpy(explan, ptr, ptrp-ptr);
      explan[0] = '-';
      explan[ptrp-ptr] = '\0';
   } else {
      if (atoi(ptr)) {
         strncpy(explan+1, ptr, ptrp-ptr);
         explan[0] = '-';
         explan[ptrp-ptr+1] = '\0';
      } else {
	 strcpy(explan, "0");
      }
   }
   i = atoi(explan);
   j = -1;
   if ((ptrp=index(explan, ':'))) j = atoi(ptrp+1);
   strcat(out, explan);

   if (!index(ptr,',')) return;
   strcat(out, "/");

   while (*ptr && *ptr<'A') ++ptr;
   ptrp = ptr;
   while (*ptrp && *ptrp!=',') ++ptrp;
   strncpy(explan, ptr, ptrp-ptr);
   explan[ptrp-ptr] = '\0';
   strcat(out, explan);
   if (j==-1) {
      if (i+1>0)
         sprintf(explan, "+%d", i+1);
      else
         sprintf(explan, "%d", i+1);
   }
   else {
      if (i+1>=0)
         sprintf(explan, "+%d:%d ", i+1, j);
      else
      if (i+1<0)
         sprintf(explan, "%d:%d", i+1, j);
   }
   strcat(out, explan);
   if (!*ptrp) return;
   strcat(out, ", ");

   if (*ptrp==',') ++ptrp;
 repscan:
   if (*ptrp=='M') {
      sscanf(ptrp+1, "%d.%d.%d/%s", &i, &j, &k, compl);
      if (j<=0 || j>5) j=1;
      strcpy(explan, msg[ORDINALS+j-1]);
      strcat(explan, " ");
      if (k<0 || k>=7) k=0;
      l = msg[LENGTH_DAY_ABBREVIATION][k]-'0';
      strncat(explan, msg[NAME_OF_DAYS+k], l);
      strcat(explan, " ");
      if (i<0 || i>11) i=0;
      l = msg[LENGTH_MONTH_ABBREVIATION][i]-'0';
      strncat(explan, msg[NAME_OF_MONTHS+i], l);
      strcat(out, explan);
      if (!*compl) return;
      if ((ptrp=index(compl,','))) *ptrp = '\0';
      strcat(out, " @");
      strcat(out, compl);
      if (!ptrp) return;
      ++ptrp;
   } else
   if (*ptrp=='J') {
      sscanf(ptrp+1, "%d/%s", &j, compl);
      if (j>365) j=365;
      i = 0;
      while (j>month[i]) {
	 j -= month[i];
	 ++i;
      }
      sprintf(explan, "%d", j);
      strcat(explan, " ");
      l =  msg[LENGTH_MONTH_ABBREVIATION][i]-'0';
      strncat(explan, msg[NAME_OF_MONTHS+i], l);
      strcat(out, explan);
      if (!*compl) return;
      if ((ptrp=index(compl,','))) *ptrp = '\0';
      strcat(out, " @");
      strcat(out, compl);
      if (!ptrp) return;
      ++ptrp;     
   } else
      return;
   if (*ptrp) {
         strcat(out, "/");
         goto repscan;
   }
}

void show_coord(ImageLayout * scene, double x, double y)
{
char str[256], compl1[40], compl2[40], lat[40], lon[40];

   if (but_main_pressed == 3) {
      strcpy(compl1, msg[RECENTER_MAP]);
      strcpy(compl2, msg[CANCEL_MOVE]);
   } else
      *compl1 = *compl2 = '\0';
   decim2dms(x, lat);
   decim2dms(y, lon);
   sprintf(str, "%slat = %s  lon = %s%s", compl1, lat, lon, compl2);
   draw_win_string(scene, mainwin, str, line_pos);
   point_shown = 1;
#ifdef SEG_SELECT
   if (seg_mode>=1 && but_main_pressed == 1) {
      arc_x = y; arc_y = x;
      if (scene->prepixmap) {
	 XFreePixmap(dpy, scene->prepixmap);
	 scene->prepixmap = None;
      }
      generate(scene);
      return;
   }
#endif
#ifdef ARCINFO
   if (arc_search && but_main_pressed == 1) {
      arc_start = 1;
      arc_x = y; arc_y = x;
      if (scene->prepixmap) {
	 XFreePixmap(dpy, scene->prepixmap);
	 scene->prepixmap = None;
      }
      generate(scene);
      return;
   }
#endif
}

void set_time(int num, char *str)
{
   struct tm ltp;
   time_t gtime;

#ifdef __linux__
   time(&gtime);
   setenv("TZ", timezones[num]->posix, 1);
#else
   char buf[256];
   time(&gtime);
   sprintf(buf, "TZ=%s", timezones[num]->posix);   
#ifdef __solaris__
   putenv(buf);
#endif
#ifdef __hpux__
   putenv(stdup(buf));
#endif
#endif 
   ltp = *localtime(&gtime);
   sprintf(str, "%s %02d:%02d:%02d %s, %s %d %s %d", 
                   msg[DATE_TIME],
                   ltp.tm_hour, ltp.tm_min, ltp.tm_sec, 
#ifdef NEW_CTIME
                   ltp.tm_zone,
#else
                   tzname[ltp.tm_isdst],
#endif
	           msg[NAME_OF_DAYS+ltp.tm_wday], ltp.tm_mday,
                   msg[NAME_OF_MONTHS+ltp.tm_mon], ltp.tm_year+1900);
}

void update_time(ImageLayout * scene, char *str)
{
   int j, y, l1, l2, x1, x2, w1, w2;

   x1 = 4;
   x2 = 4;
   y = h_button+pixmap_height_max+11*(fonth[0]+4)+28;
   l1 = strlen(str);
   l2 = strlen(time_string);

   j = 0;

   XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix);
   while(j<l1 || j<l2) {
      if (j<l1)
         w1 = XTextWidth(xfont[0], &str[j], 1);
      else
	 w1 = 0;
      if (j<l2)
         w2 = XTextWidth(xfont[0], &time_string[j], 1);
      else
	 w2 = 0;
      if (x1!=x2) {
	 w2 = XTextWidth(xfont[0], time_string, l2);
         XClearArea(dpy, datawin, x1, y-fontasc[0], w2, fonth[0], False);
         XDrawString(dpy, datawin, gc, x1, y, &str[j], l1-j);
	 break;
      }
      if (j<l2 || (j<l1 && str[j]!=time_string[j]))
         XClearArea(dpy, datawin, x1, y-fontasc[0], w1, fonth[0], False);
      if (j<l1)
         XDrawString(dpy, datawin, gc, x1, y, &str[j], 1);
      x1 += w1;
      x2 += w2;
      ++j;
   }
   strcpy(time_string, str);
}

void write_point_primary(ImageLayout * scene, int i)
{
    char str[256];
    sprintf(str, "|%.6f,%.6f", scene->mempoint[2*i], scene->mempoint[2*i+1]);
    write_primary(str);
}

void show_mark(ImageLayout * scene)
{
   ScreenPt pt;
   SpherePt spt;
   int u, v, du = 0, dv = 0, l;
   char name[256];

   if (brief_menu) return;

   if (cmd_mode==MODE_HELP && cmd_type==M_HELP_EDIT && scene->numpoint>0) {
      for (l=0; l<scene->numpoint; l++) {
         spt.sph[LATITUDE] = scene->mempoint[2*l];
         spt.sph[LONGITUDE] = scene->mempoint[2*l+1];
         pt = project(scene, spher2cart(scene, spt));
         if (!visible) continue;
         u = pt.coord[X];
         v = pt.coord[Y];
	 if (l==line_clicked+start_list-1)
            XSetForeground(dpy, gc, scene->color[C_FG_SELPOINT].pix);
         else
            XSetForeground(dpy, gc, scene->color[C_FG_SELRECT].pix);
         XDrawLine(dpy, mainwin, gc, u-6, v, u+6, v);
         XDrawLine(dpy, mainwin, gc, u, v-6, u, v+6);
      }
   }

   if (city_found<0) return;
   clear_city_shown();

   city_shown = 1;
   exposed |= DONE_MARK;

   spt.sph[LONGITUDE] = locations[city_found]->lon;
   spt.sph[LATITUDE] = locations[city_found]->lat;
   pt = project(scene, spher2cart(scene, spt));
   if (!visible) return;
   u = pt.coord[X];
   v = pt.coord[Y];

   XSetForeground(dpy, gc, scene->color[C_FG_MARKED].pix);
   XSetFont(dpy, gc, xfont[1]->fid);
   reformat_string(name, locations[city_found]->name, 0);
   simplify_string(name);

   l = strlen(name);
   if (locations[city_found]->obj!='l') {
      XDrawLine(dpy, mainwin, gc, u-6, v, u+6, v);
      XDrawLine(dpy, mainwin, gc, u, v-6, u, v+6);
      du = -4-XTextWidth(xfont[1], locations[city_found]->name, l);
      dv = -3;
   }
   if (locations[city_found]->draw & TEXT_DRAWN) {
      city_already_shown = 1;
      l = scene->ropt.smartlabels;
      city_shown_box_w = 0;
      scene->ropt.smartlabels = 0;
      draw_location(scene, locations[city_found]);
      scene->ropt.smartlabels = l;
      city_already_shown = 0;
      if (city_shown_box_x > u - 7) {
	  city_shown_box_w = city_shown_box_w + (city_shown_box_x - u + 7);
	  city_shown_box_x = u - 7;
      }
      if (city_shown_box_y > v - 7) {
	  city_shown_box_h = city_shown_box_h + (city_shown_box_y - v + 7);
	  city_shown_box_y = v - 7;
      }
      if (city_shown_box_y + city_shown_box_h < v + 7)
	  city_shown_box_h = v + 7 - city_shown_box_y;
      return;
   }

   city_shown_box_w = 13-du;
   city_shown_box_h = fonth[1]+13;

   if (u>scene->width/2) {
      city_shown_box_x = u+du-2;
   } else {
      city_shown_box_x = u-6;
      du = 6;
   }
   city_shown_box_y = v-6-fontasc[1];
   XDrawString(dpy, mainwin, gc, u+du,v+dv, name, l);
}

void free_flag_data()
{
   int i;
   if (flag_dir) {
      for (i=0; i<num_flag_dirs; i++) {
         free(flag_dir[i]);
         free(flag_type[i]);
      }
      free(flag_dir);
      free(flag_type);
      free(flag_ordering);
   }  
}

int set_flag_dirs()
{
   int i, j, n, error;
   char *ptr, *ptrp;
   char dirname[256];
   struct stat buf;

   free_flag_data();

   num_flag_dirs = 0;
   flag_dir = NULL;
   flag_type = NULL;
   flag_ordering = NULL;
   error = 0;

   ptr = flag_descr;
   while (ptr) {
      ptrp = index(ptr, ':');
      if (!ptrp) {
 	 flag_ordering = strdup(ptr);
         break;
      }
      *ptrp = '\0';
      n = num_flag_dirs;
      ++num_flag_dirs;
      flag_dir = (char **) realloc(flag_dir, num_flag_dirs*sizeof(char*));
      flag_type = (char **) realloc(flag_type, num_flag_dirs*sizeof(char*));
      flag_dir[n] = strdup(ptr);
      buf.st_mode = 0;
      sprintf(dirname, "%s/%s", FLAGPATH, flag_dir[n]);
      stat(dirname, &buf);
      if (!S_ISDIR(buf.st_mode)) error = 1;
      *ptrp = ':';
      ptr = ptrp+1;
      ptrp = index(ptr, '|');
      if (ptrp) *ptrp = '\0';
      flag_type[n] = strdup(ptr);
      for (i=0; i<strlen(ptr); i++) 
	 flag_type[n][i] = tolower(flag_type[n][i]);
      j = 1;
      for (i=0; i<num_flag_types; i++) {
	 if (!strcmp(flag_type[n], flag_formats[i])) {
            j = 0;
            break;
	 }
      }
      error |= j;
      if (ptrp) *ptrp = '|'; else break;
      ptr = ptrp+1;
      if (!*ptr) break;
   }
   if (error || !flag_ordering) return 1;
   if (strlen(flag_ordering)<2*num_flag_dirs+1) return 1;
   if (flag_ordering[num_flag_dirs] != ',') return 1;
   for (i=0; i<2*num_flag_dirs+1; i++) if (i!=num_flag_dirs) {
      j = flag_ordering[i] - '1';
      if (j>9)
	 j = flag_ordering[i] - 'a' + 9;
      if (j<0 || j>=num_flag_dirs) return 1;
   }
   return 0;
}

void list_flag_dirs()
{
   char dirname[256], name[80], ftype[80];
   struct dirent *dirent;
   DIR *dir;
   char *ptr;
   int i, j, k, n;
   int *weight, *order;

   sprintf(dirname, "%s/flags", SHAREDIR);
   dir = opendir(dirname);
   if (dir == NULL) return;
     
   flag_descr = NULL;
   flag_dir = NULL;
   num_flag_types = sizeof(flag_formats)/sizeof(char *);

   n = 1;
   for (dirent = readdir(dir); dirent != NULL; dirent = readdir(dir)) {
      ptr = dirent->d_name;
      if (!strcmp(ptr, ".") || !strcmp(ptr, "..")) continue;
      ++num_flag_dirs;
      strncpy(name, ptr, 78); name[78] = '\0';
      strcpy(ftype, name);
      ptr = index(ftype, '_');
      if (ptr) *ptr = '\0';
      j = -1;
      for (i=0; i<num_flag_types; i++) {
	if (!strcasecmp(ftype, flag_formats[i])) { j = i; break; }
      }
      if (j == -1) continue;
      for (i=0; i<strlen(ftype); i++) ftype[i] = toupper(ftype[i]); 
      n += strlen(name) + strlen(ftype) + 2;
      i = (flag_descr == NULL);
      flag_descr = (char*) realloc(flag_descr, n);
      if (i) flag_descr[0] = '\0'; else strcat(flag_descr, "|");
      strcat(flag_descr, name);
      strcat(flag_descr, ":");
      strcat(flag_descr, ftype);
   }

   closedir(dir);
   set_flag_dirs();
   weight = (int *)malloc(num_flag_dirs*sizeof(int));
   order = (int *)malloc(num_flag_dirs*sizeof(int));

   k = 2*num_flag_dirs+2;
   n += k;
   flag_descr = (char*) realloc(flag_descr, n);
   flag_ordering = malloc(k);
   flag_ordering[num_flag_dirs] = ',';
   flag_ordering[k-1] = '\0';

   for (k=0; k<=1; k++) {

      for (i=0; i<num_flag_dirs; i++)
         weight[i] = order[i] = 0;

      for (i=0; i<num_flag_dirs; i++) {
         for (j=0; j<num_flag_types; j++) {
             if (!strcmp(flag_type[i], flag_formats[(k)?flag_rev[j]:j])) 
                weight[i] = j;
         }
         ptr = index(flag_dir[i], '_');
         if (ptr && atoi(ptr+1)>=200) weight[i] += 1000;
      }

      if (k==0) {
         for (i=0; i<num_flag_dirs; i++) 
         for (j=0; j<num_flag_dirs; j++)
            if (j!=i && weight[j]>=weight[i]) ++order[j];
      }
      if (k==1) {
         for (i=0; i<num_flag_dirs; i++) 
         for (j=0; j<num_flag_dirs; j++)
            if (j!=i && weight[j]<=weight[i]) ++order[j];
      }

      for (i=0; i<num_flag_dirs; i++) weight[order[i]] = i+1;

      for (i=0; i<num_flag_dirs; i++) {
	 ptr = &flag_ordering[i+k*(num_flag_dirs+1)];
         if (weight[i]<10)
            *ptr = '0'+weight[i];
         else
            *ptr = 'a'+weight[i]-10;
      }
   }

   free(weight);
   free(order);

   strcat(flag_descr, "|");
   strcat(flag_descr, flag_ordering); 
   /* DEBUG...  
   printf("%s\n", flag_descr);
   for (i=0; i<num_flag_dirs; i++)
      printf("%s %s\n", flag_dir[i], flag_type[i]);
   */
}

void show_datawin(ImageLayout * scene, int raise)
{
   static char *flag[2] = { NULL, NULL};
   static char *prev_flag[2] = { NULL, NULL};
   struct stat buf;
   int i, j=0, k, lstep, lmax, line_y, erase_text = 0, show_flags;
   int x, y, w, h;
   char str[11][256],
	path[256], name[256], country[256], lat[40], lon[40],
        alt[20], pop[20], rank1[20], rank2[20], rank3[20], adm_status[40];
   char *ptr;

   if (city_found<0) return;
   if (city_found != old_city_shown) erase_text = 1;
   old_city_shown = city_found;

   buf.st_mode = 0;
   if (stat(FLAGPATH, &buf) || !S_ISDIR(buf.st_mode))
      show_flags = 0;
   else
      show_flags = 1;

   exposed &= ~DATA_WINDOW;
   data_text = realloc(data_text, 4*sizeof(char));
   *data_text = '\0';

   if (locations[city_found]->obj == 'l') {
      strcpy(name, locations[city_found]->name);
      simplify_string(name);
      decim2dms(locations[city_found]->lat, lat);
      decim2dms(locations[city_found]->lon, lon);
      sprintf(str[0], "%s, %s  (%c, %d)",
    	 name, msg[BEGIN_CONTINENT_DESCRIPTION+locations[city_found]->tz],
         locations[city_found]->status, locations[city_found]->population);
      sprintf(str[1], "%s = %s  %s = %s",
           msg[LATITUDE_ABBREVIATED], lat, 
           msg[LONGITUDE_ABBREVIATED], lon);
      if (locations[city_found]->rank==-1) {
         datawin_height = h_button+2*(fonth[0]+4)+12;
         if (raise)
            XMapRaised(dpy, datawin);
         else
            XMapWindow(dpy, datawin);
         (void) get_window_placement(datawin, &x, &y, &w, &h);
         if (w!=datawin_width || h!=datawin_height)
            XResizeWindow(dpy, datawin, datawin_width, datawin_height);
         XFlush(dpy);
	 if (!datawin_on) usleep(80000);
	 usleep(20000);
         datawin_on = 1;
	 XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix);
         for (i=0; i<=1; i++) {
	    j = strlen(str[i]);
            XDrawString(dpy, datawin, gc, 4, 
            h_button+(fonth[0]+4)*(i+1)+2, str[i], j);
         }
         XDrawLine(dpy, datawin, gc, 0, h_button, datawin_width, h_button);
         if (butpix[0]!=None) {
            XCopyArea(dpy, butpix[0], datawin, gc, 0,0, 
		w_buttons-1, h_button-1, 0, 0);
	 }
	 return;
      }

      j = locations[city_found]->rank;
      sprintf(str[2], "%s", countries[j]->name);
      sprintf(str[3], msg[DATA_CURRENCY],
            countries[j]->currency, countries[j]->curr_code);
      sprintf(str[4], msg[DATA_TELEPHONE], countries[j]->telephone);
      sprintf(str[5], msg[DATA_AREA], countries[j]->area);
      sprintf(str[6], msg[DATA_POPULATION],
	    countries[j]->capital, 
            countries[j]->population);
      lstep = 2;
      lmax = 6;
      if (show_flags) {
	 ptr = countries[j]->flags;
	 goto doflags;
      } else goto skipflags;
   }

   if (locations[city_found]->obj != 'c' && 
       locations[city_found]->obj != 'a' && 
       locations[city_found]->obj != 'b' &&
       locations[city_found]->obj != 'p') return;

   if (locations[city_found]->status=='C') 
      sprintf(adm_status, "   (%s)", msg[CAPITAL_OF_STATE]);
   else
   if (locations[city_found]->status=='R') 
      sprintf(adm_status, "   (%s)", msg[CAPITAL_OF_REGION]);
   else
      *adm_status = '\0';
   reformat_string(name, locations[city_found]->name, 0);

   if (locations[city_found]->alt==-30000) 
      strcpy(alt, "?");
   else
      sprintf(alt, "%dm", locations[city_found]->alt);
   decim2dms(locations[city_found]->lat, lat);
   decim2dms(locations[city_found]->lon, lon);
   sprintf(str[1], "%s = %s  %s = %s   %s = %s",
           msg[LATITUDE_ABBREVIATED], lat,
           msg[LONGITUDE_ABBREVIATED], lon, 
           msg[ALTITUDE_ABBREVIATED], alt);

   if (locations[city_found]->obj == 'b') {
      sprintf(str[0], name);
      sprintf(str[2], msg[ADMINISTRATIVE_REGION],
                 (locations[city_found]->region[0])?
                  locations[city_found]->region : "-");
      str[3][0] = '\0';
      goto fix_tz;
   }

   if (locations[city_found]->obj == 'a') {
      sprintf(str[0], name);
      sprintf(str[2], msg[AIRPORT_CODE_COUNTRY],
         locations[city_found]->region, locations[city_found]->rank);
      sprintf(str[3], msg[AIRPORT_RUNWAY_LENGTH], 
         locations[city_found]->population);
   }

   if (locations[city_found]->rank) 
      sprintf(rank1, "%d", locations[city_found]->rank);
   else
      strcpy(rank1, "-");
   if (locations[city_found]->contrank) 
      sprintf(rank2, "%d", locations[city_found]->contrank);
   else
      strcpy(rank2, "-");
   if (locations[city_found]->worldrank) 
      sprintf(rank3, "%d", locations[city_found]->worldrank);
   else
      strcpy(rank3, "-");

   if (locations[city_found]->obj=='c') {
      sprintf(country, 
         countries[timezones[locations[city_found]->tz]->country]->name);
      if ((ptr=index(country,','))) *ptr='\0';
      sprintf(str[0], "%s, %s%s", name, country, adm_status);
      sprintf(str[2], msg[ADMINISTRATIVE_REGION],
                 (locations[city_found]->region[0])?
                  locations[city_found]->region : "-");
      if (locations[city_found]->population) {
         sprintf(pop, "%d", locations[city_found]->population);
         sprintf(str[4], msg[POPULATION_NUMBER], pop);
         sprintf(str[5], msg[CONTINENT_AND_WORLD_RANKS], rank1, rank2, rank3);
         sprintf(str[3], "%s    %s", str[4], str[5]);
      }
      else
         sprintf(str[3], msg[POPULATION_NUMBER], "?");
   } else
   if (locations[city_found]->obj=='p') {
      sprintf(str[0], name);
      sprintf(str[2], locations[city_found]->region);
      sprintf(str[3], msg[CONTINENT_AND_WORLD_RANKS], rank1, rank2, rank3);
   }

 fix_tz:
   j = locations[city_found]->tz;
   k = timezones[j]->country;
   sprintf(str[4], "%s", countries[k]->name);
   sprintf(str[5], msg[DATA_CURRENCY],
            countries[k]->currency, countries[k]->curr_code);
   sprintf(str[6], msg[DATA_TELEPHONE], countries[k]->telephone);
   if (countries[k]->capital[0]=='@') {
      k = (countries[k]->capital[1]-'A')*26+(countries[k]->capital[2]-'A');
      k = country_table[k];
      sprintf(str[7], msg[DATA_TERRITORY], countries[k]->name);
   } else
      sprintf(str[7], msg[DATA_AREA], countries[k]->area);
   sprintf(str[8], msg[DATA_POPULATION],
	    countries[k]->capital, 
            countries[k]->population);
   sprintf(str[9], "%s %s; ", msg[AREA_AND_TIMEZONE], timezones[j]->name);
   explain_tz(str[9], timezones[j]->posix);
   set_time(j, str[10]);
   strcpy(time_string, str[10]);
   lstep = 4;
   lmax = 10;
   time_count = 1;
   if (!show_flags) goto skipflags;
   ptr = timezones[j]->flags;
   
 doflags:
   for (i=0; i<=1; i++) {
      if (prev_flag[i]) free(prev_flag[i]);
      prev_flag[i] = flag[i];
      flag[i] = NULL;
      pixmap_width[i] = pixmap_height[i] = 0;
   }
   pixmap_height_max = 0;
   
   flag[0] = strdup(ptr);
   if ((ptr = index(flag[0], ','))) {
      *ptr = '\0';
      flag[1] = strdup(ptr+1);
   }
   
   for (i=0; i<=1; i++) {
      if (!flag[i] || (prev_flag[i] && strcmp(flag[i], prev_flag[i]))) {
         if (flag_image[i]) XDestroyImage(flag_image[i]);
         flag_image[i] = NULL;
      }
      if (flag[i] && !flag_image[i])
         flag_image[i] = readIMG(scene, FLAGPATH, flag[i], 150,
                                 &scene->color[C_BG_TEXT]);
      if (!flag_image[i]) {
         if (flag[i]) {
            pixmap_width[i] = 270;
            pixmap_height[i] = 150;
         }
      } else {
         pixmap_width[i] = flag_image[i]->width;
         pixmap_height[i] = flag_image[i]->height;
      }
      if (pixmap_height[i] > pixmap_height_max) 
	 pixmap_height_max = pixmap_height[i];
   }

 skipflags:
   if (pixmap_height_max>0)
      datawin_height = h_button + pixmap_height_max + 26;
   else {
      pixmap_height_max = -8;
      datawin_height = h_button + 20;
   }
   datawin_height += (lmax+1)*(fonth[0]+4)+10*(lmax==10); 
   if (datawin_x>-100000) {
      XSizeHints xsh;
      xsh.flags = USPosition | PSize;
      xsh.x = datawin_x;
      xsh.y = datawin_y;
      xsh.width = datawin_width;
      xsh.height = datawin_height;
      XSetNormalHints(dpy, datawin, &xsh);
   }

   if (raise)
      XMapRaised(dpy, datawin);
   else
      XMapWindow(dpy, datawin);
   (void) get_window_placement(datawin, &x, &y, &w, &h);
   if (w!=datawin_width || h!=datawin_height)
      XResizeWindow(dpy, datawin, datawin_width, datawin_height);
   if (datawin_x>-100000) {
      XMoveWindow(dpy, datawin, datawin_x, datawin_y);
      datawin_x = -1000000;
   }
   XFlush(dpy);
   if (!datawin_on) usleep(80000);
   usleep(20000);
   datawin_on = 1;
   
   show_mark(scene);
   XClearArea(dpy, datawin, 0, h_button + 1, datawin_width, 4, False);
   XClearArea(dpy, datawin, 0, h_button+5, 4, pixmap_height_max, False);

   for (i=0; i<=1; i++) if (flag[i]) {
      j = (i)? pixmap_width[0]+12 : 4;
      if (flag_image[i]) {
         XPutImage(dpy, datawin, gc, flag_image[i], 0, 0, 
                   j, h_button + 5, pixmap_width[i], pixmap_height[i]);
      } else {
	 sprintf(path, "%s/???/%s.???", FLAGPATH, flag[i]);
         XSetForeground(dpy, gc, scene->color[C_BG_TEXT].pix);
         XFillRectangle(dpy, datawin, gc, j, h_button + 5,
	                pixmap_width[i], pixmap_height[i]);
	 XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix);
         XDrawRectangle(dpy, datawin, gc, j, h_button + 5, 
                        pixmap_width[i]-1, pixmap_height[i]-1);
         XDrawString(dpy, datawin, gc, 
                     (i)? pixmap_width[0]+20:12, h_button+8+2*fonth[0], path, 
		     strlen(path));
      }
   }
   if (flag[1]) {
      XClearArea(dpy, datawin, pixmap_width[0]+4, h_button+5, 
                 8, pixmap_height_max, False);
      XClearArea(dpy, datawin, 
                 pixmap_width[0]+pixmap_width[1]+12, h_button + 5, 
                 datawin_width, pixmap_height_max, False);
   } else
      XClearArea(dpy, datawin, pixmap_width[0]+4, h_button+5, 
                 datawin_width, pixmap_height_max, False);
   k = 90;
   if (erase_text)
      XClearArea(dpy, datawin, 0, h_button+pixmap_height_max+5,
                      datawin_width, datawin_height, False);
   XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix);
   for (i=0; i<=lmax; i++) {
      j = strlen(str[i]);
      XDrawString(dpy, datawin, gc, 4, 
         h_button + pixmap_height_max+(fonth[0]+4)*(i+1)+8+
           ((i>=lstep)?10:0)+((i>=9)?10:0), 
         str[i], j);
	 k += j+2;
         data_text = realloc(data_text, (k+2)*sizeof(char));
	 if (i==lstep)
            strcat(data_text, "\n");
	 if (i==lmax) {
            for (j=1; j<=78; j++) strcat(data_text, "-");
            strcat(data_text, "\n");
	 } else
            strcat(data_text, str[i]);
         strcat(data_text, "\n");
   }

   line_y = h_button+pixmap_height_max + (lstep+1)*(fonth[0]+4)+14-fontasc[0];

   XDrawLine(dpy, datawin, gc, 0, h_button, datawin_width, h_button);
   XDrawLine(dpy, datawin, gc, 0, line_y, datawin_width, line_y); 

   if (butpix[0]!=None) {
      XCopyArea(dpy, butpix[0], datawin, gc, 0, 0,
		w_buttons-1, h_button-1, 0, 0);
      XClearArea(dpy, datawin, w_buttons-1, 0, 
                      datawin_width, h_button-1, False);
   } else
      for (i=0; i<NUM_BUTTONS; i++) {
	 char s[4];
	 XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix);
         XDrawRectangle(dpy, datawin, gc, 
                        i * w_button + 4, 3,
                        w_button - 4, h_button - 8);
	 s[0] = s[2] = '?';
	 s[1] = '1'+i;
	 s[3] = '\0';
	 XDrawString(dpy, datawin, gc, 
                     i * w_button + 8, 
                     7+fontasc[0], s, 3);
      }

   if (lmax==10) {
      j = h_button + pixmap_height_max + 11*(fonth[0]+4)+4-fontasc[0];
      XDrawLine(dpy, datawin, gc, 0, j, datawin_width, j); 
   }
   XFlush(dpy);
}


void flag_viewer(int j)
{
   struct stat buf;
   char *viewer;   
   char name[256], cmd[512];

   if (j<0 || j>num_flag_dirs) return;
   if (!flag_name || !flag_name) return;
   sprintf(name, "%s/%s/%s.%s", 
           FLAGPATH, flag_dir[j], flag_name, flag_type[j]);
   if (stat(name, &buf) || !S_ISREG(buf.st_mode)) strcat(name, ".gz");
   if (stat(name, &buf) || !S_ISREG(buf.st_mode)) return;
   if (!strcmp(flag_type[j], "eps")) viewer = ps_viewer;
      else
   if (!strcmp(flag_type[j], "svg")) viewer = svg_viewer;
      else
   viewer = im_viewer;
   sprintf(cmd, "%s %s &", viewer, name);
   system(cmd);
}

void show_flagwin(ImageLayout * scene, int raise)
{
   XEvent ev, *pev;
   int x, y, w, h, n;
   if (!flag_name) return;
   if (raise)
      XMapRaised(dpy, flagwin);
   else
      XMapWindow(dpy, flagwin);     
   XFlush(dpy);
   if (!flagwin_on || raise) usleep(20000);
   flagwin_on = 1;
   if (!big_flag_image) {
      flag_size = 1;
      big_flag_image = readIMG(scene, FLAGPATH, flag_name, flagwin_height,
                               &scene->color[C_BG_TEXT]);
      flag_size = 0;
   }
   if (raise && big_flag_image && 
       (flagwin_width != big_flag_image->width || 
        flagwin_height != big_flag_image->height)) {
      flagwin_width = big_flag_image->width;
      flagwin_height = big_flag_image->height;
      (void) get_window_placement(flagwin, &x, &y, &w, &h);
      if (w!=flagwin_width || h!=flagwin_height) {
         XResizeWindow(dpy, flagwin, flagwin_width, flagwin_height);
	 XFlush(dpy);
	 usleep(40000);
	 pev = NULL;
         n = 0;
	 while (XCheckIfEvent(dpy, &ev, evpred, (XPointer)0)) {
	    if (ev.xexpose.window != flagwin) {
	       ++n;
	       pev = (XEvent *)realloc(pev, n*sizeof(XEvent));
               pev[n-1] = ev;
	    }
	 }
         if (pev) while (n>=1) { --n; XPutBackEvent(dpy, &pev[n]); }
         if (pev) free(pev);
      }
   }

   if (big_flag_image && (big_flag_image->width > flagwin_width)) {
      h = (flagwin_width*big_flag_image->height) / big_flag_image->width;
      XDestroyImage(big_flag_image);
      flag_size = 1;
      big_flag_image = readIMG(scene, FLAGPATH, flag_name, h, 
                               &scene->color[C_BG_TEXT]);
      flag_size = 0;
   }

   XSetWindowBackground(dpy, flagwin, scene->color[C_BG_TEXT].pix);
   if (big_flag_image) {
      XPutImage(dpy, flagwin, gc, big_flag_image, 0, 0, 0, 0, 
	        big_flag_image->width, big_flag_image->height);
      XClearArea(dpy, flagwin, big_flag_image->width, 0, 
                 flagwin_width, flagwin_height, False);
      XClearArea(dpy, flagwin, 0, big_flag_image->height,
                 flagwin_width, flagwin_height, False);
   } else
      XClearWindow(dpy, flagwin);
}
	    
void view_outfile(ImageLayout * scene)
{
   struct stat buf;
   char compl[50], str[512];

   if (!*scene->outfile) return;
   *compl = '\0';
   
   #ifdef ZLIB
   if (im_compress && strcmp(scene->outfile+strlen(scene->outfile)-3,".gz"))
      strcpy(compl, ".gz");
   #endif

   sprintf(str, "%s%s", scene->outfile, compl);
   buf.st_mode = 0;
   stat(str, &buf);
   if (!S_ISREG(buf.st_mode)) return;

   get_output_type(scene);
   if (img_output==OUT_RC && *editor_cmd) {
      sprintf(str, "(%s %s%s ; rm -f %s%s ) &", editor_cmd, 
              scene->outfile, compl, scene->outfile, compl);
      system(str);
   } else
   if ((img_output==OUT_EPS || img_output==OUT_PS) && *ps_viewer) {
      sprintf(str, "%s %s%s &", ps_viewer, scene->outfile, compl);
      system(str);
   } else
   if (img_output!=OUT_EPS && img_output!=OUT_PS && *im_viewer) {
      sprintf(str, "%s %s%s &", im_viewer, scene->outfile, compl);
      system(str);
   }
   img_output = OUT_NONE;
}

void edit_rc_output(ImageLayout * scene)
{
   char ptr[256];
   strcpy(ptr, scene->outfile);
   secure_tmpnam(scene->outfile);
   strcat(scene->outfile, "_xrmap_data.rc");
   img_output = OUT_RC;
   overwrite = 1;
   open_outfile(scene);
   print_image(scene);
   view_outfile(scene);
   strcpy(scene->outfile, ptr);
}

void clear_mainwin_strips(ImageLayout * scene)
{
   if (point_shown) {
      clear_strip(scene, TOP);
      clear_strip(scene, BOTTOM);
      show_mark(scene);
      point_shown = 0;
   }
}

void show_point(ImageLayout * scene, int u, int v, int active)
{
   double x, y, eps;
   int i=0, j, k, found, popul, max;
   int up, vp, uf=0, vf=0;
   char lat[256], lon[256];
   char cmd[1024];

   if (brief_menu) return;

   found = -1;
   if (inverse_coord(scene, u, v, &x, &y)) {
      eps = 1.5/scene->gopt.zoom;
      if (but_main_pressed==1) {
	 popul = -30000;
	 max = 10;
	 if (active)
         for (i=0; i<scene->numdef; i++) 
	    if (scene->def[i][0]==(char)2) {
               double fact = 0.3334*(scene->def[i][6]-'0'+1);
	       double xp, yp;
	       char *rep;
	       int m, n;
	       rep = strdup(scene->def[i]+8);
               n=0;
	       for (m=0; m<strlen(rep); m++) {
		  if (rep[m]==' ') rep[m]='\037';
		  if (rep[m]==',' || rep[m]=='|') {
		     n++;
                     if (n<=2) rep[m] = ' ';
		  }
	       }
	       sprintf(cmd, "SHAREDIR=%s ; ", SHAREDIR);
               m = strlen(cmd);
	       n = sscanf(rep, "%s %s %s", lat, lon, cmd+m);
               free(rep);
	       xp = dms2decim(lat);
	       yp = dms2decim(lon);
	       if (n==3 && fabs(x-xp)+fabs(y-yp)<eps*fact) {
		  for (m=0; m<strlen(cmd); m++) 
                      if (cmd[m]=='\037') cmd[m]=' ';
                  strcat(cmd," &");
		  system(cmd);
	       }
	 }
         for (i=0; i<numloc; i++) {
	    if ((locations[i]->draw & SPOT_DRAWN) &&
	        fabs(x-locations[i]->lat)+fabs(y-locations[i]->lon)<eps) {
	       ScreenPt pt;
               SpherePt spt;
	       spt.sph[LONGITUDE] = locations[i]->lon;
	       spt.sph[LATITUDE] = locations[i]->lat;
	       pt = project(scene, spher2cart(scene, spt));
	       up = pt.coord[X];
               vp = pt.coord[Y];
	       j = abs(u-up);
	       k = abs(v-vp);
               if (j<3 && k<3 && j+k<=max) {
		  if (j+k<max) popul = -30000;
		  max = j+k;
		  if (locations[i]->population>popul) {
		     found = i;
		     uf = up;
		     vf = vp;
                     popul = locations[i]->population;
		  }
	       }
	    }
	 }
      }

      if (v>scene->height/2) j = TOP; else j = BOTTOM;

      if (j!=line_pos) {
	 clear_strip(scene, line_pos);
	 line_pos = j;
      }

      if (found>=0) {
         if (found==city_found) return;
	 city_found = found;
         show_datawin(scene, 1);
      }
      show_coord(scene, x, y);

   } else
      clear_mainwin_strips(scene);
}

void open_cmdwin(ImageLayout * scene)
{
    cmd_mode = MODE_CMD;
    cmd_type = M_CMD_START;
    draw_win_cmd(scene, 0);
    XMapRaised(dpy, cmdwin);
}

void open_explwin(ImageLayout * scene)
{
    if (explpix)
       XSetWindowBackgroundPixmap(dpy, explwin, explpix);
    else
       XSetWindowBackground(dpy, explwin, scene->color[C_BG_CMDWIN].pix);
    XMapRaised(dpy, explwin);
    explwin_on = 1;
    expl_shift = 0;
}

/* 
 *  SECTION 6 : X EVENTS ROUTINES
 */

void do_escape(ImageLayout * scene)
{
int i;
	line_clicked = -1;
	*cmd_string = '\0';
	caret_pos = 0;
        cmd_mode = MODE_RUN;
	cmd_type = M_RUN_START;
	memcpy(scene, scene->backup, sizeof(ImageLayout));
	if (setup_change & FONT_CHANGE) {
           for (i=0; i<=5; i++)
	      set_font(scene->ropt.font[i], i);
           setup_change &= ~FONT_CHANGE;
	}
	if (setup_change & COLOR_CHANGE) {
	   get_all_colors(scene);
	   setup_change &= ~COLOR_CHANGE;
	   if (color_depth<=8) {
	      generate(scene);
              return;
	   }
	}
	if (cmdwin_on) close_cmdwin(scene);
}

void do_activate(ImageLayout * scene, KeySym keysym)
{
char str[512], outfilename[256], compl[6];
struct stat buf;

	if (cmd_mode==MODE_MENU && cmd_type==M_MENU_SEARCH) {
	   if (!*cmd_string) {
              draw_win_cmd(scene, 2);
	      if (keysym==XK_Return && line_clicked<=3) return;
	   }
	   if (search_string) free(search_string);
           search_string = strdup(cmd_string);
	   search_city(scene);
	   search_output(scene, (keysym==XK_exclam));
	   return;
	} 

	if (cmd_mode==MODE_HELP && cmd_type==M_HELP_EDIT) {
	   int i, j;
	   char str[40];
	   i = strlen(cmd_string);
	   if (scene->numpoint && i>=2 &&
               cmd_string[i-2]=='|' && cmd_string[i-1]=='*') {
	      cmd_string = realloc(cmd_string, i+40*scene->numpoint);
	      cmd_string[i-2] = '\0';
	      for (j=0; j<scene->numpoint; j++) {
                 sprintf(str, "|%.6f,%.6f",
			 scene->mempoint[2*j], scene->mempoint[2*j+1]);
		 strcat(cmd_string, str);
	      }
	   }
           parse_define(scene, cmd_string);
	   generate(scene);
	   show_mark(scene);
	   *cmd_string = '\0';
	   draw_win_cmd(scene, 2);
	   return;
	}

	if (cmd_mode==MODE_FILE && 
            (cmd_type==M_FILE_DATA || cmd_type==M_FILE_PRINTCFG)) {
           str2value(scene, line_clicked, cmd_string);
	   if (keysym==XK_Return) {
              draw_win_cmd(scene, 2);
	      return;
	   }
	}

	if (cmd_mode==MODE_FILE && cmd_type==M_FILE_SAVE) {
	   if (line_clicked<=1) {
      	      strncpy(scene->outfile, cmd_string, 255);
	      scene->outfile[255] = '\0';
	      draw_win_cmd(scene, 2);
	      return;
	   }
	   #ifdef ZLIB
 	   if (im_compress && *scene->outfile &&
              strcmp(scene->outfile+strlen(scene->outfile)-3,".gz"))
   	      strcpy(compl, ".gz");
   	   else
	   #endif
   	      *compl = '\0';
           sprintf(outfilename, "%s%s", scene->outfile, compl);
	   if (runlevel && line_clicked==2 && !*scene->outfile) {
	     noname:
	      draw_win_string(scene, cmdwin, msg[NO_FILENAME_SPECIFIED], BOTTOM);
	      return;
	   }
	   if (line_clicked==3) {
	      if (!*scene->outfile) goto noname;
	      buf.st_mode = 0;
              stat(outfilename, &buf);
              if (!S_ISREG(buf.st_mode)) {
	       notsaved:
 	         draw_win_string(scene, cmdwin, msg[FILE_NOT_SAVED], BOTTOM);
		 return;
	      }
	      sprintf(str, msg[VIEWING_IMAGE], outfilename);
	      draw_win_string(scene, cmdwin, str, BOTTOM);
	      view_outfile(scene);
	      return;
	   }
	   if (line_clicked==4) {
	      if (!*scene->outfile) goto noname;
	      buf.st_mode = 0;
              stat(outfilename, &buf);
              if (!S_ISREG(buf.st_mode)) goto notsaved;
	      if (strcmp(outfilename+strlen(outfilename)-3,".ps") &&
                  strcmp(outfilename+strlen(outfilename)-4,".eps") &&
	          strcmp(outfilename+strlen(outfilename)-6,".ps.gz") &&
	          strcmp(outfilename+strlen(outfilename)-7,".eps.gz"))
		 goto notsaved;
	      sprintf(str, msg[PRINTING_IMAGE], outfilename);
	      draw_win_string(scene, cmdwin, str, BOTTOM);
	      if (strcmp(outfilename+strlen(outfilename)-3,".gz"))
                 sprintf(str, "%s %s &", print_cmd, outfilename);
	      else
                 sprintf(str, "gzip -cd %s | %s - &", outfilename, print_cmd);
	      system(str);
              return;
	   }
	   if (overwrite==1) overwrite=-1;
	   open_outfile(scene);
	   if (overwrite==-1) {
	      get_output_type(scene);
   	      sprintf(str, msg[WRITING_IMAGE_TO_FILE], outfilename);
	      draw_win_string(scene, cmdwin, str, BOTTOM);
	      if (img_output == OUT_EPS)
		 generate(scene);
	      else {
	         print_image(scene);
	         strcpy(((ImageLayout *)scene->backup)->outfile, scene->outfile);
                 ((ImageLayout *)scene->backup)->prepixmap = scene->prepixmap;
	      }
	      img_output = OUT_NONE;
	      overwrite = 0;
	   }
	}

	if (cmd_mode==MODE_CMD) {
	   if (*cmd_string && parse_cmd_line(scene, cmd_string, " ")) return;
	}

	if (keysym==XK_exclam || ((cmd_mode==MODE_CMD) && expert)) {
	   if (cmd_mode == MODE_MENU && cmd_type==M_MENU_LIST &&
	       search_index>=0) {
	      if (num_found==1 && search_by<=5) {
		 search_output(scene, 1);
		 return;
	      }
	      if (search_index!=-1) {
		 if (search_by==6)
		    city_found = loc_pointer[search_index];
		 else
		    city_found = search_index;
	      }
	   }
           if (!memcmp((char *)scene, (char *)scene->backup, 
               sizeof(ImageLayout))) { 
	      draw_win_string(scene, cmdwin, msg[NO_CHANGE_MADE], BOTTOM);
	      return;
	   }

           /* look whether some options have changed that force to 
              regenerate image */
           if (memcmp((char *)scene, (char *)scene->backup, 
	        sizeof(ImageLayout)-256-
                (C_ENDCOLOR-C_FG_TEXT)*sizeof(Colordata))) { 
	      check_datachanges(scene);
	      generate(scene);
	      if (datawin_on)
	         show_mark(scene);
	   }
	   if (search_index==city_found && search_index>=0) 
              show_datawin(scene, 1);
	   return;
	}

        /* Remaining text_input cases with XK_Return */
	if (text_input_mode()) {
	   if (line_clicked>=1 && line_clicked<=box_numitems) {
	      str2value(scene, line_clicked, cmd_string);
	      if (setup_change)
		 draw_win_cmd(scene, 0);
	      else
		 draw_win_cmd(scene, 2);
	   }
        } else
	   draw_win_cmd(scene, 0);
}

void filemenu(ImageLayout * scene)
{
	overwrite = 0;
	cmd_mode = MODE_FILE;
	cmd_type = M_FILE_START;
	cmd_string = (char *)realloc(cmd_string, 1);
	*cmd_string = '\0';
	cmd_killed_char = '\0';
	caret_pos = 0;
}

int click_truncated_list(int l, int total, int *level) 
{
    if (l==1 && start_list>0) {
       start_list -= (num_listed-3);
       if (start_list<0) start_list = 0;
       *level = 1;
       return 0;
    } else
    if (l==num_listed && start_list+num_listed<total) {
       start_list += (num_listed-3);
       if (start_list+num_listed>total)
	  start_list = total-num_listed;
       *level = 1;
       return 0;
    } else {
       if (line_clicked==-10)
	  *level = 1;
       else
	  *level = 2;
       return 1;
    }
}

void adjust_list(int total, int *l)
{
    if (*l==1 && start_list>0) {
       line_clicked = -10;
       start_list -= (num_listed-3);
       if (start_list<0) start_list = 0;
       *l = num_listed-1;
    } else
    if (*l==num_listed &&
       start_list+num_listed<total) {
       start_list += (num_listed-3);
       line_clicked = -10;
       if (start_list+num_listed>total)
          start_list = total-num_listed;
       *l = 2;
    }
}

void search_output(ImageLayout * scene, int force)
{
int i;
    if (num_found==0) {
       i = caret_pos;
       caret_pos = -10;
       draw_win_string(scene, cmdwin, msg[NO_MATCH_IN_SEARCH], BOTTOM);
       usleep(WARNING_TIME);
       caret_pos = i;
       draw_win_string(scene, cmdwin, search_string, BOTTOM);
    } else
    if (num_found==1 && force==1) {
	  city_found = loc_pointer[0];
	  scene->gopt.xrot = locations[city_found]->lat;
	  scene->gopt.yrot = locations[city_found]->lon;
          update_positions(scene, city_found);
	  search_index = city_found;
          check_datachanges(scene);
	  generate(scene);
          show_mark(scene);
          show_datawin(scene, 1);
    } else {
       cmd_mode = MODE_MENU;
       cmd_type = M_MENU_SEARCH;
       draw_win_cmd(scene, 0);
       cmd_type = M_MENU_LIST;
       draw_win_cmd(scene, 1);
    }
}

void convert_keysym(KeySym * key)
{
    if (*key == XK_Control_L ||
        *key == XK_Control_R ) {
	   control_pressed = 0;
	   *key = '\0';
	   return;
    }
    if (*key>=XK_KP_0 && *key<=XK_KP_9)
        *key += XK_0-XK_KP_0;
    if (*key==XK_KP_Add) *key = XK_plus;
    if (*key==XK_KP_Subtract) *key = XK_minus;
    if (*key==XK_KP_Multiply) *key = XK_asterisk;
    if (*key==XK_KP_Divide) *key = XK_slash;
    if (*key==XK_KP_Delete) *key = XK_BackSpace;
    if (*key==XK_KP_Decimal) *key = XK_period;
    if (*key==XK_KP_Enter) *key = XK_Return;
    if (*key==XK_BackSpace) *key = XK_Delete;
}

void regenerate_objects(ImageLayout *scene, int i, int j)
{
    char str[256];
    if (i)
       sprintf(str, msg[GENERATING_MAP_WITH], msg[j]);
    else
       sprintf(str, msg[GENERATING_MAP_WITHOUT], msg[j]);
    draw_win_string(scene, mainwin, str, BOTTOM);
    generate(scene);
    show_mark(scene);
}

void rotate_generate(ImageLayout *scene, int i, int j)
{
    char str[256];
    if (scene->color[i].bool==ON &&
        scene->color[i+1].bool==OFF) {
       scene->color[i].bool = ON; 
       scene->color[i+1].bool = ON; 
       sprintf(str, msg[GENERATING_MAP_WITH_OBJECTS_AND_NAMES], msg[j]);
    } 
    else
    if (scene->color[i].bool==OFF) {
       scene->color[i].bool = ON; 
       scene->color[i+1].bool = OFF; 
       sprintf(str, msg[GENERATING_MAP_WITH_OBJECTS], msg[j]);
    } 
    else {
       scene->color[i].bool = OFF; 
       scene->color[i+1].bool = OFF; 
       sprintf(str, msg[GENERATING_MAP_WITHOUT_OBJECTS], msg[j]);
    }
    draw_win_string(scene, mainwin, str, BOTTOM);
    generate(scene);
    show_mark(scene);
}

void rotate_value(ImageLayout *scene, int i)
{
    if (scene->color[i].bool == OFF) {
       scene->color[i].bool = ON;
       scene->color[i+1].bool = OFF;
    } else
    if (scene->color[i].bool == ON &&
        scene->color[i+1].bool == OFF) 
       scene->color[i+1].bool = ON;
    else
    if (scene->color[i].bool == ON &&
	scene->color[i+1].bool == ON) {
       scene->color[i].bool = OFF;
       scene->color[i+1].bool = OFF;
    }
}

void show_modified_buttons(int mode, int num)
{
   int but_x;
   if (num < 0 || num >= NUM_BUTTONS) return;
   but_x = w_button*num + 3;

   if (butpix[0]!=None)
      XCopyArea(dpy, butpix[0], datawin, gc, 
                but_x, 0, w_button-1, h_button-1, 
                but_x, 0);

   if (butpix[1]!=None &&
       mode==1 && num>=0 && butpix[1]!=None) {
      XCopyArea(dpy, butpix[1], datawin, gc, 
                but_x, 0, w_button-1, h_button-1, 
                but_x, 0);
   }

   if (butpix[2]!=None &&
      mode==2 && num>=0 && butpix[2]!=None) {
      XCopyArea(dpy, butpix[2], datawin, gc, 
                but_x, 0, w_button-1, h_button-1, 
                but_x, 0);
   }
}

void show_mouse_hint(ImageLayout * scene, int num)
{
    int i, j, w;
    
    i = w_buttons + 8;
    j = 5;
    w = XTextWidth(xfont[0], 
	   msg[BEGIN_MOUSE_HINTS+num], strlen(msg[BEGIN_MOUSE_HINTS+num]));
    XSetForeground(dpy, gc, scene->color[C_BG_CMDWIN].pix);
    XFillRectangle(dpy, datawin, gc, i+1, j+1, w+6, fonth[0]+5);
    XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix);
    XDrawRectangle(dpy, datawin, gc, i, j, w+8, fonth[0]+6);
    XDrawString(dpy, datawin, gc, i+4, j+fontasc[0]+3, 
	msg[BEGIN_MOUSE_HINTS+num], strlen(msg[BEGIN_MOUSE_HINTS+num]));
}

void erase_mouse_hint(ImageLayout * scene, int num)
{
    int i, j;
    
    i = w_buttons + 8;
    j = 5;
    XClearArea(dpy, datawin, i, j, datawin_width-i, fonth[0]+7, False);
}

int main(int argc, char **argv) {
        /* Global geometric structure */
        ImageLayout *scene; 
	/* misc variables */
        XEvent ev;
        Time ev_time = 0;
        KeySym keysym = 0;
	char *string;
	struct stat buf;
	int i, j=0, l, m;
        int button_visit = -1, hint_shown = -1, wait_iter = 0;
        char str[1024];

	/* Table for Mollweide function
	for (i=0; i<=1000; i++) {
	    double d, e;
	    d = e = (double)i*0.001;
            mollweide(&e);
	    printf("%12.10f --> %12.10f %12.10f\n", d, e, 
              log(1-e)/log(1-d));
	}
	*/

	/* the default behaviour */
	ps_viewer = strdup(PS_VIEWER); /* Should have gv installed !! */
	im_viewer = strdup(IM_VIEWER); /* Should install ImageMagick !! */
	html_viewer = strdup(HTML_VIEWER); /* Default is dillo */
	svg_viewer = strdup(SVG_VIEWER); /* Default is inkscape */
	svg_convert = strdup(SVG_CONVERT); /* Default is inkscape */
	print_cmd = strdup(PRINT_CMD); /* BSD type printing system... */
	editor_cmd = strdup(EDITOR);   /* Default editor */
	midi_cmd = strdup(MIDIPLAYER);   /* Default editor */

        *language = '\0';
	bzero(feature_descr, 6*sizeof(char **));

	cmd_string = strdup("");
	expl_implicit = strdup("");
	search_string = strdup("");
	search_index = -1;

	/* the main struct for the data file */
	scene = (ImageLayout *) malloc(sizeof(ImageLayout));
	scene->backup = (ImageLayout *)NULL;
      
        scene->projection = SPHERICAL;
	scene->position = NULL;
	scene->num_positions = 0;
	scene->aspect = 1.0;
	scene->accuracy = 1.0;
	scene->width = 0;
	scene->height = 0;
        scene->pixmap = 0;
        scene->prepixmap = 0;
	scene->numdef = 0;
	scene->nummod = 0;
	scene->modpos = NULL;
	scene->numpoint = 0;
	scene->mempoint = NULL;

	bzero(&scene->rotation, sizeof(Matrix));
	bzero(&scene->gopt, sizeof(GeomOptions));
	bzero(&scene->ropt, sizeof(RenderOptions));

	scene->gopt.zoom = 1.0;
	scene->gopt.desired_categories = 0xFFFFFFFF; /* default is all */
	scene->gopt.desired_continents = 0xFFFFFFFF; /* default is all */
	strcpy(scene->gopt.lineorder, lineorder0);

	scene->ropt.spacing_lat = 15.0;
	scene->ropt.spacing_lon = 15.0;
        scene->ropt.smartlabels = 1;  /* default is +smartlabels */

        memcpy(scene->ropt.mark_step, mark_step0, sizeof(mark_step0));
        memcpy(scene->ropt.name_step, name_step0, sizeof(name_step0));
	memcpy(scene->ropt.airport_mark, airport_mark0, sizeof(airport_mark0));
	memcpy(scene->ropt.airport_size, airport_size0, sizeof(airport_size0));
	memcpy(scene->ropt.peak_mark, peak_mark0, sizeof(peak_mark0));
	memcpy(scene->ropt.peak_size, peak_size0, sizeof(peak_size0));
	memcpy(scene->ropt.city_mark, city_mark0, sizeof(city_mark0));
	memcpy(scene->ropt.city_size, city_size0, sizeof(city_size0));
	strcpy(scene->ropt.city_filter, city_filter0);
	strcpy(scene->ropt.loc_filter, loc_filter0);
	
	*scene->mapfile = '\0';
	*scene->locfile = '\0';
	*scene->outfile = '\0';
	*scene->macrofile = '\0';
	*scene->theme = '\0';

        list_flag_dirs();

	for (i=0; i<=5; i++) {
            strcpy(scene->ropt.font[i], "6x13");
	    xfont[i] = NULL;
	}

	/* initial setting (which is to print nothing !!) */
	for (i=0; i< C_ENDCOLOR; i++)
            scene->color[i].bool = INACTIVE;

	list_lang = list_languages();

        /* read i18n file */
	for (i=1; i<argc-1; i++) 
 	   if (!strpcmp(argv[i], "language", 4)) {
	      strncpy(language, argv[i+1], 2);
	      language[2] = '\0';
	      read_i18n_file(scene);
	      argv[i+1] = language;
	      break;
	   }
        if (!*language) read_i18n_file(scene);

	/* parse system wide rcfile */
	strncpy(scene->rcfile, RCFILE, 255);
	scene->rcfile[255] = '\0';
        parse_rcfile(scene);

	/* Check whether user has specified its own rcfile(s) */
	j = 0;
	for (i=1; i<argc-1; i++) 
	  if (!strpcmp(argv[i], "rcfile", 3)) {
	     ++i;
	     if (argv[i][0] == '\0' ||
                 !strcasecmp(argv[i],"none") || 
                 !strcasecmp(argv[i],"null")) {
 	        *scene->rcfile = '\0';
	        ++j;
	        continue;
	     }
	     strncpy(scene->rcfile, argv[i], 255);
	     scene->rcfile[255] = '\0';
	     parse_rcfile(scene);
	     ++j;
	  }

	if (j==0) {
	   /* if ~/.xrmaprc exists, use that file instead (for a rcfile) */
	   scene->rcfile[0] = '\0';
	   string = getenv("HOME");
	   if (string != NULL) {
	      sprintf(scene->rcfile, "%s/.xrmaprc", string);
	      buf.st_mode = 0;
	      if (stat(scene->rcfile, &buf)) scene->rcfile[0] = '\0';
	   }
	   if (scene->rcfile[0]) parse_rcfile(scene);
	}

	fix_features_description(scene);

	/* parse the command line options */
	*cmd_string= '\0';
	for (i=1; i<argc; i++) {
	    j = strlen(cmd_string);
	    cmd_string = (char *) realloc(cmd_string, j+strlen(argv[i])+2);
	    cmd_string[j] = '\177';
	    cmd_string[j+1] = '\0';
	    strcat(cmd_string, argv[i]);
	}
	if (*cmd_string && parse_cmd_line(scene, cmd_string, "\177")) exit(-1);

	cmd_string = (char *) realloc(cmd_string, 1);
	*cmd_string = '\0';
	cmd_killed_char = '\0';
	if (scene->projection==SPHERICAL) scene->aspect = 1.0;

        /* set the window dimensions */
	if (scene->width==0 && scene->height==0) {
	   if (scene->projection==RECTANGULAR || 
               scene->projection==CYLINDRICAL ||
               scene->projection>=SINUSOIDAL) {
	      scene->width = 1000;
	      scene->height = 500 * scene->aspect;
	   } else {
	      scene->width = 672;
	      scene->height = 672 * scene->aspect;
	   }
	} else
	if (scene->height==0) {
	   if (scene->projection==RECTANGULAR || 
               scene->projection==CYLINDRICAL ||
               scene->projection>=SINUSOIDAL) {
	      scene->height = scene->width * (0.5*scene->aspect);
	   } else {
	      scene->height = scene->width * scene->aspect;
	   }
	} else
	if (scene->width==0) {
	   if (scene->projection==RECTANGULAR ||
               scene->projection==CYLINDRICAL ||
               scene->projection>=SINUSOIDAL) {
	      scene->width = scene->height / (0.5*scene->aspect);
	   } else {
	      scene->width = scene->height / scene->aspect;
	   }
	}

	/* set some default values */
        set_radius(scene);
        check_spacing(scene);

	if (!*scene->mapfile) {
	   strncpy(scene->mapfile, MAPFILE, 255); /* default */
	   scene->mapfile[255] = '\0';
	}
	if (!*scene->locfile) {
	   strncpy(scene->locfile, LOCFILE, 255); /* default */
	   scene->locfile[255] = '\0';
	   parse_locfile(scene);
	}

        /* We are now entering the GUI program */
        runlevel = 1;

	/* Open X display */
        dpy = XOpenDisplay(NULL);
	if (!dpy) {
	   if (dump_format == DUMP_STAT) printf("ABORT\n");
	   fprintf(stderr, "%s\n", msg[COULDNT_OPEN_DEFAULT_X_DISPLAY]);
	   exit(-1);

	}
        scr = DefaultScreen(dpy);
        color_depth = DefaultDepth(dpy, scr);
        bigendian = (ImageByteOrder(dpy) == MSBFirst);

        if (color_depth > 16)
            color_pad = 32;
        else if (color_depth > 8)
            color_pad = 16;
        else
            color_pad = 8;

        Root = RootWindow(dpy, scr);
        visual = DefaultVisual(dpy, scr);
	if (color_depth <= 8)
	   color_table = (unsigned char *) malloc(256);
	else
           cmap = DefaultColormap(dpy, scr);

        /* Load X fonts */
	for (i=0; i<=5; i++) {
    	   xfont[i] = XLoadQueryFont(dpy, scene->ropt.font[i]);
	   if (xfont[i] == (XFontStruct *)NULL) {
	      fprintf(stderr, msg[REPLACING_BY_DEFAULT_FONT],scene->ropt.font[i]);
              fprintf(stderr, "\n");
              strcpy(scene->ropt.font[i], "fixed");
              xfont[i] = XLoadQueryFont(dpy, scene->ropt.font[i]);
	   }
	   if (xfont[i] == (XFontStruct *)NULL) {
	      fprintf(stderr, msg[CANT_OPEN_FONT], scene->ropt.font[i]);
              fprintf(stderr, "\n");
	      exit(1);
	   }
           set_font_params(i);
	}

	/* get all colors from X colormap */
        get_all_colors(scene);

        /* open the X windows */
        mainwin = make_window(scene->width, scene->height);
        show_title(scene, mainwin);

	datawin_width = 634;
	datawin_height = 340;
	datawin = make_window(datawin_width, datawin_height);
	show_title(scene, datawin);

	flagwin_width = 720;
	flagwin_height = 480;
	flagwin = make_window(flagwin_width, flagwin_height);
	show_title(scene, flagwin);

	cmdwin_width = 634;
	cmdwin_height = cmdwin_height0;
        cmdwin = make_window(cmdwin_width, cmdwin_height);
	show_title(scene, cmdwin);

	explwin_width = 360;
	explwin_height = explwin_height0;
        explwin = make_window(explwin_width, explwin_height);
	show_title(scene, explwin);

        if (!datapix)
           datapix = xim2pix(readIMG(scene, PIXMAPPATH, datapix_name, 0,
                                     &scene->color[C_BG_TEXT]));
        if (!cmdpix)
           cmdpix = xim2pix(readIMG(scene, PIXMAPPATH, cmdpix_name, 0,
                                    &scene->color[C_BG_TEXT]));
        if (!explpix)
           explpix = xim2pix(readIMG(scene, PIXMAPPATH, explpix_name, 0,
                                     &scene->color[C_BG_TEXT]));
        set_auxil_win_background(scene);

	for (i=0; i<=2; i++) {
           if (butpix_name[i])
              strcpy(str, butpix_name[i]);
	   else
              sprintf(str, DEFAULTBUTTONS, i);
           butpix[i] = xim2pix(readIMG(scene, PIXMAPPATH, str, 0,
                                       &scene->color[C_BG_TEXT]));
	}
        get_button_dimensions();

	if (dump_format!=DUMP_STAT && (img_output==OUT_NONE || preview>0.0))
           XMapWindow(dpy, mainwin);

       	create_GCs(scene);
        parse_theme(scene);

	if (!scene->backup)
           scene->backup = (ImageLayout *) malloc(sizeof(ImageLayout));
	memcpy(scene->backup, scene, sizeof(ImageLayout));

	/* generate the image */
	if (start_menu && img_output == OUT_NONE) {
	   image_init(scene);
	   ((ImageLayout *)scene->backup)->pixmap = scene->pixmap;
	   /* disturb a little bit the zoom value to force update in
              case 'activate' is run */
	   ((ImageLayout *)scene->backup)->gopt.zoom = 
               scene->gopt.zoom * 1.000001;
	   keysym = (KeySym) start_menu;
	   start_menu = 0;
	   goto startkey;
	} else {
	   if (*search_string) {
	      search_city(scene);
	      if (num_found!=1)
		 generate(scene);
	      search_output(scene, 1);
	   } else
	      generate(scene);
	}

        /* quit after preview time if user only wants file output */
	if (img_output != OUT_NONE) {
	   if (preview>0.0) {
	      usleep((int)(preview*1000000));
	   }
	   exit(0);
        }

	/* check X events */
	for (;;) {
	  if (!XCheckIfEvent(dpy, &ev, evpred, (XPointer)0)) {
             usleep(20000);
	     i = 0;
	     if (datawin_on && button_visit>=0) {
	        if (hint_shown != button_visit) {
		   ++wait_iter;
		   if (wait_iter>=20) {
	              if (hint_shown >=0)
		         erase_mouse_hint(scene, hint_shown);
		      show_mouse_hint(scene, button_visit);
		      hint_shown = button_visit;
		      wait_iter = 0;
		   }
		}
	     }
	     if (datawin_on && button_visit==-1) {
	        if (hint_shown >=0) {
		   erase_mouse_hint(scene, hint_shown);
		   hint_shown = -1;
		}
	     }

	     if (time_count==0 && datawin_on && 
                 city_found>=0 && city_found<numloc &&
                 locations[city_found]->obj!='l') {
	        i = locations[city_found]->tz;
	        set_time(i, str);
		update_time(scene, str);
	     }
	     time_count = (time_count+1)%33;
	     continue;
	  }

	  if (ev.type==EnterNotify || ev.type==LeaveNotify) {
	     if (ev.xexpose.window == mainwin && but_main_pressed!=2)
	        clear_mainwin_strips(scene);
             if (ev.xexpose.window == datawin) {
                show_modified_buttons(0, button_visit);
		erase_mouse_hint(scene, button_visit);
		button_visit = -1;
		hint_shown = -1;
		but_data_pressed = 0;
	     }
             continue;
	  }

          if (ev.type==ButtonRelease) 
             but_main_pressed = 0;
          if (ev.type==ButtonPress)
	     but_main_pressed = ev.xbutton.button;

          if (ev.xclient.message_type == wm_protocols &&
              ev.xclient.format == 32 &&
              ev.xclient.data.l[0] == wm_delete_window) {
 	     if (ev.xexpose.window == mainwin) {
	        if (brief_menu==3) exit(0);
		brief_menu = 3;
                show_brief_menu(scene);
	     }
	     if (ev.xexpose.window == cmdwin) {
                close_cmdwin(scene);
	     }
	     if (ev.xexpose.window == datawin) {
                close_datawin(scene);
	     }
	     if (ev.xexpose.window == explwin) {
                close_explwin(scene);
	     }
	     if (ev.xexpose.window == flagwin) {
                close_flagwin(scene);
	     }	     
	  }

	  if (ev.xexpose.window == flagwin) {
	     if (ev.type == ButtonPress && ev.xbutton.button<=Button3) {
	        XClearArea(dpy, flagwin, 10, 10, 200, 
                                (1+((num_flag_dirs+1)>>1))*(fonth[0]+12)+9, 
                                False);
		XSetForeground(dpy, gc, scene->color[C_FG_TEXT].pix);
		strcpy(str, msg[READJUST_WINDOW]);
 	        XDrawString(dpy, flagwin, gc, 32, 
                            20+fontasc[0], str, strlen(str));
		XDrawRectangle(dpy, flagwin, gc, 
                               16, 17,
                               187, fonth[0]+6);
		for (i=0; i<num_flag_dirs; i++) {
		   XDrawRectangle(dpy, flagwin, gc, 
                                  16+97*(i&1), 
                                  17+(1+(i>>1))*(fonth[0]+12),
                                  90, fonth[0]+6);
		   strcpy(str, flag_dir[i]);
 	           XDrawString(dpy, flagwin, gc, 
                               40+95*(i&1),
                               20+fontasc[0]+(1+(i>>1))*(fonth[0]+12),
                               str, strlen(str));
		}
		XFlush(dpy);
	     }
	     if (ev.type == ButtonRelease && ev.xbutton.button<=Button3) {
	        j = -2;
		for (i=0; i<=((num_flag_dirs+1)>>1); i++)
		   if (ev.xbutton.x>=16 && ev.xbutton.x<=203 &&
                       ev.xbutton.y>=17+i*(fonth[0]+12) && 
                       ev.xbutton.y<=13+(i+1)*(fonth[0]+12)) {
		      if (i==0)
		         j = -1;
                      else {
			 j = 2*i-2;
                         if (ev.xbutton.x>=113) j += 1;
                         else
                         if (ev.xbutton.x>=106) j = -2;
		      }
                      break;
		   }
                if (j==-1)
                   show_flagwin(scene, 1);
	        else
	           if (big_flag_image) show_flagwin(scene, 0);
	        flag_viewer(j);
	     }
	     if (ev.type == KeyRelease) {
                char buffer[1];
                XLookupString((XKeyEvent *)&ev, buffer, 1, &keysym, NULL);
                if (keysym == XK_equal || keysym == XK_KP_Equal)
		   show_flagwin(scene, 1);
	     }
	  }

	  if (ev.xexpose.window == explwin)
	  switch(ev.type) {
  	     case LeaveNotify:
	          but_expl_pressed &= ~2;
		  break;
  	     case EnterNotify:
	          but_expl_pressed |= 2;
		  break;

	     case MotionNotify:
	     case ButtonPress:
                  if (ev.type==ButtonPress && ev.xbutton.button<=Button3) 
                     but_expl_pressed = 1;
	     case ButtonRelease:
                if (ev.type==ButtonRelease) {
                   but_expl_pressed = 0;
		   if (ev.xbutton.button==4) goto expl_up;
		   if (ev.xbutton.button==5) goto expl_down;
		}
	        if (ev.xbutton.y>=0 && ev.xbutton.y<fonth[0]+8) {
		   int i, j=-1;
		   if (ev.type!=ButtonRelease) break;
	           for (i=0; i<=4; i++) 
		      if (ev.xbutton.x>8*i*char_width &&
                         ev.xbutton.x<8*(i+1)*char_width) {
		         j = i;
			 break;
		      }
		   if (j==-1 && ev.xbutton.x>explwin_width-8*char_width) {
		      close_explwin();
		      break;
		   }
		   if (j==0) {
		      if (getenv("HOME")) {
                         strcpy(expl_currdir, getenv("HOME"));
                         strcat(expl_currdir, "/");
		      }
		   }
		   if (j==1) {
                      strcpy(expl_currdir, SHAREDIR);
                      strcat(expl_currdir, "/");
		   }
		   if (j==2) {
                      strcpy(expl_currdir, "/");
		   }
		   if (j==3) {
                      getcwd(expl_currdir, sizeof(expl_currdir));
                      strcat(expl_currdir, "/");
		   }
		   if (j>=0 && j<=3) {
		      free_dirlist(expl_dirtable);
		      expl_dirtable = NULL;
		      expl_shift = 0;
		      show_explwin(scene, 0, 1);
		   }
		} else
		if (ev.xbutton.y<2*(fonth[0]+8)) {
		   if (ev.type!=ButtonRelease) break;
		   expl_shift = 0;
		   show_explwin(scene, 0, 1);
		} else {
		   if (ev.xbutton.x>explwin_width-13 &&
                       ev.xbutton.x<explwin_width) {
		      if (ev.xbutton.y<=2*fonth[0]+28) {
		         if (ev.type!=ButtonPress) break;
                         goto expl_up;
		      } else
		      if (ev.xbutton.y>=explwin_height-12) {
		         if (ev.type!=ButtonPress) break;
                         goto expl_down;
		      } else {
			 if (ev.type==MotionNotify && but_expl_pressed!=1)
			    break;
			 expl_shift = 
                            ((ev.xbutton.y-2*fonth[0]-28)*expl_table_entries)/
			    (explwin_height-2*fonth[0]-40);
			 if (expl_shift>=expl_table_entries-2)
                            expl_shift = expl_table_entries-2;
 		         show_explwin(scene, 0, 2);
		      }
		   } else {
		      if (ev.type!=ButtonRelease) break;
		      show_explwin(scene, ev.xbutton.x, ev.xbutton.y);
		   }
		}
	        break;

	     case KeyRelease: {
                char buffer[1];
                XLookupString((XKeyEvent *)&ev, buffer, 1, &keysym, NULL);
                if (keysym==XK_Up || keysym == XK_Page_Up) {
		expl_up:
		   if (expl_shift<=0) break;
		   expl_shift -= expl_lines - 2;
		   if (expl_shift<0) expl_shift = 0;		   
		   show_explwin(scene, 0, 2);
		} else
                if (keysym==XK_Down || keysym == XK_Page_Down) {
		expl_down:
		   if (expl_shift>=expl_table_entries - 3) break;
     	           expl_shift += expl_lines - 3;
		   if (expl_shift>expl_table_entries - 3)
		      expl_shift = expl_table_entries - 3;
		   show_explwin(scene, 0, 2);
		} else
                if (keysym==XK_Escape) {
		   close_explwin(scene);
	           ev.xexpose.window = mainwin;
		   XMapRaised(dpy, mainwin);
                   XSetInputFocus(dpy, mainwin, 
                               RevertToPointerRoot, CurrentTime);
		   }
	        }
		break;
   
	     default:
	        break;
	  }

	  if (ev.xexpose.window == datawin)
	  switch(ev.type) {
	     case ButtonPress:
	     case MotionNotify :
	       if (ev.xbutton.button > Button3) break;
	        j = 1;
	        for (i=0; i<NUM_BUTTONS; i++)
                if (ev.xbutton.x>i*w_button+3 &&
                    ev.xbutton.x<(i+1)*w_button &&
                    ev.xbutton.y>3 &&
                    ev.xbutton.y<h_button-3) {
		   if (ev.type == ButtonPress) {
		      but_data_pressed = ev.xbutton.button;
		      show_modified_buttons(2, i);
		   }
		   j = 0;
		   if (button_visit != i) {
		      ev_time = ev.xbutton.time;
		      if (ev.type == MotionNotify) {
		      	 show_modified_buttons(0, button_visit);
		      	 show_modified_buttons(1, i);
		      }
		      button_visit = i;
		      wait_iter = 0;
		   }
		}
		if (j) {
                   show_modified_buttons(0, button_visit);
		   button_visit = -1;
		   wait_iter = 0;
		}
	        break;

	     case ButtonRelease:
	       if (ev.xbutton.button > Button3) break;
                but_data_pressed = 0;
	        show_modified_buttons(1, button_visit);
		erase_mouse_hint(scene, button_visit);
		button_visit = -1;
		hint_shown = -1;
		wait_iter = 0;
	        show_mark(scene);
		if (city_found>=0 &&
                    locations[city_found]->obj=='l' &&
		    locations[city_found]->rank==-1) {
		    if (ev.xbutton.x>5*w_button+3 &&
                        ev.xbutton.x<6*w_button &&
                        ev.xbutton.y>3 &&
		        ev.xbutton.y<24 ) {
			goto recenter;
		    }
                    break;
		}
	        for (i=0; i<NUM_BUTTONS; i++)
                if (ev.xbutton.x>i*w_button+3 &&
                    ev.xbutton.x<(i+1)*w_button &&
                    ev.xbutton.y>3 &&
                    ev.xbutton.y<h_button-3) {
		   char cmd[512], path[256], code[4], cia_code[4];
		   struct stat buf;
                   char tmpname[80];
                   FILE *ft;
		   if (city_found>=0 && (
                       locations[city_found]->obj=='c' || 
                       locations[city_found]->obj=='a' || 
                       locations[city_found]->obj=='b' || 
                       locations[city_found]->obj=='p' || 
                       locations[city_found]->obj=='l')) {
                      if (locations[city_found]->obj=='l')
			 j = locations[city_found]->rank;
		      else
                         j = timezones[locations[city_found]->tz]->country;
	              strcpy(code, countries[j]->code2);
		      code[0] = tolower(code[0]);
		      code[1] = tolower(code[1]);
		      strcpy(cia_code, countries[j]->cia);
		      j = 0;
		      if (i==0) {
		       factbook_retry:
			 if (j==0)
		            sprintf(path, "%s/%s-%s.txt", 
			            CIATEXTPATH, code, language);
			 if (j==1)
		            sprintf(path, "%s/%s-en.txt", 
				    CIATEXTPATH, code);
			 if (j==2)
		            sprintf(path, "%s/%s.txt", 
				    CIATEXTPATH, code);
			 ++j;
		      } else
		      if (i==1) {
		       html_retry:
			 if (j==0)
		            sprintf(path, "%s/%s-%s.html", 
				    CIAGEOSPATH, cia_code, language);
			 if (j==1)
		            sprintf(path, "%s/%s-en.html", 
				    CIAGEOSPATH, cia_code);
			 if (j==2)
		            sprintf(path, "%s/%s.html", 
				    CIAGEOSPATH, cia_code);
			 ++j;
		      } else
		      if (i==2) {
		       anthem_retry:
			 if (j==0)
		            sprintf(path, "%s/%s-%s.ant", 
				    ANTHEMPATH, code, language);
			 if (j==1)
		            sprintf(path, "%s/%s-en.ant", 
				    ANTHEMPATH, code);
			 if (j==2)
		            sprintf(path, "%s/%s.ant", 
				    ANTHEMPATH, code);
			 ++j;
		      } else
		      if (i==3) {
		         static char *suff[] = { "mid", "mp3", "ogg" };
		       music_retry:
		         sprintf(path, "%s/%s.%s", HYMNPATH, code, suff[j]);
			 ++j;
		      }
		      else
		      if (i==4) {
		       map_retry:
			 if (j==0) {
		            sprintf(path, "%s/%s.pdf", PDFMAPSPATH, code);
			    sprintf(cmd, "%s %s &", ps_viewer, path);
			 }
			 if (j==1) {
		            sprintf(path, "%s/%s-map.gif", 
				    CIAMAPSPATH, cia_code);
			    sprintf(cmd, "%s %s &", im_viewer, path);
			 }
                         ++j;
		      }
		      else
		      if (i==5) {
			 goto recenter;
		      }
		      bzero(&buf, sizeof(buf));
	              buf.st_mode = 0;
		      stat(path, &buf);
                      if (!S_ISREG(buf.st_mode)) {
                         if (i==0 && j<=2) goto factbook_retry;
                         if (i==1 && j<=2) goto html_retry;
                         if (i==2 && j<=2) goto anthem_retry;
                         if (i==3 && j<=2) goto music_retry;
                         if (i==4 && j<=2) goto map_retry;
			 break;
		      }
                      if (i==1) {
                         sprintf(cmd,
                           "%s %s &", html_viewer, path);
                         system(cmd);
			 break;
                      }
		      if (i<=2) {
			 secure_tmpnam(tmpname);
                         strcat(tmpname, "_xrmap_");
			 strcat(tmpname, code);
		         if (i==0)
                            strcat(tmpname, ".txt");
                         else
		         if (i==2)
                            strcat(tmpname, ".ant");
                         ft = fopen(tmpname, "w");
                         if (ft) {
                            if (data_text && *data_text)
                               fprintf(ft, data_text);
			    if (i==2)
			       fprintf(ft, "%s\n\n", msg[NATIONAL_ANTHEM]);
                            fclose(ft);
                            sprintf(cmd,
                               "( cat %s >> %s ; %s %s ; rm -f %s ) &",
                               path, tmpname, editor_cmd, 
                               tmpname, tmpname);
                            system(cmd);
			 }
			 break;
		      }
		      if (i==3) {
                         sprintf(cmd, "%s %s &", midi_cmd, path);
                         system(cmd);
			 break;
		      }
		      if (i==4) {
			 system(cmd);
			 break;
		      }
		   }
		}
	        if (ev.xbutton.button == 3) {
		 recenter:
		   if (city_found>=0 && city_found<numloc) {
                      XMapRaised(dpy, mainwin);
		      scene->gopt.xrot = locations[city_found]->lat;
		      scene->gopt.yrot = locations[city_found]->lon;
		      draw_win_string(scene, mainwin, msg[RECENTERING_TO_POINT], BOTTOM);
		      generate(scene);
		      show_mark(scene);
 		      city_shown = 1;
		      break;
		   }
		}
                if ((ev.xbutton.x>=4 && ev.xbutton.x<4+pixmap_width[0] &&
                     ev.xbutton.y>=h_button+4 && 
                     ev.xbutton.y<h_button+4+pixmap_height[0]) ||
                    (ev.xbutton.x>=12+pixmap_width[0] && 
                     ev.xbutton.x<12+pixmap_width[0]+pixmap_width[1] &&
                     ev.xbutton.y>=h_button+4 && 
                     ev.xbutton.y<h_button+4+pixmap_height[1])) {
                   char path[80];
		   char *ptr, *ptrp;
                   ptr = ptrp = NULL;
                   if (locations[city_found]->obj=='l') {
                      i = locations[city_found]->rank;
                      if (i>=0) ptr = countries[i]->flags;
		   } else {
		      i = locations[city_found]->tz;
		      if (i>=0) ptr = timezones[i]->flags;
		   }
                   if (ptr) {
		      strncpy(path, ptr, 78);
                      path[78] = '\0';
                      ptr = path;
                      if ((ptrp = index(ptr, ','))) {
                         *ptrp = '\0';
                         ptrp += 1;
		      }
                      if (ptrp && ev.xbutton.x>4+pixmap_width[0])
			 ptr = ptrp;
		      if (flag_name && strcmp(ptr, flag_name)) {
			 if (big_flag_image) XDestroyImage(big_flag_image);
			 big_flag_image = NULL;
			 free(flag_name);
		      }
		      flag_name = strdup(ptr);
		      show_flagwin(scene, 1);
                      break;
		   }
		}
                break;

	     case KeyPress:
	     case KeyRelease: {
                  char buffer[1];
                  XLookupString((XKeyEvent *)&ev, buffer, 1, &keysym, NULL);
                  if (keysym==XK_k || keysym==XK_K) {
		     close_datawin(scene);
		     break;
		  }
	          ev.xexpose.window = mainwin;
		  XMapRaised(dpy, mainwin);
                  XSetInputFocus(dpy, mainwin, 
                                 RevertToPointerRoot, CurrentTime);
		  break;
	     }

  	     default:
		break;
	  }

	  if (ev.xexpose.window == cmdwin)
	  switch(ev.type) {
	     case KeyPress : {
                   char buffer[1];
                   XLookupString((XKeyEvent *) &ev, buffer, 1, &keysym, NULL);
		   if (keysym == XK_Control_L ||
                       keysym == XK_Control_R ) {
		       control_pressed = 1;
		   }
		}
		break;
                	     
	     case KeyRelease : {
                char buffer[1];
                XLookupString((XKeyEvent *) &ev, buffer, 1, &keysym, NULL);
		/* printf("%d\n", keysym); */

	        convert_keysym(&keysym);
		if (keysym==0) break;

                if ((keysym==XK_k || keysym==XK_K) && !text_input_mode()) {
		   close_datawin(scene);
		   close_cmdwin(scene);
		   break;
		}

		if (keysym==XK_Escape) {
		   do_escape(scene);
		   break;
		}
	        if (keysym==XK_Return || keysym==XK_exclam) {
		   do_activate(scene, keysym);
		   break;
		} 
		if (cmd_mode==MODE_MENU && cmd_type==M_MENU_START) {
                   if (keysym==XK_d || keysym==XK_D ||
                       keysym==XK_f || keysym==XK_F ||
                       keysym==XK_h || keysym==XK_H ||
                       keysym==XK_n || keysym==XK_N ||
                       keysym==XK_c || keysym==XK_C ||
                       keysym==XK_o || keysym==XK_O ||
                       keysym==XK_q || keysym==XK_Q ||
		       keysym==XK_s || keysym==XK_S) {
		          if (keysym==XK_h || keysym==XK_H) {
			     cmd_mode = MODE_HELP;
			     cmd_type = M_HELP_START;
			     draw_win_cmd(scene, 1);
			     break;
			  }
			  cmd_mode = MODE_RUN;
			  cmd_type = M_RUN_START;
			  goto startkey;
		       }
		}
		if (!expert && keysym==XK_Up) {
		   if (!click_input_mode()) break;
		   if (cmd_mode==MODE_HELP && cmd_type==M_HELP_SHORTCUTS) {
		      if (start_shortcut>0) --start_shortcut;
                      draw_win_cmd(scene, 2);
                      break;
		   }
		   l = line_clicked;
		   if (l==-1) 
		      l = box_numitems;
		   else
		   if (l==1) {
                      l = -1;
		      line_clicked = -1;
		      *cmd_string = '\0';
		      caret_pos = 0;
		   } else
		      --l;
                   goto pre_do_click;
	        }
		if (!expert && keysym==XK_Down) {
		   if (!click_input_mode()) break;
		   if (cmd_mode==MODE_HELP && cmd_type==M_HELP_SHORTCUTS) {
		      ++start_shortcut;
                      draw_win_cmd(scene, 2);
                      break;
		   }
		   l = line_clicked;
		   if (l==-1) 
                      l = 1;
		   else {
		      ++l;
		      if (l>box_numitems) {
		         l = -1;
		         line_clicked = -1;
		         *cmd_string = '\0';
		         caret_pos = 0;
		      }
		   }
	        pre_do_click:
	           if (cmd_mode==MODE_MENU && cmd_type==M_MENU_LIST)
		      adjust_list(num_found, &l);
		   if (cmd_mode==MODE_HELP && cmd_type==M_HELP_EDIT)
		      adjust_list(scene->numpoint, &l);
                   goto do_click;
		}
		if (!expert && keysym==XK_Tab) {
                   if (cmd_mode==MODE_FILE) 
                      cmd_type = (cmd_type%M_FILE_SAVE)+1;
		   else
                   if (cmd_mode==MODE_OPTION)
                      cmd_type = (cmd_type%M_OPTION_CAT)+1;
		   else
                   if (cmd_mode==MODE_COLOR) 
                      cmd_type = (cmd_type%M_COLOR_CIL)+1;
                   if (cmd_mode==MODE_HELP) {
                      cmd_type = (cmd_type%M_HELP_EDIT)+1;
                      if (cmd_type==M_HELP_SHORTCUTS)
			 start_shortcut = 0;
		   }
		   line_clicked = -1;
	           draw_win_cmd(scene, 0);
		   break;
		}
		if (!expert && keysym==XK_Page_Up) {
		   if (cmd_type) {
		      if (cmd_mode==MODE_MENU && cmd_type==M_MENU_LIST)
			 cmd_type = M_MENU_SEARCH;
		      else
                         cmd_type = 0;
		   }
		   else {
		      cmd_mode = MODE_MENU;
		      cmd_type = M_MENU_START;
	           }
	           draw_win_cmd(scene, 0);
	           break;
	        }
                if (text_input_mode()) {
		   if (control_pressed) {
		      if (keysym==XK_space) {
			 keysym = 31;
			 goto specialchar;
		      }
                      if (keysym==XK_a || keysym==XK_A)
		         caret_pos = 0;
		      else
                      if (keysym==XK_b || keysym==XK_B ||
                         keysym==XK_p || keysym==XK_P) {
                         if (caret_pos>0) --caret_pos;
		      }
		      else
                      if (keysym==XK_f || keysym==XK_F ||
                          keysym==XK_n || keysym==XK_N) {
                         if (caret_pos<strlen(cmd_string)) ++caret_pos;
		      }
		      else
		      if (keysym==XK_d || keysym==XK_D) {
		         int l, m;
                         l = strlen(cmd_string);
		         for (m=caret_pos; m<l; m++)
			    cmd_string[m] = cmd_string[m+1];
		      }
		      else
		      if (keysym==XK_h || keysym==XK_H) {
		         int l, m;
                         l = strlen(cmd_string);
		         if (caret_pos) {
		            for (m=caret_pos-1; m<l; m++)
			       cmd_string[m] = cmd_string[m+1];
			    --caret_pos;
		         }
		      }
		      else
		      if (keysym==XK_k || keysym==XK_K) {
			 cmd_killed_length = strlen(cmd_string);
			 cmd_killed_pos = caret_pos;
		         cmd_killed_char = cmd_string[caret_pos];
		         cmd_string[caret_pos] = '\0';
	              }
	              else
		      if (keysym==XK_y || keysym==XK_Y) {
			 if (cmd_killed_char) {
			    caret_pos = cmd_killed_pos;
			    cmd_string[cmd_killed_pos] = cmd_killed_char;
			    cmd_string[cmd_killed_length] = '\0';
		         }
		      }
		      else
                      if (keysym==XK_e || keysym==XK_E)
			 caret_pos = strlen(cmd_string);
		      else
                      if (keysym==XK_w || keysym==XK_W)
			 write_primary(cmd_string+caret_pos);
		   } 
                   else
		   if (keysym==XK_Right) {
		      if (caret_pos<strlen(cmd_string)) ++caret_pos;
		   } 
                   else		      
		   if (keysym==XK_Left) {
		      if (caret_pos>0) --caret_pos;
		   } 
                   else		      		      
                   if (keysym==XK_Delete) {
		      int l, m;
                      l = strlen(cmd_string);
		      if (caret_pos) {
		         for (m=caret_pos-1; m<l; m++)
		            cmd_string[m] = cmd_string[m+1];
			 --caret_pos;
		      }
		   }
		   else
		   if (keysym>=32 && keysym<=255) {
		      int l, m;
		   specialchar:
		      if (cmd_string) 
                         l = strlen(cmd_string);
		      else
		         l = 0;
                      cmd_string = (char *)realloc(cmd_string, l+2);
                      cmd_killed_char = '\0';
		      for (m=l; m>caret_pos; m--)
			  cmd_string[m] = cmd_string[m-1];
                      cmd_string[caret_pos] = keysym;
		      cmd_string[l+1] = '\0';
                      ++caret_pos;
	           }
		   draw_win_string(scene, cmdwin, cmd_string, BOTTOM);
	        }
	        break;
	     }
	     break;

	     case ButtonPress :
	        if (ev.xbutton.button > Button3) break;
		line_pos = -1;
	        expl_output = 0;
		if (cmd_mode && ev.xbutton.y<=fonth[0]+5) break;
		if (cmd_mode==MODE_MENU) break;
		if (cmd_mode && ev.xbutton.y>=cmdwin_height-fonth[0]-6) {
		   if (text_input_mode())
                      do_caret(scene, ev.xbutton.x);
		   break;
		}
		break;

             case ButtonRelease :
	        expl_output = 0;
		if (ev.xbutton.button==2 && cmd_mode && text_input_mode() && 
                    ev.xbutton.y>=cmdwin_height-fonth[0]-6) {
		   char *ptr;
		   int i, l, lp;
		   ptr = read_primary();
		   l = strlen(ptr);
   	           for (i=0; i<l; i++)
	               if (ptr[i]<' ') ptr[i] = ' ';
		   lp = strlen(cmd_string);
                   do_caret(scene, ev.xbutton.x);
		   cmd_string = realloc(cmd_string, l+lp+4);
		   for (i=lp; i>=caret_pos; i--)
		       cmd_string[i+l] = cmd_string[i];
		   for (i=0; i<l; i++)
		       cmd_string[caret_pos+i] = ptr[i];
		   free(ptr);
		   caret_pos +=l;
                   draw_win_string(scene, cmdwin, cmd_string, BOTTOM);
		   break;
		}
		if (ev.xbutton.button==3 && cmd_mode && text_input_mode() && 
                    ev.xbutton.y>=cmdwin_height-fonth[0]-6) {
		   char *ptr;
		   int l, lp;
		   l = caret_pos;
                   do_caret(scene, ev.xbutton.x);
		   if (caret_pos>l)
		      lp = caret_pos;
		   else {
		      lp = l;
                      l = caret_pos;
		   }
		   ptr = strdup(cmd_string+l);
		   ptr[lp-l] = '\0';
		   write_primary(ptr);
		   free(ptr);
		}

                if (ev.xbutton.button >= Button4 && 
                    cmd_mode == MODE_HELP &&
		    cmd_type == M_HELP_SHORTCUTS) {
		   if (ev.xbutton.button == Button4) {
 		      if (start_shortcut>0) --start_shortcut; 
		   }
		   if (ev.xbutton.button == Button5) {
 		      ++start_shortcut; 
		   }
		   draw_win_cmd(scene, 2);
                   break;
		}

                if (ev.xbutton.button >= Button4 && 
                    ((cmd_mode == MODE_MENU &&
		      cmd_type == M_MENU_LIST) ||
                     (cmd_mode == MODE_HELP && 
                      (cmd_type == M_HELP_EDIT || 
                       cmd_type == M_HELP_EXTRA)))) {
		   if (ev.xbutton.button == Button4) {
 		      if (start_list>0) --start_list; 
		   }
		   if (ev.xbutton.button == Button5) {
		      int m;
		      if (cmd_mode == MODE_MENU)
		 	 m = num_found;
		      else {
			 if (cmd_type == M_HELP_EXTRA)
                            m = num_doc;
			 else
			    m = scene->numpoint;
		      }
 		      ++start_list; 
                      if (start_list + num_listed >= m)
			 start_list = m - num_listed;
		      if (start_list<0) start_list = 0;
		   }
		   draw_win_cmd(scene, 1);
                   break;
		}
                if (ev.xbutton.button >= Button4) break;

		if (!expert && ev.xbutton.y<=fonth[0]+5) {
		   if (ev.xbutton.x>=cmdwin_width-action_width) {
		      brief_menu = 3;
                      do_escape(scene);
		      show_brief_menu(scene);
                      break;
		   }
		   if (ev.xbutton.x>=cmdwin_width-2*action_width) {
		      do_escape(scene);
		      break;
		   }
		   if (ev.xbutton.x>=cmdwin_width-3*action_width) {
                      do_activate(scene, XK_exclam);
		      break;
		   }

		   cmd_mode = MODE_MENU;
		   for (i=M_MENU_HELP; i>=1; i--) {
		      if (ev.xbutton.x>=
                             XTextWidth(xfont[0], labels_generalmenu, 
                                        spacing_generalmenu*(i-1)-1))
			 break;
		   }
	           if (i==M_MENU_HELP) {
		      cmd_mode = MODE_HELP;
		      cmd_type = M_HELP_START;
		   }
		   if (i==M_MENU_FILE) {
		      cmd_mode = MODE_FILE;
		      cmd_type = M_FILE_START;
                   }
		   if (i==M_MENU_CMD) {
		      cmd_mode = MODE_CMD;
		      cmd_type = M_CMD_START;
                   }
                   if (i==M_MENU_SEARCH) {
		      cmd_type = M_MENU_SEARCH;
		      free(cmd_string);
		      cmd_string = strdup(search_string);
		      caret_pos = strlen(search_string);
	           }	    
		   if (i==M_MENU_OPTION) {
		      cmd_mode = MODE_OPTION;
		      cmd_type = M_OPTION_START;
		   }
		   if (i==M_MENU_COLOR) {
		      cmd_mode = MODE_COLOR;
                      cmd_type = M_COLOR_START;
		   }
		   if (i==M_MENU_HELP) {
		      cmd_mode = MODE_HELP;
		      cmd_type = M_HELP_START;
                   }
                   draw_win_cmd(scene, 0);
		   break;
		}

		if (!expert && ev.xbutton.y>=fonth[0]+16 &&
                    ev.xbutton.y<=2*fonth[0]+21) {

                   line_clicked = -1;
		   *cmd_string = '\0';
		   caret_pos = 0;

		   if (cmd_mode==MODE_FILE) {
		      cmd_type = M_FILE_SAVE;
		      for (i=M_FILE_SAVE; i>=1; i--) {
		         if (ev.xbutton.x<
                             XTextWidth(xfont[0], labels_filemenu, 
                                                  spacing_filemenu*i-1))
			 cmd_type = i;
		      }
		      if (cmd_type == M_FILE_SAVE)
			 overwrite = 0;
		   }

                   if (cmd_mode==MODE_OPTION) {
		      cmd_type = M_OPTION_CAT;
		      for (i=M_OPTION_CAT; i>=1; i--) {
		         if (ev.xbutton.x<XTextWidth(xfont[0],
                             labels_optionmenu, spacing_optionmenu*i-1))
			 cmd_type = i;
		      }
		   }

                   if (cmd_mode==MODE_COLOR) {
		      int i;
		      cmd_type = M_COLOR_CIL;
		      for (i=M_COLOR_CIL; i>=1; i--) {
		      if (ev.xbutton.x<XTextWidth(xfont[0],
                         labels_colormenu, spacing_colormenu*i-1))
			 cmd_type = i;
		      }
		   }
                   if (cmd_mode==MODE_HELP) {
		      cmd_type = M_HELP_EDIT;
		      for (i=M_HELP_EDIT; i>=1; i--) {
		      if (ev.xbutton.x<XTextWidth(xfont[0],
                         labels_helpmenu, spacing_helpmenu*i-1))
			 cmd_type = i;
		      }
		      if (cmd_type==M_HELP_EDIT) {
			 start_list = 0;
                         show_mark(scene);
		      }
		      if (cmd_type==M_HELP_EXTRA)
		         start_list = 0;
		   }
		   draw_win_cmd(scene, 1);
		   break;
		}

                if (cmd_mode==MODE_HELP && cmd_type==M_HELP_SHORTCUTS) {
                   if (ev.xbutton.y>box_y + box_numitems*box_spacing)
		      ++start_shortcut;
                   if (ev.xbutton.y>box_y + box_spacing &&
		       ev.xbutton.y<box_y + box_spacing + box_height) {
		      if (start_shortcut>0) --start_shortcut;
		   }
		   draw_win_cmd(scene, 2);
                   break;
		}

                /* Click released on the bottom strip */
		if (ev.xbutton.y>=cmdwin_height-fonth[0]-6) {
		   if (point_shown)
		      draw_win_cmd(scene, 0);
		   else
   		   if (text_input_mode())
		      do_caret(scene, ev.xbutton.x);
		   break;
		}
                /* Click released somewhere not on the top/bottom strips */
                if (click_input_mode()) {
                   l = -1;
		   if (ev.xbutton.x>box_x && ev.xbutton.x<box_x+box_width) {
		      j = ((int)ev.xbutton.y - box_y);
		      m = 0;
		      while (j<0) { j += box_spacing; m += 1; }
		      j = j/box_spacing - m;
		      if (ev.xbutton.y>box_y+j*box_spacing &&
			  ev.xbutton.y<box_y+j*box_spacing+box_height)
			 l = j;
		   }
		do_click:
 		   expl_output = 0;
		   if (l>=1 && l<=box_numitems) {
		      if (cmd_mode==MODE_HELP && cmd_type==M_HELP_SHORTCUTS) {
			 draw_win_cmd(scene, 1);
			 break;
		      }
		      if (cmd_mode==MODE_HELP && cmd_type==M_HELP_DOC) {
                         char cmd[256];
			 if (l==box_numitems)
			    show_manual();
			 else {
			    if (strstr(doc_descr[l-1], ".rc")) {
			        sprintf(cmd, "xrmap -rcfile %s/%s &",
                                     DOCPATH, doc_descr[l-1]);
			    } else
			    if (strstr(doc_descr[l-1], ".png") ||
				strstr(doc_descr[l-1], ".jpg") ||
				strstr(doc_descr[l-1], ".gif")) {
			         sprintf(cmd, "%s %s/%s &",
				     im_viewer, DOCPATH, doc_descr[l-1]);			       
			    } else {
                              if (strncmp(editor_cmd, "emx", 3))
			         sprintf(cmd, "%s %s/%s &",
				     editor_cmd, DOCPATH, doc_descr[l-1]);
                              else
			         sprintf(cmd, "%s -edit 0 %s/%s &",
				     editor_cmd, DOCPATH, doc_descr[l-1]);
			    }
			    system(cmd);
			 }
			 line_clicked = l;
			 draw_win_cmd(scene, 1);			 
			 break;
		      }
		      if (cmd_mode==MODE_HELP && cmd_type==M_HELP_EXTRA) {
                         char cmd[256];
			 if (start_list && l==1) {
			    start_list -= (num_listed/2 - 1);
			    if (start_list<0) start_list = 0;
			    line_clicked = -1;
			    draw_win_cmd(scene, 1);
			    break;
			 }
			 if (start_list + num_listed < num_doc && 
			     l==num_listed) {
                            start_list += (num_listed/2 - 1);
                            line_clicked = -1;
			    draw_win_cmd(scene, 1);
                            break;
			 }
                         if (strncmp(editor_cmd, "emx", 3))
			    sprintf(cmd, "%s %s/%s &",
			            editor_cmd, CIAEXTRAPATH, 
				    doc_descr[start_list+l-1]);
                         else
			    sprintf(cmd, "%s -edit 0 %s/%s &",
				    editor_cmd, CIAEXTRAPATH, 
				    doc_descr[start_list+l-1]);
			 system(cmd);
			 line_clicked = l;
			 draw_win_cmd(scene, 1);			 
			 break;
		      }
                      if (cmd_mode==MODE_HELP && cmd_type==M_HELP_EDIT) {
			 int level;
                         line_clicked = l;
			 if (click_truncated_list(l,scene->numpoint, &level)) {
			    int i = l+start_list-1;
			    write_point_primary(scene, i);
			    show_mark(scene);
			 } else
                            line_clicked = -10;
			 draw_win_cmd(scene, level);
			 break;
		      }
		      if (line_clicked == l || 
			  (cmd_mode==MODE_MENU && cmd_type==M_MENU_LIST)) {
			 int j=0;
                         if (cmd_mode==MODE_FILE) {
			    if (cmd_type==M_FILE_DATA) {
			       if (l==1)
				  sprintf(expl_currdir, "%s/rc/",SHAREDIR);
			       if (l>=2 && l<=4) {
				  getcwd(expl_currdir, 256);
				  strcat(expl_currdir, "/");
			       }
			       if (l==5)
				  sprintf(expl_currdir, "%s/themes/",SHAREDIR);
			       if (l==6)
				  sprintf(expl_currdir, "%s/pixmaps/optional/",
                                          SHAREDIR);
		               if (expl_dirtable) free_dirlist(expl_dirtable);
		               expl_dirtable = NULL;
		               expl_shift = 0;
			       if (expl_implicit) free(expl_implicit);
			       expl_implicit = strdup(expl_currdir);
			       if (l==6)
				 sprintf(expl_implicit,"%s/pixmaps/",SHAREDIR);
			       expl_output = 1;
			       show_explwin(scene, 0, 0);
			    }
			    if (cmd_type==M_FILE_PRINTCFG) {
			       if (l==4) {
				  if (ps_rot==0) ps_rot = 90;
				  else
				  if (ps_rot==90) ps_rot = -90;
				  else
				  if (ps_rot==-90) ps_rot = 0;
				  cmd_string = (char *) realloc(cmd_string, 4);
	                          cmd_killed_char = '\0';
				  sprintf(cmd_string, "%d", ps_rot);
				  caret_pos = strlen(cmd_string);
			       }
			       if (l==6) {
			          ps_frame = 1-ps_frame;
			          cmd_string = (char *) realloc(cmd_string, 2);
			          cmd_string[0] = (ps_frame)? '+':'-';
			          cmd_string[1] = '\0';
	                          cmd_killed_char = '\0';
			       }
			       if (l==7) {
			          ps_grayscale = 1-ps_grayscale;
			          cmd_string = (char *) realloc(cmd_string, 2);
			          cmd_string[0] = (ps_grayscale)? '+':'-';
			          cmd_string[1] = '\0';
	                          cmd_killed_char = '\0';
			       }
			       if (l==8) {
			          im_compress = 1-im_compress;
			          cmd_string = (char *) realloc(cmd_string, 2);
			          cmd_string[0] = (im_compress)? '+':'-';
			          cmd_string[1] = '\0';
	                          cmd_killed_char = '\0';
			       }
			       if (l==9 && *scene->macrofile) {
				  sprintf(str, "if [ ! -r %s ] ; "
                                               "then cat %s > %s ; fi",
				     scene->macrofile, 
				     SHAREDIR"/postscript/private.ps", 
                                     scene->macrofile);
				  system(str);
                                  sprintf(str, "%s %s &",
				     editor_cmd, scene->macrofile);
				  system(str);
			       }
			    }
			    if (cmd_type==M_FILE_SAVE) {
			       if (line_clicked==1) {
				  getcwd(expl_currdir, 256);
				  strcat(expl_currdir, "/");
		                  if (expl_dirtable) 
                                     free_dirlist(expl_dirtable);
		                  expl_dirtable = NULL;
		                  expl_shift = 0;
                                  expl_output = 1;
			          show_explwin(scene, 0, 0);
			       }
			       if (line_clicked==5) {
		                  draw_win_cmd(scene, 2);
			          goto print_automatic;
			       }
			       do_activate(scene, XK_Return);
			       break;
			    }
			 }		 
                         if (cmd_mode==MODE_MENU) {
			    if (cmd_type==M_MENU_SEARCH) {
			       search_by = l;
			       do_activate(scene, XK_Return);
			       break;
			    }
			    if (cmd_type==M_MENU_LIST) {
			       int level;
			       if (click_truncated_list(l,num_found, &level)) {
                                  city_found = loc_pointer[start_list+l-1];
                                  line_clicked = l;
				  if (search_by==6) {
				     search_index = start_list+l-1;
				     memcpy(&scene->gopt, 
                                         &scene->position[start_list+l-1].xrot,
                                         4*sizeof(double));
                                     if (datawin_on)
			                show_datawin(scene, 1);
			             draw_win_cmd(scene, level);
				     break;
				  }
			          search_index = city_found;
	                          scene->gopt.xrot=locations[city_found]->lat;
	                          scene->gopt.yrot=locations[city_found]->lon;
			          show_datawin(scene, 1);
			       }
			       draw_win_cmd(scene, level);
			       break;
			    }
			 }
			 if (cmd_mode==MODE_OPTION) {
			    if (cmd_type==M_OPTION_PARAM) {
			       if (l==1) {
                                  scene->projection = 
                                     (scene->projection+1)%NUMPROJ;
				  cmd_string = (char *) realloc(cmd_string, 3);
	                          cmd_killed_char = '\0';
				  visible = 1;
				  sprintf(cmd_string, "%d", scene->projection);
			       }
			       if (l==NUM_PARAM-3) {
                                  scene->ropt.latcoord =
                                     (scene->ropt.latcoord + 1) % 3;
                                  scene->ropt.loncoord = scene->ropt.latcoord;
				  cmd_string = (char *) realloc(cmd_string, 4);
	                          cmd_killed_char = '\0';
                                  cmd_string[0] = get_grid_coordinates(scene->ropt.latcoord, 0);
                                  cmd_string[1] = get_grid_coordinates(scene->ropt.loncoord, 1);
				  cmd_string[2] = '\0';
			       }
			       if (l==NUM_PARAM-2) {
                                  dms = 1-dms;
				  cmd_string[0] = (dms)? '+':'-';
				  cmd_string[1] = '\0';
                                  update_auxil_windows(scene);
			       }
			       if (l==NUM_PARAM-1) {
				  scene->gopt.transparent = 1-scene->gopt.transparent;
				  cmd_string = (char *) realloc(cmd_string, 2);
				  cmd_string[0] = 
                                     (scene->gopt.transparent)? '+' : '-';
				  cmd_string[1] = '\0';
	                          cmd_killed_char = '\0';
			       }
			       if (l==NUM_PARAM) {
				  secure = 1-secure;
				  cmd_string = (char *) realloc(cmd_string, 2);
				  cmd_string[0] = (secure)? '+' : '-';
				  cmd_string[1] = '\0';
	                          cmd_killed_char = '\0';
			       }
			    }
			    if (cmd_type==M_OPTION_HIERARCHY) {
                               if (l==NUM_HIERARCHY-3) {
				  scene->ropt.smartlabels = 1-scene->ropt.smartlabels;
				  cmd_string = (char *) realloc(cmd_string, 2);
			          cmd_string[0] = (scene->ropt.smartlabels)? '+':'-';
				  cmd_string[1] = '\0';
	                          cmd_killed_char = '\0';
			       }
                               if (l==NUM_HIERARCHY-2) {
				  scene->ropt.placetext = 1-scene->ropt.placetext;
				  cmd_string = (char *) realloc(cmd_string, 2);
			          cmd_string[0] = (scene->ropt.placetext)? '+':'-';
				  cmd_string[1] = '\0';
	                          cmd_killed_char = '\0';
			       }
                               if (l==NUM_HIERARCHY) {
                                  char *ptr = strstr (list_lang, language)+3;
                                  if (!ptr || ptr>=list_lang+strlen(list_lang))
				     ptr = list_lang;
				  cmd_string = (char *) realloc(cmd_string, 4);
				  strncpy(language, ptr, 2);
				  language[2] = '\0';
				  strcpy(cmd_string, language);
                         	  read_i18n_file(scene);
	                          fix_features_description(scene);
			          draw_win_cmd(scene, 0);
			          break;
			       }
			    }
			    if (cmd_type==M_OPTION_MARKS) {
	                       switch(l) {
	                          case 1: rotate_value(scene, C_CITY_CIRCLE);
				          break;
	                          case 2: rotate_value(scene,C_AIRPORT_SYMBOL);
				          break;
	                          case 3: rotate_value(scene, C_OBSERV_SYMBOL);
				          break;
	                          case 4: rotate_value(scene, C_PEAK_TRIANGLE);
				          break;
                                  case 5: scene->color[C_LOC_LAND].bool = 
                                            !scene->color[C_LOC_LAND].bool;
                                          break;
                                  case 6: scene->color[C_LOC_WATER].bool = 
                                            !scene->color[C_LOC_WATER].bool;
                                          break;
                                  case 7: scene->color[C_LON_GRID].bool = 
                                            !scene->color[C_LON_GRID].bool;
                                          break;
                                  case 8: scene->color[C_LAT_GRID].bool =
                                            !scene->color[C_LAT_GRID].bool;
                                          break;
                                  case 9: scene->color[C_MAIN_LINES].bool = 
                    			!scene->color[C_MAIN_LINES].bool;
                                          break;
                                  case 10: scene->color[C_EARTH_CONTOUR].bool =
                                           !scene->color[C_EARTH_CONTOUR].bool;
                                          break;
                                  case 11: scene->color[C_BG_SKY].bool =
                                            !scene->color[C_BG_SKY].bool;
                                          break;
                                  case 12: scene->color[C_FG_STARS].bool =
                                            !scene->color[C_FG_STARS].bool;
                                           break;
                    	          default: break;
			       }
			       cmd_string = realloc(cmd_string, 3);
			       value2str(scene, l, cmd_string, 0);
			    }
			    if (cmd_type>=M_OPTION_CONTIN) {
                               j = 1<<(l-1);
			    }
			    if (cmd_type==M_OPTION_CONTIN) {
			       if (scene->gopt.desired_continents & j) {
				  scene->gopt.desired_continents &= ~j;
				  *cmd_string = '-';
			       } else {
				  scene->gopt.desired_continents |= j;
			          *cmd_string = '+';
			       } 
			    }
			    if (cmd_type==M_OPTION_CAT) {
			       if (scene->gopt.desired_categories & j) {
				  scene->gopt.desired_categories &= ~j;
				  *cmd_string = '-';
			       } else {
			          scene->gopt.desired_categories |= j;
				  *cmd_string = '+';
			       } 
			    }
			 }
		         if (cmd_mode==MODE_COLOR) {
			    if (cmd_type>=M_COLOR_LABELS+(l==1)) {
			       j = feature_index[cmd_type-1]+l-1;
			       scene->color[j].bool = 1-scene->color[j].bool;
			       *cmd_string = (scene->color[j].bool)? '+' : '-';
			    }
			 }
		      } else {
			if (cmd_mode==MODE_FILE && cmd_type==M_FILE_SAVE &&
                            line_clicked==1 && *cmd_string)
			   strcpy(scene->outfile, cmd_string);
		        line_clicked = l;
	                if (cmd_mode==MODE_MENU && cmd_type==M_MENU_SEARCH) {
 	                   search_by = l;
		           draw_win_cmd(scene, 2);			   
			   break;
	                }
			value2str(scene, line_clicked, str, 0);
		        l = strlen(str);
		        cmd_string = (char *)realloc(cmd_string, l+2);
		        strcpy(cmd_string, str);
	                cmd_killed_char = '\0';
			if (cmd_mode==MODE_OPTION && 
                            cmd_type==M_OPTION_HIERARCHY) {
			   if (line_clicked==1)
			      cmd_string[5] = '\0';
			   if (line_clicked==NUM_HIERARCHY)
			      cmd_string[2] = '\0';
			   l = strlen(cmd_string);
			}
		        caret_pos = l;
		      }
		   }
		   draw_win_cmd(scene, 2);
		   break;
		}
		if (cmd_mode==MODE_MENU) break;
		if (cmd_mode && ev.xbutton.y>=scene->height-fonth[0]-6) {
                   do_caret(scene, ev.xbutton.x);
	           break;
		}
	        break;
	  }


        if (ev.xexpose.window == mainwin)
 	   switch(ev.type) {
	      case KeyPress : {
                   char buffer[1];
                   XLookupString((XKeyEvent *) &ev, buffer, 1, &keysym, NULL);
		   if (keysym == XK_Control_L ||
                       keysym == XK_Control_R ) {
		       control_pressed = 1;
		   }
	      }
	      break;
                	     
	      case KeyRelease : {
                char buffer[1];
                XLookupString((XKeyEvent *) &ev, buffer, 1, &keysym, NULL);

	      startkey:
	        convert_keysym(&keysym);

                if (brief_menu) {
		   if (keysym == XK_Escape)
		      brief_menu = 0;
                   if ((brief_menu==1 || brief_menu==2) 
		       && keysym == XK_space)
		      brief_menu = 3-brief_menu;
		   if (brief_menu == 3 && keysym != XK_q && keysym != XK_Q)
		      brief_menu = 0;
		   if (brief_menu == 4)
		      brief_menu = 0;
		}
		show_brief_menu(scene);

		if (keysym==0) break;
                else
		if (keysym==XK_Return) {
		   exposed |= MAIN_WINDOW;
		}
                else
		if (keysym==XK_at) {
		   if (!explwin_on) {
                      getcwd(expl_currdir, sizeof(expl_currdir));
                      strcat(expl_currdir, "/");
	              open_explwin(scene);
		   }
                } 
                else
		if (keysym==XK_colon) {
		   double fact;
                   fact = 1.0;
                   if (scene->gopt.zoom>1.0)
		      fact = 1.0/(1.0+0.5*atan(scene->gopt.zoom));
		   sprintf(str, 
                      "earthview -h %d -lat %g %g -lon %g %g &",
                      scene->height,
		      scene->gopt.xrot - fact*90.0/scene->gopt.zoom,
		      scene->gopt.xrot + fact*90.0/scene->gopt.zoom,
		      scene->gopt.yrot - fact*180.0/scene->gopt.zoom,
		      scene->gopt.yrot + fact*180.0/scene->gopt.zoom);
                   system(str);
		} 
                else
                if (keysym==XK_degree) {
                   dms = 1-dms;
		} 
                else
                if (keysym==XK_less) {
		   parse_locfile(scene);
		   list_flag_dirs();
                   generate(scene);
		   show_mark(scene);
		} 
                else
                if (keysym==XK_ampersand || keysym==XK_Print) {
		    char name[256];
		print_automatic:
		    strcpy(name, scene->outfile);
		    secure_tmpnam(scene->outfile);
                    strcat(scene->outfile, "_xrmap_out.eps");
                    sprintf(str, msg[WRITING_IMAGE_TO_FILE], scene->outfile);
                    draw_win_string(scene, mainwin, str, BOTTOM);
		    if (cmd_mode == MODE_FILE && cmd_type==M_FILE_SAVE) {
                       draw_win_string(scene, cmdwin, str, BOTTOM);
		    }
		    img_output = OUT_EPS;
		    overwrite = 1;
   		    generate(scene);
		    img_output = OUT_NONE;
		    sprintf(str, "( %s %s ; rm -f %s ) &", 
                       ps_viewer, scene->outfile, scene->outfile);
		    system(str);
        	    overwrite = 0;
		    if (cmd_mode == MODE_FILE && cmd_type==M_FILE_SAVE) {
		       draw_win_cmd(scene, 2);
                    } else
		       strcpy(scene->outfile, name);
		    break;
		} 
		else
                if (keysym==XK_Delete) {
		   if (scene->num_positions>=2) {
		      XYZPosition pos;
		      i = scene->num_positions-1;
		      pos = scene->position[i];
		      for (j=i; j>0; j--)
                          scene->position[j] =scene->position[j-1];
		      scene->position[0] = pos;
                      memcpy(&scene->gopt, &scene->position[i].xrot, 
                             4*sizeof(double));
                      generate(scene);
                      if (scene->position[i].loc>=0) {
			 city_found = scene->position[i].loc;
			 show_datawin(scene, 1);
		      }
		      break;
		   }
		}
		else
	        if (keysym==XK_q || keysym==XK_Q) {
		   if (brief_menu == 3) exit(0);
                   brief_menu = 3;
		   show_brief_menu(scene);
		} else
		if (keysym==XK_d || keysym==XK_D) {
        	   normalize_size_cmdwin();
		   open_cmdwin(scene);
                   break;
		} 
		else
		if (keysym==XK_asterisk)
                   edit_rc_output(scene);
		else
		if (keysym==XK_exclam) {
		   cmdwin_height = fonth[0]+6;
		   expert = 1;
		   XResizeWindow(dpy, cmdwin, cmdwin_width, cmdwin_height);
                   XMapRaised(dpy, cmdwin);
		   XResizeWindow(dpy, cmdwin, cmdwin_width, cmdwin_height);
                   cmd_mode = MODE_CMD;
                   cmd_type = M_CMD_START;
                   draw_win_cmd(scene, 0);
		} else
                if (keysym==XK_k || keysym==XK_K) {
		   close_datawin(scene);
		   break;
		}
		else
		if (keysym==XK_f || keysym==XK_F) {
                   filemenu(scene);
		   normalize_size_cmdwin();
	           draw_win_cmd(scene, 0);
		   break;
		}
#ifdef SEG_SCAN
		else
		if (keysym==XK_w || keysym==XK_W) {
                   seg_scan(scene);
		}
#endif
		else
		if (keysym==XK_o || keysym==XK_O) {
		   cmd_mode = MODE_OPTION;
		   cmd_type = M_OPTION_START;
		   normalize_size_cmdwin();
		   draw_win_cmd(scene, 0);
		}
		else
		if (keysym==XK_c || keysym==XK_C) {
		   cmd_mode = MODE_COLOR;
		   cmd_type = M_COLOR_START;
		   normalize_size_cmdwin();
		   draw_win_cmd(scene, 0);
		}
		else
		if (keysym==XK_n || keysym==XK_N) {
		   cmd_mode = MODE_HELP;
		   cmd_type = M_HELP_EDIT;
		   start_list = 0;
		   normalize_size_cmdwin();
		   draw_win_cmd(scene, 0);
		}
		else
		if (keysym==XK_s || keysym==XK_S) {
		   cmd_mode = MODE_MENU;
		   cmd_type = M_MENU_SEARCH;
		   free(cmd_string);
		   cmd_string = strdup(search_string);
		   caret_pos = strlen(search_string);
		   normalize_size_cmdwin();
		   draw_win_cmd(scene, 0);
		}
                else
		if (keysym==XK_m || keysym==XK_M || keysym==XK_Tab) {
		   normalize_size_cmdwin();
		   if (cmdwin_on) {
		      XMapRaised(dpy, cmdwin);
		   } else {
		      cmd_mode = MODE_MENU;
		      cmd_type = M_MENU_START;
		      draw_win_cmd(scene, 0);
		   }
		}
                else
                if (keysym==XK_i || keysym==XK_I)
		   rotate_generate(scene, C_CITY_CIRCLE, OBJECT_TYPE_CITIES);
                else
                if (keysym==XK_a || keysym==XK_A)
		   rotate_generate(scene, C_AIRPORT_SYMBOL,
                                          OBJECT_TYPE_AIRPORTS);
                else
                if (keysym==XK_b || keysym==XK_B)
		   rotate_generate(scene, C_OBSERV_SYMBOL,
                                          OBJECT_TYPE_OBSERVATORIES);
                else
                if (keysym==XK_p || keysym==XK_P)
		   rotate_generate(scene, C_PEAK_TRIANGLE, OBJECT_TYPE_PEAKS);
		else
                if (keysym==XK_l || keysym==XK_L) {
		   if (scene->color[C_LOC_LAND].bool==ON || 
                       scene->color[C_LOC_WATER].bool==ON) {
                      scene->color[C_LOC_LAND].bool = OFF;
                      scene->color[C_LOC_WATER].bool = OFF;
		      regenerate_objects(scene, WITHOUT,OBJECT_TYPE_LOCATIONS);
		   } else {
                      scene->color[C_LOC_LAND].bool = ON;
                      scene->color[C_LOC_WATER].bool = ON;
		      regenerate_objects(scene, WITH, OBJECT_TYPE_LOCATIONS);
		   }
                }
		else
                if (keysym==XK_e || keysym==XK_E) {
		   if (scene->projection == SPHERICAL) {
                      scene->color[C_EARTH_CONTOUR].bool = 
                         !scene->color[C_EARTH_CONTOUR].bool;
		      if (scene->color[C_EARTH_CONTOUR].bool)
	                 regenerate_objects(scene, WITH,
                                 OBJECT_TYPE_EARTH_CONTOUR);
		      else
	                 regenerate_objects(scene, WITHOUT,
                                 OBJECT_TYPE_EARTH_CONTOUR);
		   }
		} 
		else
                if (keysym==XK_g || keysym==XK_G) {
		   if (scene->color[C_LAT_GRID].bool==ON ||
		       scene->color[C_LON_GRID].bool==ON) {
		      int done = 0;
		      if (scene->color[C_LAT_GRID].bool==ON &&
			  scene->ropt.latcoord == 0) {
			 done = 1;
                         scene->ropt.latcoord = 1;
		      }
		      if (scene->color[C_LON_GRID].bool==ON &&
			  scene->ropt.loncoord == 0) {
			 done = 1;
                         scene->ropt.loncoord = 1;
		      }
		      if (!done) {
                         scene->ropt.latcoord = 0;
                         scene->ropt.loncoord = 0;
                         scene->color[C_MAIN_LINES].bool = OFF;
                         scene->color[C_LAT_GRID].bool = OFF; 
                         scene->color[C_LON_GRID].bool = OFF; 
	                    regenerate_objects(scene, WITHOUT,
                               OBJECT_TYPE_GRIDLINES);
		      } else
	                    regenerate_objects(scene, WITH,
                               OBJECT_TYPE_GRIDLINES);
		   } else {
                      scene->color[C_MAIN_LINES].bool = ON;
                      scene->color[C_LAT_GRID].bool = ON; 
                      scene->color[C_LON_GRID].bool = ON; 
	                 regenerate_objects(scene, WITH,
                           OBJECT_TYPE_GRIDLINES);
		   }
                }
		else
		if (keysym==XK_t || keysym==XK_T) {
                   scene->color[C_MAIN_LINES].bool
                      = !scene->color[C_MAIN_LINES].bool;
                   if (scene->color[C_MAIN_LINES].bool)
	              regenerate_objects(scene, WITH, OBJECT_TYPE_TROPICS);
                   else
	              regenerate_objects(scene, WITHOUT, OBJECT_TYPE_TROPICS);
		}
		else
		if (keysym==XK_r || keysym==XK_R) {
	           reverse = 1 - reverse;
		   get_all_colors(scene);
		   draw_win_string(scene, mainwin,
                         msg[REVERSING_COLORS], BOTTOM);
		   generate(scene);
                }
		else
		if (keysym==XK_plus) {
	           draw_win_string(scene, mainwin, msg[ZOOMING_BY_SQRT2], BOTTOM);
                   scene->gopt.zoom *= sqrt(2);
	           if (scene->gopt.zoom>MAXZOOM) scene->gopt.zoom = MAXZOOM;
		   generate(scene);
		}
                else
		if (keysym==XK_minus) {
	           draw_win_string(scene, mainwin, msg[REDUCING_BY_SQRT2], BOTTOM);
                   scene->gopt.zoom /= sqrt(2);
	           if (scene->gopt.zoom<MINZOOM) scene->gopt.zoom = MINZOOM;
		   generate(scene);
		}
		else
		if (keysym==XK_Right) {
                   scene->gopt.yrot += angle_inc(scene->gopt.zoom);
	           sprintf(str, msg[MOVING_TO_LONGITUDE], scene->gopt.yrot);
		   draw_win_string(scene, mainwin, str, BOTTOM);
		   generate(scene);
		}
		else
		if (keysym==XK_Left) {
                   scene->gopt.yrot -= angle_inc(scene->gopt.zoom);
	           sprintf(str, msg[MOVING_TO_LONGITUDE], scene->gopt.yrot);
		   draw_win_string(scene, mainwin, str, BOTTOM);
		   generate(scene);
		}
		else
		if (keysym==XK_Up) {
                   scene->gopt.xrot += angle_inc(scene->gopt.zoom);
	           sprintf(str, msg[MOVING_TO_LATITUDE], scene->gopt.xrot);
		   draw_win_string(scene, mainwin, str, BOTTOM);
		   generate(scene);
		}
                else
		if (keysym==XK_Down) {
                   scene->gopt.xrot -= angle_inc(scene->gopt.zoom);
	           sprintf(str, msg[MOVING_TO_LATITUDE], scene->gopt.xrot);
		   draw_win_string(scene, mainwin, str, BOTTOM);
		   generate(scene);
		}
		else
                if (keysym==XK_Home) {
                   scene->gopt.yrot -= 15.0;
	           sprintf(str, msg[MOVING_TO_LONGITUDE], scene->gopt.yrot);
		   draw_win_string(scene, mainwin, str, BOTTOM);
		   generate(scene);
		}
                else
                if (keysym==XK_End) {
                   scene->gopt.yrot += 15.0;
	           sprintf(str, msg[MOVING_TO_LONGITUDE], scene->gopt.yrot);
		   draw_win_string(scene, mainwin, str, BOTTOM);
		   generate(scene);
		}
		else
                if (keysym==XK_Page_Up) {
                   scene->gopt.xrot += 15.0;
	           sprintf(str, msg[MOVING_TO_LATITUDE], scene->gopt.xrot);
		   draw_win_string(scene, mainwin, str, BOTTOM);
		   generate(scene);
		}
                else
                if (keysym==XK_Page_Down) {
                   scene->gopt.xrot -= 15.0;
	           sprintf(str, msg[MOVING_TO_LATITUDE], scene->gopt.xrot);
		   draw_win_string(scene, mainwin, str, BOTTOM);
		   generate(scene);
		}
		else
		if (keysym == XK_h || keysym == XK_H)
		      show_manual();
		else
		if (keysym == XK_v || keysym == XK_V) {
		   show_version(scene, mainwin);
		}
		else
		if (keysym == XK_question) {
                   sprintf(str, msg[ZOOM_AND_POSITION],
		      scene->gopt.zoom, scene->aspect,
                      scene->gopt.xrot, scene->gopt.yrot, scene->gopt.zrot);
                   draw_win_string(scene, mainwin, str, TOP);
		}
		else
		if (keysym == XK_quotedbl) {
		   cmd_mode = MODE_HELP;
		   cmd_type = M_HELP_SHORTCUTS;
        	   normalize_size_cmdwin();
		   XMapRaised(dpy, cmdwin);
		   line_clicked = -1;
		   cmdwin_on = 1;
		   draw_win_cmd(scene, 0);                         
		}
                else
		if (keysym != XK_Shift_L && 
                    keysym != XK_Shift_R ) {
		    if (brief_menu==0)
		       brief_menu = 1;
		    show_brief_menu(scene);
		}
	      }
	     break;

 	     case ButtonPress :
	        but_main_pressed = ev.xbutton.button;
		if (but_main_pressed!=2)
	           show_point(scene, ev.xbutton.x, ev.xbutton.y, !secure);
		if (but_main_pressed==3) {
                   mouse_x1 = mouse_x2 = ev.xbutton.x;
                   mouse_y1 = mouse_y2 = ev.xbutton.y;
		   maxmove = 0;
		}
                break;

 	     case ButtonRelease :
	        but_main_pressed = 0;
                clear_mainwin_strips(scene);             

                if (brief_menu) {
		   int m = 0;
                   if (brief_menu == 1)
		      m = BEGIN_MAP_FEATURES - BEGIN_LIST_SHORTCUTS + 1;
                   if (brief_menu == 2)
		      m = END_MAP_FEATURES - BEGIN_MAP_FEATURES + 1;
                   if (brief_menu == 3)
		      m = 1;
		   j = 0;
		   for (i=1; i<=m; i++) {
		      if (ev.xbutton.x>=30 && ev.xbutton.x<=91 &&
                          ev.xbutton.y>= i * (fonth[0]+12) + 20 &&
                          ev.xbutton.y<=(i+1)* (fonth[0]+12) + 13)
			 j = i;
		   }
                   if (brief_menu==1 && j==1) {
		      brief_menu = 3;
		      show_brief_menu(scene);
		      break;
		   }
                   if ((brief_menu==1 || brief_menu==2) && j==m) {
		      brief_menu = 3-brief_menu;
		      show_brief_menu(scene);
		      break;
		   }
                   if (brief_menu==3 && j==1) exit(0);
                   if (brief_menu==4) {
		      brief_menu = 0;
                      show_brief_menu(scene);
		      break;
		   }
		   if (j>=1) {
		      if (brief_menu==1)
		         keysym = msg[BEGIN_LIST_SHORTCUTS+j-1][3];
		      if (brief_menu==2)
		         keysym = msg[BEGIN_MAP_FEATURES+j-1][3];
		      brief_menu = 0;
		      XClearWindow(dpy, mainwin);
		      show_mark(scene);		      
		      goto startkey;
		   }
		   if (brief_menu) {
		      if (ev.xbutton.button==2)
		         brief_menu = 3-brief_menu;
		      else
			 brief_menu = 0;
		   }
	           show_brief_menu(scene);
                   break;
		}
		
                if (cmd_mode==MODE_HELP && cmd_type==M_HELP_EDIT &&
                    ev.xbutton.button==1) {
		      double x, y;
                      if (inverse_coord(scene, 
                            ev.xbutton.x, ev.xbutton.y, &x, &y)) {
			 ++scene->numpoint;
			 scene->mempoint = (double *) realloc(scene->mempoint,
                            2*scene->numpoint*sizeof(double));
			 scene->mempoint[2*scene->numpoint-2] = x;
			 scene->mempoint[2*scene->numpoint-1] = y;
			 line_clicked = scene->numpoint - start_list;
		      }
		    write_point_primary(scene, scene->numpoint-1);
		    show_mark(scene);
	            if (cmdwin_on) draw_win_cmd(scene, 1);
		}

  	        /* Button 2 released, raise the menu */
		if (ev.xbutton.button==2) {
		   if (brief_menu == 0) brief_menu = 1;
		      else
		   if (brief_menu <= 2) brief_menu = 3 - brief_menu;
		   show_brief_menu(scene);
		}

		/* Button 3 released, recenter the map */
		if (ev.xbutton.button==3) {
		      double x, y;
                      if (maxmove<=2) {
                         if (inverse_coord(scene, 
                            ev.xbutton.x, ev.xbutton.y, &x, &y)) {
		            scene->gopt.xrot = x;
		            scene->gopt.yrot = y;
	                    draw_win_string(scene,
                               mainwin, msg[RECENTERING_TO_POINT], BOTTOM);
			    show_new_center(scene,ev.xbutton.x,ev.xbutton.y,7);
		            generate(scene);
		         } else
                            XClearWindow(dpy, mainwin);
		      } else {
                         int u, v;
			 double f, g;
			 u = (mouse_x1+mouse_x2)/2;
			 v = (mouse_y1+mouse_y2)/2;
                         if (inverse_coord(scene, u, v, &x, &y)) {
			    f=(1.0+abs(mouse_x2-mouse_x1))/(1.0+scene->width);
			    g=(1.0+abs(mouse_y2-mouse_y1))/(1.0+scene->height);
			    if (f/g<5.0 && g/f<5.0) {
                               scene->gopt.xrot = x;
                               scene->gopt.yrot = y;
			       scene->gopt.zoom /= sqrt((f*f+g*g)*0.5);
			       if (scene->gopt.zoom>MAXZOOM) 
                                  scene->gopt.zoom = MAXZOOM;
	                       draw_win_string(scene,
                                  mainwin, msg[RECENTERING_TO_POINT],BOTTOM);
			       show_new_center(scene, u, v, 7);
		               generate(scene);
			    } else
                               XClearWindow(dpy, mainwin);
			 } else
                            XClearWindow(dpy, mainwin);
		      }
                      show_mark(scene);
		}
		break;

	     /* User has moved the mouse */
	     case MotionNotify :
                if (brief_menu) break;
                if (but_main_pressed==1 || but_main_pressed==3)
		   show_point(scene, ev.xbutton.x, ev.xbutton.y, 0);
	        if (but_main_pressed==3)
		   show_area_border(scene, ev.xbutton.x, ev.xbutton.y);
	        break;
	   }

	   if (XPending(dpy)) continue;

           /* ConfigureNotify events that have been postponed */

           if (notified & MAIN_WINDOW) {
	      int x, y;
	      unsigned int w, h;
	      if (get_window_placement(mainwin, &x, &y, &w, &h) &&
                  (w!=scene->width || h!=scene->height) ) {
	         sprintf(str, msg[RESIZING_WINDOW], w, h);
		 scene->width = w;
		 scene->height = h;
		 draw_win_string(scene, mainwin, str, BOTTOM);
                 set_radius(scene);
		 generate(scene);
                 exposed |= DATA_WINDOW;
	      }
	   }

           if (cmdwin_on && (notified & CMD_WINDOW)) {
	      int x, y;
	      unsigned int w, h;
	      if (get_window_placement(cmdwin, &x, &y, &w, &h) &&
                  (w!=cmdwin_width || h!=cmdwin_height) ) {
		 cmdwin_width = w;
		 cmdwin_height = h;
                 exposed |= CMD_WINDOW;
	      }
	   }

           if (datawin_on && (notified & DATA_WINDOW)) {
	      int x, y;
              (void) get_window_placement(datawin,
                       &x, &y, &datawin_width, &datawin_height);
              time_count = 0;
              exposed |= DATA_WINDOW;
	   }

           if (explwin_on && (notified & EXPL_WINDOW)) {
	      int x, y;
	      unsigned int w, h;
	      if (get_window_placement(explwin, &x, &y, &w, &h) &&
                  (w!=explwin_width || h!=explwin_height) ) {
		 if (h<=6*fonth[0]+48) h = 6*fonth[0]+48; 
		 explwin_width = w;
		 explwin_height = h;
		 expl_shift = 0;
                 exposed |= EXPL_WINDOW;
	      }
	   }

           if (notified & FLAG_WINDOW) {
	      int x, y;
	      unsigned int w, h;
	      if (get_window_placement(flagwin, &x, &y, &w, &h) &&
		  (w!=flagwin_width || h!=flagwin_height) ) {
		 if (big_flag_image) XDestroyImage(big_flag_image);
		 big_flag_image = NULL;
                 flagwin_width = w;
		 flagwin_height = h;
                 exposed |= FLAG_WINDOW;
	      }
	   }
           notified = 0;

           /* Expose events that have been postponed */
	   if (exposed & MAIN_WINDOW) {
              if (brief_menu>0)
		 show_brief_menu(scene);
	      show_mark(scene);
	   }
	   if (cmdwin_on && (exposed & CMD_WINDOW)) 
                draw_win_cmd(scene, 0);
	   if (datawin_on && (exposed & DATA_WINDOW)) 
                show_datawin(scene, 0);
	   if (explwin_on && (exposed & EXPL_WINDOW)) 
                show_explwin(scene, 0, 0);
	   if (flagwin_on && (exposed & FLAG_WINDOW)) 
                show_flagwin(scene, 0);
           exposed = 0;
	}

	return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1