diff options
Diffstat (limited to 'abs/not_built/core/LinHES-timezone/linhes_timezone.c')
-rw-r--r-- | abs/not_built/core/LinHES-timezone/linhes_timezone.c | 1120 |
1 files changed, 1120 insertions, 0 deletions
diff --git a/abs/not_built/core/LinHES-timezone/linhes_timezone.c b/abs/not_built/core/LinHES-timezone/linhes_timezone.c new file mode 100644 index 0000000..1cf04b2 --- /dev/null +++ b/abs/not_built/core/LinHES-timezone/linhes_timezone.c @@ -0,0 +1,1120 @@ +#include <stdio.h> +#include <math.h> +#include <stdlib.h> +#include <stdio.h> +#define _GNU_SOURCE +#include <string.h> +#include <strings.h> +#include <X11/Xlib.h> +#include <X11/Intrinsic.h> +#include <X11/IntrinsicI.h> +#include <lirc/lirc_client.h> +#include <pthread.h> + +#include "timezone_map.h" + +Display *display; +Window window; +GC gc; +int screen; +int selected_zone; +int selected_place; +Pixmap pixmap; +XColor ocean; +XColor land[8]; +XColor border; +XColor selected_border; +XColor selected_land; +XColor name_colour; +XColor location_dot; +XColor lat_lon; +XColor tux_yellow; +Dimension screen_width = 1920; +Dimension screen_height = 1080; +Dimension width = 1920; +Dimension height = 1080; +Position x = 0; +Position y = 0; +XFontStruct *font; +XPoint xpoints[1000]; +int radius; +double aspect_correction = 1; + +double target_lat; +double target_lon; + +double displayed_lat; +double displayed_lon; + +double lon_rotate[2] = {1, 0}; +double lat_rotate[2] = {1, 0}; + +double acceleration = 0.01; +char input_keys[200]; + +int guessing_timezone = FALSE; +time_t guess_timeout = 0; +int guess_failed = FALSE; +time_t guess_failed_timeout = 0; +int show_information = FALSE; +int info_displayed = FALSE; + +void select_place (int place) +{ + target_lon = atan2 (zone_data[selected_zone].place_info[place].v.y, + zone_data[selected_zone].place_info[place].v.x); + target_lat = acos (zone_data[selected_zone].place_info[place].v.z /2); + + selected_place = place; +} + +void default_zone (char *arg_zone) +{ + int found_zone = FALSE; + + for (int zone = 0; zone < NUM_ZONES; zone++) + { + for (int place = 0; place < zone_data[zone].num_places; place++) + { + if (strstr (zone_data[zone].place_info[place].zonename, + arg_zone[0] ? arg_zone : "Los_Angeles")) + { + selected_zone = zone; + select_place (place); + found_zone = TRUE; + } + } + } + + if (!found_zone) + { + default_zone (""); + } +} + +int translate_point (vect_type *v, XPoint *p) +{ + vect_type v2; + vect_type v3; + + v2.x = v->x * lon_rotate[0] + v->y * lon_rotate[1]; + v2.y = v->x * -1.0 * lon_rotate[1] + v->y * lon_rotate[0]; + v2.z = v->z; + + v3.x = v2.x * lat_rotate[0] + v2.z * lat_rotate[1]; + v3.y = v2.y * radius; + v3.z = v2.x * -1.0 * lat_rotate[1] + v2.z * lat_rotate[0]; + + + // If the point is behind the face of the globe, project it to the edge. + if (v3.x < 0) + { + p->x = width /2 + radius * sin (atan2 (v3.y,v3.z)) * aspect_correction; + p->y = height/2 - radius * cos (atan2 (v3.y,v3.z)); + } + else + { + p->x = width /2 + lrint (v3.y) * aspect_correction; + p->y = height/2 - lrint (v3.z); + } + + // Return a value indicating if it is on the front of the world. + return (v3.x >= 0); +} + +void draw_zone ( + Drawable d, + int zone, + int fill, + int selected) +{ + int boundary = 0; + int num_points = 0; + int all_on_back = 1; + + if (selected && fill) + XSetForeground (display, gc, selected_land.pixel); + + while (boundary < zone_data[zone].num_boundary_points) + { + if (zone_data[zone].boundary_points[boundary].x < -9) + { + + if ((num_points > 1) && !all_on_back) + { + if (fill) + { + if (!selected) + { + if (zone == NUM_ZONES - 1) + { + if (boundary < 380) + XSetForeground (display, gc, WhitePixel (display, screen)); + else if (boundary < 470) + XSetForeground (display, gc, tux_yellow.pixel); + else if (boundary < 1120) + XSetForeground (display, gc, BlackPixel (display, screen)); + else + XSetForeground (display, gc, WhitePixel (display, screen)); + } + else + { + XSetForeground (display, gc, + land[boundary % XtNumber (land)].pixel); + } + } + + XFillPolygon ( + display, d, gc, + xpoints, + num_points, Complex, CoordModeOrigin); + } + else + XDrawLines ( + display, d, gc, + xpoints, + num_points, CoordModeOrigin); + } + + boundary++; + num_points = 0; + all_on_back = 1; + } + else + { + if (translate_point (&zone_data[zone].boundary_points[boundary], + &xpoints[num_points])) + all_on_back = 0; + + num_points++; + boundary++; + } + } +} + +void draw_string (int x, int y, const char*s, unsigned long colour) +{ + XSetForeground (display, gc, BlackPixel (display, screen)); + for (int x_pos = x - 3; x_pos <= x + 3; x_pos++) + for (int y_pos = y - 3; y_pos <= y + 3; y_pos++) + XDrawString (display, pixmap, gc, x_pos, y_pos, s, strlen (s)); + + XSetForeground (display, gc, colour); + XDrawString (display, pixmap, gc, x, y, s, strlen (s)); +} + +void draw_point (XPoint p, char *s) +{ + int text_width; + + int dot_size = ceil (sqrt (height) / 6.0); + + if (s) + dot_size += 2; + + XSetForeground (display, gc, + s ? WhitePixel (display, screen) : location_dot.pixel); + XFillRectangle (display, pixmap, gc, + p.x - dot_size / 2, p.y - dot_size / 2, dot_size, dot_size); + + XSetForeground (display, gc, BlackPixel (display, screen)); + XSetLineAttributes (display, gc, 2, LineSolid, CapRound, JoinRound); + XDrawRectangle (display, pixmap, gc, + p.x - dot_size / 2, p.y - dot_size / 2, dot_size, dot_size); + + if (s) + { + int text_x; + int text_y; + + text_width = XTextWidth (font, s, strlen (s)); + + if (p.x + text_width + 30 > width) + { + text_x = p.x - text_width - 6; + text_y = p.y + 10; + } + else + { + text_x = p.x + 6; + text_y = p.y + 10; + } + + draw_string (text_x, text_y, s, name_colour.pixel); + } +} + +void redraw_map () +{ + XPoint selected_point; + char selected_name[100]; + + lon_rotate[0] = cos (displayed_lon); + lon_rotate[1] = sin (displayed_lon); + + lat_rotate[1] = cos (displayed_lat) * radius; + lat_rotate[0] = sin (displayed_lat) * radius; + + /* Draw the map into the pixmap. */ + + XSetForeground (display, gc, BlackPixel (display, screen)); + XFillRectangle (display, pixmap, gc, 0, 0, width, height); + + XSetForeground (display, gc, ocean.pixel); + XFillArc (display, pixmap, gc, + width / 2 - radius * aspect_correction, height / 2 - radius, + radius * 2 * aspect_correction, radius * 2, 0, 360 * 64); + + XSetForeground (display, gc, lat_lon.pixel); + XSetLineAttributes (display, gc, 2, LineSolid, CapRound, JoinRound); + + for (int lon = 0; lon < 24; lon++) + for (int lat = 0; lat < 12 * 3; lat++) + { + XPoint line[2]; + vect_type v; + v.x = cos (lon * 15 * M_PI / 180) * cos ((90 - lat * 5) * M_PI / 180); + v.y = sin (lon * 15 * M_PI / 180) * cos ((90 - lat * 5) * M_PI / 180); + v.z = sin ((90 - lat * 5) / 180.0 * M_PI); + line[0] = line[1]; + if (translate_point (&v, &line[1]) && (lat > 0)) + XDrawLines (display, pixmap, gc, line, 2, CoordModeOrigin); + } + + for (int lat = 0; lat < 12; lat++) + for (int lon = 0; lon <= 24 * 3; lon++) + { + XPoint line[2]; + vect_type v; + v.x = cos (lon * 5 * M_PI / 180) * cos ((90 - lat * 15) * M_PI / 180); + v.y = sin (lon * 5 * M_PI / 180) * cos ((90 - lat * 15) * M_PI / 180); + v.z = sin ((90 - lat * 15) / 180.0 * M_PI); + line[0] = line[1]; + if (translate_point (&v, &line[1]) && (lon > 0)) + XDrawLines (display, pixmap, gc, line, 2, CoordModeOrigin); + } + + for (int zone = 0; zone < NUM_ZONES; zone++) + draw_zone (pixmap, zone, 1, 0); + + XSetLineAttributes (display, gc, 2, LineSolid, CapRound, JoinRound); + XSetForeground (display, gc, border.pixel); + for (int zone = 0; zone < NUM_ZONES - 1; zone++) + draw_zone (pixmap, zone, 0, 0); + + if (show_information) + { + info_displayed = TRUE; + char *s[4] = {"Left/Right: Change Offset", + "Up/Down: Change Location", + "Enter: Select Location", + "Esc: Abort"}; + int num = XtNumber(s); + for (int i = 0; i < num; i++) + { + int text_width = XTextWidth (font, s[i], strlen (s[i])); + draw_string (width/2 - text_width/2, + height/2 + (-2 + i) * (font->ascent + font->descent), + s[i], name_colour.pixel); + } + } + else if (guessing_timezone || (info_displayed = FALSE)) + { + char *s = "Guessing Timezone"; + int text_width = XTextWidth (font, s, strlen (s)); + draw_string (width/2 - text_width/2, height/2, s, name_colour.pixel); + } + else if (guess_failed) + { + char *s = "Unable to Guess Timezone"; + char *s2 = "Please Select Timezone Manually"; + int text_width = XTextWidth (font, s, strlen (s)); + draw_string (width/2 - text_width/2, height/2, s, name_colour.pixel); + text_width = XTextWidth (font, s2, strlen (s2)); + draw_string (width/2 - text_width/2, + height/2 + font->ascent + font->descent, + s2, name_colour.pixel); + } + else + { + draw_zone (pixmap, selected_zone, 1, 1); + XSetForeground (display, gc, selected_border.pixel); + draw_zone (pixmap, selected_zone, 0, 1); + + for (int place = 0; place < zone_data[selected_zone].num_places; place++) + { + XPoint point; + + translate_point (&zone_data[selected_zone].place_info[place].v, &point); + + draw_point (point, NULL); + + if ((place == selected_place) && (!guessing_timezone)) + { + char *underscore; + selected_point = point; + strcpy (selected_name, strchr (zone_data[selected_zone].place_info[place].zonename, '/') + 1); + while (underscore = strchr (selected_name, '_')) + underscore[0] = ' '; + } + } + + draw_point (selected_point, selected_name); + + { + char zone_offset[100]; + sprintf (zone_offset, "UTC%s", zone_data[selected_zone].offset); + draw_string ( + ((width * 0.95 - XTextWidth (font, "UTC+88", strlen ("UTC+88"))) + + ((width / 2) + radius / sqrt (2))) / 2, + ((lrint (height * 0.05) + font->ascent) + + (height / 2 - radius / sqrt (2))) / 2, + zone_offset, name_colour.pixel); + } + } + + if (!guessing_timezone && !guess_failed) + { + const char *title = "Select Your Time Zone"; + const char *help = "Help = i"; + + draw_string (width / 2 - XTextWidth (font, title, strlen (title)) / 2, + ((lrint (height * 0.05) + font->ascent) + + (height / 2 - radius / sqrt (2))) / 2, + title, WhitePixel (display,screen)); + + draw_string (width * 0.05, height * 0.95 - font->descent - font->ascent, + help, name_colour.pixel); + } + + XCopyArea (display, pixmap, window, gc, 0, 0, width, height, 0, 0); +} + +int nearest_z (double near_z) +{ + double min_delta = + fabs (near_z - zone_data[selected_zone].place_info[0].v.z); + int min_delta_place = 0; + + for (int place = 1; place < zone_data[selected_zone].num_places; place++) + { + double delta = + fabs (near_z - zone_data[selected_zone].place_info[place].v.z); + + if (delta < min_delta) + { + min_delta_place = place; + min_delta = delta; + } + } + + return min_delta_place; +} + +void handle_key (char key) +{ + double selected_z; + + selected_z = zone_data[selected_zone].place_info[selected_place].v.z; + + if (show_information) + { + show_information = FALSE; + return; + } + + switch (key) + { + case 'U': + select_place ((selected_place + + zone_data[selected_zone].num_places - 1) % + zone_data[selected_zone].num_places); + break; + + case 'D': + select_place ((selected_place + 1) % + zone_data[selected_zone].num_places); + break; + + case 'L': + selected_zone = (selected_zone + NUM_ZONES - 1) % NUM_ZONES; + select_place (nearest_z (selected_z)); + break; + + case 'R': + selected_zone = (selected_zone + 1) % NUM_ZONES; + select_place (nearest_z (selected_z)); + break; + + case 'I': + show_information = !show_information; + break; + + case 'X': + printf ("%s\n", zone_data[selected_zone].place_info[selected_place].zonename); + exit (0); + + case 'E': + exit(1); + } +} + +void handle_event (XEvent *xevent) +{ + switch (xevent->type) + { + case Expose: + redraw_map (); + break; + + case KeyPress: + switch (XLookupKeysym (&xevent->xkey, 0)) + { + case XK_Up: + handle_key ('U'); + break; + + case XK_Down: + handle_key ('D'); + break; + + case XK_Left: + handle_key ('L'); + break; + + case XK_Right: + handle_key ('R'); + break; + + case XK_Return: + handle_key ('X'); + break; + + case XK_Escape: + handle_key ('E'); + break; + + case XK_I: + case XK_i: + handle_key ('I'); + break; + } + + break; + } +} + +Bool event_predicate (Display *display, XEvent *xevent, XPointer unused) +{ + return (xevent->type == KeyPress) || (xevent->type == Expose); +} + +void next_view () +{ + static double step_size = 0.01; + double error_total; + double lat_error = target_lat - displayed_lat; + double lon_error = target_lon - displayed_lon; + + if (guessing_timezone) + { + displayed_lon += 1 / 180.0 * M_PI; + } + else + { + lat_error = atan2 (sin (lat_error), cos( lat_error)); + lon_error = atan2 (sin (lon_error), cos (lon_error)); + + error_total = sqrt (lat_error * lat_error + lon_error * lon_error); + + if (error_total < acceleration) + { + displayed_lat = target_lat; + displayed_lon = target_lon; + } + else + { + if (error_total > (step_size + acceleration) * + (step_size + acceleration) / acceleration / 2) + step_size += acceleration; + else + step_size -= acceleration; + + if (step_size < acceleration) + step_size = acceleration; + + displayed_lat += step_size * (lat_error / error_total); + displayed_lon += step_size * (lon_error / error_total); + } + } +} + +void *lirc_thread (void *unused) +{ + int lirc_fd; + struct lirc_config *lirc_config; + char *lirc_code; + + if ((lirc_fd = lirc_init ("mythtv",0)) == -1) + fprintf (stderr,"Error initialising lirc\n"); + else + { + int readc_status; + + if (readc_status = lirc_readconfig (NULL, &lirc_config, NULL)) + { + fprintf (stderr,"Error loading lirc config file %d %p\n", readc_status, lirc_config); + } + } + + while ((lirc_nextcode (&lirc_code) == 0) && (lirc_code != NULL)) + { + char *action; + + while ((lirc_code2char (lirc_config, lirc_code, &action) == 0) && + (action != NULL)) + { + if (strcasecmp (action, "down") == 0) + strcat (input_keys, "D"); + + if (strcasecmp (action, "up") == 0) + strcat (input_keys, "U"); + + if (strcasecmp (action, "left") == 0) + strcat (input_keys, "L"); + + if (strcasecmp (action, "right") == 0) + strcat (input_keys, "R"); + + if (strcasecmp (action, "return") == 0) + strcat (input_keys, "X"); + + if (strcasecmp (action, "Esc") == 0) + strcat (input_keys, "E"); + } + + free (lirc_code); + lirc_code = NULL; + } +} + +void get_value (FILE *input, char*output, int out_len) +{ + const char *value_pattern = "value=\""; + char *value; + + output[0] = 0; + fgets (output, out_len, input); + + if (value = strcasestr (output, value_pattern)) + { + memmove (output, value + strlen (value_pattern), + strlen (value + strlen (value_pattern)) + 1); + } + + if (value = strchr (output, '"')) + value[0] = 0; +} + +void *timezone_guess (void *unused) +{ + const double invalid = 99999; + FILE *guess_data; + char line_in[1000]; + double guess_latitude = invalid; + double guess_longitude = invalid; + char guess_zone[1000] = {0}; + char *timezone_info_command; + + if (getenv ("FAKE_GEOBYTES")) + { + timezone_info_command = + "sleep 2 ; " + "echo Latitude ; " + "echo \" <td value=\\\"-34.993\\\"\" ;" + "echo Longitude ; " + "echo \" <td value=\\\"138.6\\\"\" ;" + "echo TimeZone ; " + "echo \" <td value=\\\"+09:30\\\"\""; + } + else + { + timezone_info_command = + "wget http://www.geobytes.com/IpLocator.htm -O - 2> /dev/null |" + "grep \"<td \" |" + "grep -i -E -A1 \"Latitude|Longitude|TimeZone\" | grep -v \"^--$\""; + } + + guess_data = popen (timezone_info_command, "r"); + + if (!guess_data) + { + fprintf (stderr, "error parsing web page for timezone guess\n"); + if (guessing_timezone) + { + guessing_timezone = FALSE; + guess_failed = TRUE; + guess_failed_timeout = time (NULL) + 3; + } + return NULL; + } + + while (fgets (line_in, sizeof (line_in), guess_data)) + { + // Look for the entries in the guess data and then the next line + // will hold the value. + + if (strcasestr (line_in, "latitude")) + { + get_value (guess_data, line_in, sizeof (line_in)); + sscanf (line_in, "%lf", &guess_latitude); + } + else if (strcasestr (line_in, "longitude")) + { + get_value (guess_data, line_in, sizeof (line_in)); + sscanf (line_in, "%lf", &guess_longitude); + } + else if (strcasestr (line_in, "timezone")) + { + get_value (guess_data, line_in, sizeof (line_in)); + + // The geobytes timezone data is of the form "+09:30" whereas the + // map timezone data is of the form "+6" or "+9.5". Convert + // to the map timezone data format so we can find the timezone. + + if (strcmp (&line_in[3], ":30") == 0) + sprintf (&line_in[3], ".5"); + else + line_in[3] = 0; + + if (line_in[1] == '0') + memmove (&line_in[1], &line_in[2], strlen (&line_in[2]) + 1); + + strncpy (guess_zone, line_in, sizeof (guess_zone)); + } + } + + pclose (guess_data); + + if ((guess_latitude != invalid) && + (guess_longitude != invalid) && + guess_zone[0] != 0) + { + int zone; + + fprintf (stderr, "guessed lat lon %f %f %s\n", + guess_latitude, guess_longitude, guess_zone); + + // Look for the guessed zone in the zone_data structure. + for (zone = 0; zone < NUM_ZONES; zone++) + { + if (strcmp (guess_zone, zone_data[zone].offset) == 0) + break; + } + + if (zone == NUM_ZONES) + { + fprintf (stderr, "couldnt find zone %s\n", guess_zone); + if (guessing_timezone) + { + guessing_timezone = FALSE; + guess_failed = TRUE; + guess_failed_timeout = time (NULL) + 3; + } + } + else + { + double x,y,z; + double min_dist_squared; + int closest_place; + + // Look for the location in the zone nearest to the guess lat/lon. + + // Convert the guessed lat/lon to x,y,z. + + guess_latitude *= M_PI / 180.0; + guess_longitude *= M_PI / 180.0; + + x = cos (guess_longitude) * cos (guess_latitude); + y = sin (guess_longitude) * cos (guess_latitude); + z = sin (guess_latitude); + + min_dist_squared = + pow (x - zone_data[zone].place_info[0].v.x, 2) + + pow (y - zone_data[zone].place_info[0].v.y, 2) + + pow (z - zone_data[zone].place_info[0].v.z, 2); + closest_place = 0; + + for (int place = 1; place < zone_data[zone].num_places; place++) + { + double dist_squared; + + dist_squared = + pow (x - zone_data[zone].place_info[place].v.x, 2) + + pow (y - zone_data[zone].place_info[place].v.y, 2) + + pow (z - zone_data[zone].place_info[place].v.z, 2); + + if (dist_squared < min_dist_squared) + { + closest_place = place; + min_dist_squared = dist_squared; + } + } + + fprintf (stderr, "Guess=%s %s\n", + zone_data[zone].place_info[closest_place].zonename, + zone_data[zone].offset); + + selected_zone = zone; + select_place (closest_place); + } + } + else + { + if (guessing_timezone) + { + guessing_timezone = FALSE; + guess_failed = TRUE; + guess_failed_timeout = time (NULL) + 3; + } + } + + guessing_timezone = FALSE; + return NULL; +} + +void remove_titlebar_and_borders () +{ + XClassHint* classHint; + char* appname; + appname="look fo rme"; + XStoreName (display, window, appname); + + /* Set the name and class hints for the window manager to use. */ + + classHint = XAllocClassHint (); + if (classHint) + { + classHint->res_name = appname; + classHint->res_class = "MoonRoot"; + } + + XSetClassHint (display, window, classHint); + XFree (classHint); + + typedef struct + { + CARD32 flags; + CARD32 functions; + CARD32 decorations; + INT32 input_mode; + CARD32 status; + } MotifWmHints, MwmHints; + + #define MWM_HINTS_DECORATIONS (1L << 1) + + + Atom XA_MOTIF_WM_HINTS = XInternAtom (display, "_MOTIF_WM_HINTS", False); + MotifWmHints mwm_hints; + + mwm_hints.flags = MWM_HINTS_DECORATIONS; + mwm_hints.decorations = 0; + + XChangeProperty ( + display, window, + XA_MOTIF_WM_HINTS, XA_MOTIF_WM_HINTS, + 32, PropModeReplace, + (char *) &mwm_hints, 5); +} + +void set_window_position (int x, int y) +{ + XSizeHints hints; + + hints.flags = USPosition | PPosition; + hints.x = x; + hints.y = y; + + XSetWMNormalHints(display, window, &hints); +} + +int main (int argc, char *argv[]) +{ + XEvent xevent; + Colormap cmap; + XColor color, colorrgb; + pthread_t tid; + int opt; + int arg_width = -1; + int arg_height = -1; + char arg_zone[100] = {0}; + + if (getenv ("ACCEL")) + acceleration = atof (getenv ("ACCEL")); + + while ((opt = getopt (argc, argv, "z:w:h:a:")) != -1) + { + switch (opt) + { + case 'z': + strncpy (arg_zone, optarg, sizeof (arg_zone) - 1); + + if (strcasecmp (arg_zone, "guess") == 0) + { + guessing_timezone = TRUE; + arg_zone[0]=0; + } + + break; + + case 'w': + arg_width = atoi (optarg); + break; + + case 'h': + arg_height = atoi (optarg); + break; + + case 'a': + acceleration = atof (optarg); + break; + + case '?': + printf ("usage: %s [-a accelleration] [-z timezone] " + "[-w width] [-h height]\n" + "e.g. linhes_timezone -w 1920 -h 1090 -z Australia/Adelaide\n" + "specify a timezone of 'guess' to determine the initial " + "timezone from\n" + "your ip address using geocache.\n", + argv[0]); + exit (0); + break; + } + } + + pthread_create (&tid, NULL, lirc_thread, NULL); + + /* Connect to the X server. */ + + display = XOpenDisplay (""); + + if (display == NULL) + { + fprintf (stderr, "cannot connect to server\n"); + exit (EXIT_FAILURE); + } + + /* Get default screen. */ + + screen = DefaultScreen (display); + screen_width = XWidthOfScreen (DefaultScreenOfDisplay (display)); + screen_height = XHeightOfScreen (DefaultScreenOfDisplay (display)); + + if ((arg_width <= 0) && (arg_height > 0)) + arg_width == arg_height; + + if (arg_width > 0) + { + width = arg_width; + + if (arg_height <= 0) + height = width; + else + height = arg_height; + + x = (screen_width - width) / 2; + y = (screen_height - height) / 2; + } + else + { + width = screen_width; + height = screen_height; + x = 0; + y = 0; + } + + if (width < height) + radius = width; + else + radius = height; + + radius = 0.96 * radius / 2; + + if ((screen_height == 0) || + (XWidthMMOfScreen (DefaultScreenOfDisplay (display)) == 0)) + aspect_correction = 1; + else + aspect_correction = + sqrt (screen_width * + XHeightMMOfScreen (DefaultScreenOfDisplay (display)) * 1.0 / + screen_height / + XWidthMMOfScreen (DefaultScreenOfDisplay (display))); + + // Protect against very wierd aspect corrections from bogus + // screen dimensions. + if ((aspect_correction < 0.5) || (aspect_correction > 2)) + aspect_correction = 1; + + window = XCreateSimpleWindow (display, + DefaultRootWindow(display), x, y, width, height, 0, + land[0].pixel, ocean.pixel); + + remove_titlebar_and_borders (); + set_window_position (x, y); + + if (!window) + { + fprintf (stderr, "cannot open window\n"); + exit (EXIT_FAILURE); + } + + /* set graphics context of rectangle to red */ + gc= XCreateGC (display, window, 0, 0); + cmap = DefaultColormap (display, screen); + + // Load the font. + + font = XLoadQueryFont (display, (width > 800) ? + "-*-lucida-bold-r-*-*-34-*-*-*-*-*-*-*" : + "-*-lucida-bold-r-*-*-20-*-*-*-*-*-*-*"); + if (!font) + fprintf (stderr,"error loading font\n"); + + XSetFont (display, gc, font->fid); + + pixmap = + XCreatePixmap (display, window, width, height, + DefaultDepth (display, DefaultScreen (display))); + + ocean.flags = DoRed | DoGreen | DoBlue; + ocean.red = 40 * 256; + ocean.green = 41 * 256; + ocean.blue = 72 * 256; + if (XAllocColor (display, cmap, &ocean) == 0) + printf ("Cant allocate color\n"); + + lat_lon.flags = DoRed | DoGreen | DoBlue; + lat_lon.red = 0 * 256; + lat_lon.green = 0 * 256; + lat_lon.blue = 86 * 256; + if (XAllocColor (display, cmap, &lat_lon) == 0) + printf ("Cant allocate color\n"); + + tux_yellow.flags = DoRed | DoGreen | DoBlue; + tux_yellow.red = 248 * 256; + tux_yellow.green = 191 * 256; + tux_yellow.blue = 17 * 256; + if (XAllocColor (display, cmap, &tux_yellow) == 0) + printf ("Cant allocate color\n"); + + for (int land_col = 0; land_col < XtNumber (land); land_col++) + { + land[land_col].flags = DoRed | DoGreen | DoBlue; + land[land_col].red = (120 + 9 * land_col) * 256; + land[land_col].green = (40 + 3 * land_col) * 256; + land[land_col].blue = 0 * 256; + if (XAllocColor (display, cmap, &land[land_col]) == 0) + printf ("Cant allocate color\n"); + } + + selected_land.flags = DoRed | DoGreen | DoBlue; + selected_land.red = 3 * 256; + selected_land.green = 40 * 256; + selected_land.blue = 13 * 256; + if (XAllocColor (display, cmap, &selected_land) == 0) + printf ("Cant allocate color\n"); + + border.flags = DoRed | DoGreen | DoBlue; + border.red = 0 * 256; + border.green = 0 * 256; + border.blue = 0 * 256; + if (XAllocColor (display, cmap, &border) == 0) + printf ("Cant allocate color\n"); + + selected_border.flags = DoRed | DoGreen | DoBlue; + selected_border.red = 80 * 256; + selected_border.green = 255 * 256; + selected_border.blue = 80 * 256; + if (XAllocColor (display, cmap, &selected_border) == 0) + printf ("Cant allocate color\n"); + + name_colour.flags = DoRed | DoGreen | DoBlue; + name_colour.red = 255 * 256; + name_colour.green = 255 * 256; + name_colour.blue = 0 * 256; + if (XAllocColor (display, cmap, &name_colour) == 0) + printf ("Cant allocate color\n"); + + location_dot.flags = DoRed | DoGreen | DoBlue; + location_dot.red = 255 * 256; + location_dot.green = 55 * 256; + location_dot.blue = 200 * 256; + if (XAllocColor (display, cmap, &location_dot) == 0) + printf ("Cant allocate color\n"); + + // Find the selected timezone (or LA if a timezone was not selected) and + // make that the selected zone and place. + + default_zone (arg_zone); + + if (guessing_timezone) + { + pthread_create (&tid, NULL, timezone_guess, NULL); + guess_timeout = time (NULL) + 10; + displayed_lat = M_PI/2; + displayed_lon = 0; + } + else + { + displayed_lat = target_lat; + displayed_lon = target_lon; + } + + /* ask for exposure event and keyboard events */ + XSelectInput(display, window, KeymapNotify | ExposureMask); + + /* pop this window up on the screen */ + XMapRaised (display, window); + + redraw_map (); + + while (1) + { + if (guessing_timezone && (time (NULL) > guess_timeout)) + { + guessing_timezone = FALSE; + guess_failed_timeout = time (NULL) + 3; + guess_failed = TRUE; + } + + if ((displayed_lat != target_lat) || (displayed_lon != target_lon) || + guessing_timezone || guess_failed || + (info_displayed ^ show_information)) + { + if (guess_failed && (time (NULL) > guess_failed_timeout)) + { + guess_failed = FALSE; + } + + next_view (); + redraw_map (); + } + else + { + usleep (1000); + } + + while (strlen (input_keys)) + { + handle_key (input_keys[0]); + memmove (&input_keys[0], &input_keys[1], strlen (input_keys)); + } + + // If there is an event pending, go on to process it. + + if (XCheckIfEvent (display, &xevent, event_predicate, NULL)) + handle_event (&xevent); + } + + return 0; +} |