/* Portions of this software.... */ /*Copyright George Peter Staplin 2003*/ /*You may use/copy/modify/distribute this software for any purpose *provided that I am given credit and you don't sue me for any bugs. */ /*Please contact me using GeorgePS@XMission.com if you like this, or *have questions. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "map_db.h" #include "socket.h" #include "nmea.h" #ifndef u_char #define u_char unsigned char #endif #include "module_jpeg.h" #include "module_png.h" Window mainWin; GC copyGC; int WIN_X = 400; int WIN_Y = 400; int AutoRecenter = 0; /* Arrays of style info */ char *style_name[16]; GC style_gc[16]; int style_count = 0; int get_byte_order (void) { union { char c[sizeof(short)]; short s; } order; order.s = 1; if ((1 == order.c[0])) { return LSBFirst; } else { return MSBFirst; } } XImage *create_image_from_buffer (Display *dis, int screen, u_char *buf, int buf_width, int buf_height, int zoom) { int depth; XImage *img = NULL; Visual *vis; double rRatio; double gRatio; double bRatio; int outIndex = 0; int i; int width = buf_width/zoom; int height = buf_height/zoom; int numBufBytes = (3 * (buf_width * buf_height)); depth = DefaultDepth (dis, screen); vis = DefaultVisual (dis, screen); rRatio = vis->red_mask / 255.0; gRatio = vis->green_mask / 255.0; bRatio = vis->blue_mask / 255.0; if (depth >= 24) { size_t numNewBufBytes = (4 * (width * height)); u_int32_t *newBuf = malloc (numNewBufBytes); for (i = 0; i < numBufBytes;) { unsigned int r, g, b; r = (buf[i++] * rRatio); g = (buf[i++] * gRatio); b = (buf[i++] * bRatio); r &= vis->red_mask; g &= vis->green_mask; b &= vis->blue_mask; newBuf[outIndex] = r | g | b; ++outIndex; } img = XCreateImage (dis, CopyFromParent, depth, ZPixmap, 0, (char *) newBuf, width, height, 32, 0 ); } else if (depth >= 15) { size_t numNewBufBytes = (2 * (width * height)); u_int16_t *newBuf = malloc (numNewBufBytes); for (i = 0; i < numBufBytes;) { unsigned int r, g, b; r = (buf[i++] * rRatio); g = (buf[i++] * gRatio); b = (buf[i++] * bRatio); r &= vis->red_mask; g &= vis->green_mask; b &= vis->blue_mask; newBuf[outIndex] = r | g | b; ++outIndex; } img = XCreateImage (dis, CopyFromParent, depth, ZPixmap, 0, (char *) newBuf, width, height, 16, 0 ); } else { fprintf (stderr, "This program does not support displays with a depth less than 15."); return NULL; } XInitImage (img); /*Set the client's byte order, so that XPutImage knows what to do with the data.*/ /*The default in a new X image is the server's format, which may not be what we want.*/ if ((LSBFirst == get_byte_order ())) { img->byte_order = LSBFirst; } else { img->byte_order = MSBFirst; } /*The bitmap_bit_order doesn't matter with ZPixmap images.*/ img->bitmap_bit_order = MSBFirst; return img; } Window create_window (Display *dis, int screen, int x, int y, int width, int height) { Window win; unsigned long windowMask; XSetWindowAttributes winAttrib; XTextProperty windowName; windowName.value = (unsigned char *) "mMDS"; windowName.encoding = XA_STRING; windowName.format = 8; windowName.nitems = strlen((char *) windowName.value); /** * Tell X to ask the window manager to set the window title. (X * itself doesn't provide window title functionality.) */ windowMask = CWBackPixel | CWBorderPixel; winAttrib.border_pixel = BlackPixel (dis, screen); winAttrib.background_pixel = BlackPixel (dis, screen); winAttrib.override_redirect = 0; win = XCreateWindow (dis, DefaultRootWindow (dis), x, y, width, height, 0, DefaultDepth (dis, screen), InputOutput, CopyFromParent, windowMask, &winAttrib ); XSetWMName(dis, win, &windowName); return win; } int imageWidth; int imageHeight; int screen; Display *dis; XImage *img; int src_x, src_y; int RedrawCount = 0; char *RedrawList[1024]; void mMDS_LoadMap(char *name) { u_char *buf = NULL; char *ext; char *c; int zoom = 1; for (c=name; *c; c++); for (; *c != '.'; c--); ext = c+1; if (strcmp(ext,"jpg") == 0 ) buf = decode_jpeg (map_db_name(name), &imageWidth, &imageHeight); else if ( strcmp(ext,"png") == 0 ) buf = decode_png (map_db_name(name), &imageWidth, &imageHeight); fprintf(stderr,"Height = %d, Width = %d\n",imageHeight,imageWidth); if (buf) { img = create_image_from_buffer (dis, screen, buf, imageWidth, imageHeight, zoom); imageWidth /= zoom; imageHeight /= zoom; free (buf); } src_x = 0; src_y = 0; } void mds_draw(char*); void redraw_exposed_area(int x, int y, int width, int height) { if (img) { XPutImage (dis, mainWin, copyGC, img, src_x+x, src_y+y, x, y, width, height); XFlush (dis); } } void mMDS_Refresh() { int i; char *c = NULL; c = map_db_check(src_x + WIN_X/2,src_y + WIN_Y/2); if (c != NULL && AutoRecenter == 1) { double center_latitude,center_longitude; printf("New map = %s\n",c); center_latitude = map_db_y2lat(src_y + WIN_Y/2); center_longitude = map_db_x2long(src_x + WIN_X/2); mMDS_LoadMap(c); src_x = map_db_long2x(center_longitude) - WIN_X/2; src_y = map_db_lat2y(center_latitude) - WIN_Y/2; } if ( (src_x + WIN_X ) > imageWidth ) src_x = imageWidth - WIN_X; if ( (src_y + WIN_Y ) > imageHeight ) src_y = imageHeight - WIN_Y; if ( src_x < 0 ) src_x = 0; if ( src_y < 0 ) src_y = 0; redraw_exposed_area(0,0,WIN_X,WIN_Y); for (i=0;i= 0 && a <= 90) b = 90 - a; if ( a > 90 && a <= 270) b = a - 90; if ( a > 270 ) b = a - 450; return b; } void mds_draw(char *c) { double latitude, longitude; int x,y,i,s; char *t,*b; GC gc = copyGC; b = (char *) malloc (strlen(c) + 1); strcpy(b,c); t = strtok(b,","); for (s=0;s<16;s++) if (style_name[s] != NULL && strcmp(t,style_name[s]) == 0) { gc = style_gc[s]; break; } t = strtok(NULL,","); if (strcmp(t,"Pixmap") == 0 ) { Window w; int x_ret, y_ret; unsigned int width_ret, height_ret, border_ret, depth_ret; t = strtok(NULL,","); for (i=0; i<16; i++) if (strcmp(t,pixmap_name[i]) == 0 ) { break; } t = strtok(NULL,","); latitude = nmea_to_double(t); t = strtok(NULL,","); if (strcmp(t,"S") == 0 ) latitude = -latitude; t = strtok(NULL,","); longitude = nmea_to_double(t); t = strtok(NULL,","); if (strcmp(t,"W") == 0 ) longitude = -longitude; y = map_db_lat2y(latitude) - src_y; x = map_db_long2x(longitude) - src_x; XGetGeometry(dis,pixmap_data[i],&w,&x_ret,&y_ret,&width_ret,&height_ret,&border_ret,&depth_ret); XSetClipMask(dis,gc,pixmap_mask[i]); XSetClipOrigin(dis,gc,x-(width_ret/2),y-(height_ret/2)); XCopyArea (dis, pixmap_data[i], mainWin, gc, 0, 0, width_ret, height_ret, x-(width_ret/2), y-(height_ret/2)); XSetClipMask(dis,gc,None); } else if (strcmp(t,"Point") == 0) { t = strtok(NULL,","); latitude = nmea_to_double(t); t = strtok(NULL,","); if (strcmp(t,"S") == 0 ) latitude = -latitude; t = strtok(NULL,","); longitude = nmea_to_double(t); t = strtok(NULL,","); if (strcmp(t,"W") == 0 ) longitude = -longitude; y = map_db_lat2y(latitude) - src_y; x = map_db_long2x(longitude) - src_x; XDrawPoint(dis,mainWin,gc,x,y); } else if (strcmp(t,"Line") == 0) { int x2, y2; t = strtok(NULL,","); latitude = nmea_to_double(t); t = strtok(NULL,","); if (strcmp(t,"S") == 0 ) latitude = -latitude; t = strtok(NULL,","); longitude = nmea_to_double(t); t = strtok(NULL,","); if (strcmp(t,"W") == 0 ) longitude = -longitude; y = map_db_lat2y(latitude) - src_y; x = map_db_long2x(longitude) - src_x; t = strtok(NULL,","); latitude = nmea_to_double(t); t = strtok(NULL,","); if (strcmp(t,"S") == 0 ) latitude = -latitude; t = strtok(NULL,","); longitude = nmea_to_double(t); t = strtok(NULL,","); if (strcmp(t,"W") == 0 ) longitude = -longitude; y2 = map_db_lat2y(latitude) - src_y; x2 = map_db_long2x(longitude) - src_x; XDrawLine(dis,mainWin,gc,x,y,x2,y2); } else if (strcmp(t,"Arc") == 0) { int height,width; int start_angle,extent_angle; t = strtok(NULL,","); height=atoi(t); t = strtok(NULL,","); width=atoi(t); t = strtok(NULL,","); start_angle=bearing2angle(t); t = strtok(NULL,","); extent_angle=atoi(t); t = strtok(NULL,","); if (strcmp(t,"CW") == 0) extent_angle = -extent_angle; t = strtok(NULL,","); latitude = nmea_to_double(t); t = strtok(NULL,","); if (strcmp(t,"S") == 0 ) latitude = -latitude; t = strtok(NULL,","); longitude = nmea_to_double(t); t = strtok(NULL,","); if (strcmp(t,"W") == 0 ) longitude = -longitude; y = map_db_lat2y(latitude) - src_y - (width / 2); x = map_db_long2x(longitude) - src_x - (height / 2); printf("start=%d,extent=%d\n",start_angle,extent_angle); XDrawArc(dis,mainWin,gc,x,y,width,height,start_angle*64,extent_angle*64); } else if (strcmp(t,"String") == 0) { char *corner,*text,*t1; XCharStruct text_bounds; int d; XGCValues values; int ox,oy; XFontStruct *font; corner = strtok(NULL,","); t1 = strtok(NULL,","); latitude = nmea_to_double(t1); t1 = strtok(NULL,","); if (strcmp(t1,"S") == 0 ) latitude = -latitude; t1 = strtok(NULL,","); longitude = nmea_to_double(t1); t1 = strtok(NULL,","); if (strcmp(t1,"W") == 0 ) longitude = -longitude; y = map_db_lat2y(latitude) - src_y; x = map_db_long2x(longitude) - src_x; text = strtok(NULL,""); XGetGCValues(dis,gc,GCFont,&values); font = XQueryFont(dis,values.font); XTextExtents(font, text, strlen(text), &d, &d, &d, &text_bounds); if (strcmp(corner,"UL") == 0 ) { ox = oy = 0; } else if (strcmp(corner,"UR") == 0 ) { oy = 0; ox = -text_bounds.width; } else if (strcmp(corner,"LL") == 0 ) { oy = -(text_bounds.ascent+text_bounds.descent); ox = 0; } else if (strcmp(corner,"LR") == 0 ) { oy = -(text_bounds.ascent+text_bounds.descent); ox = -text_bounds.width; } XDrawString(dis,mainWin,gc,x+ox,y+oy,text,strlen(text)); } else if (strcmp(t,"ImageString") == 0) { char *corner,*text,*t1; XCharStruct text_bounds; int d; XGCValues values; int ox,oy; XFontStruct *font; corner = strtok(NULL,","); t1 = strtok(NULL,","); latitude = nmea_to_double(t1); t1 = strtok(NULL,","); if (strcmp(t1,"S") == 0 ) latitude = -latitude; t1 = strtok(NULL,","); longitude = nmea_to_double(t1); t1 = strtok(NULL,","); if (strcmp(t1,"W") == 0 ) longitude = -longitude; y = map_db_lat2y(latitude) - src_y; x = map_db_long2x(longitude) - src_x; text = strtok(NULL,""); XGetGCValues(dis,gc,GCFont,&values); font = XQueryFont(dis,values.font); XTextExtents(font, text, strlen(text), &d, &d, &d, &text_bounds); if (strcmp(corner,"UL") == 0 ) { oy = text_bounds.ascent; ox = 0; } else if (strcmp(corner,"UR") == 0 ) { oy = text_bounds.ascent; ox = -text_bounds.width; } else if (strcmp(corner,"LL") == 0 ) { oy = -text_bounds.descent; ox = 0; } else if (strcmp(corner,"LR") == 0 ) { oy = -text_bounds.descent; ox = -text_bounds.width; } XDrawImageString(dis,mainWin,gc,x+ox,y+oy,text,strlen(text)); } free(b); } void mMDS_Draw(char *c) { char buff[16]; int i; for (i=0;i 0 ) { printf("[%s] = \"%s\"\n",name,b.data); mds_parser(b.data); } } close(f); } } int main (int argc, char *argv[]) { int s; int i; XGCValues values; unsigned long valuemask; XFontStruct *font; map_db_read(); s = socket_init(6002); dis = XOpenDisplay (NULL); screen = DefaultScreen (dis); mainWin = create_window (dis, screen, 20, 20, WIN_X, WIN_Y); font = XLoadQueryFont(dis,"fixed"); values.foreground = XBlackPixel(dis,screen); values.background = XWhitePixel(dis,screen); values.font = font->fid; valuemask = GCForeground | GCBackground | GCFont; copyGC = XCreateGC (dis, mainWin, valuemask, &values); XMapRaised (dis, mainWin); XSelectInput(dis, mainWin, ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask); mds_readfile(".mMDSrc"); mMDS_Refresh(); while (1) { XEvent event; int cnt; KeySym key; XButtonEvent *b = (XButtonEvent *) &event; XConfigureEvent *c = (XConfigureEvent *) &event; socket_handler(s,mds_parser); while ((cnt = XPending(dis)) > 0 ) { XNextEvent (dis, &event); switch (event.type) { case Expose: redraw_exposed_area(event.xexpose.x,event.xexpose.y,event.xexpose.width,event.xexpose.height); // printf("%d\n",event.xexpose.count); if (event.xexpose.count == 0) { // socket_send_all("Expose\n"); for (i=0;ibutton == 1) { // printf("%d,%d\n",b->x,b->y); src_x += b->x - WIN_X/2; src_y += b->y - WIN_Y/2; mMDS_Refresh(); } if (b->button == 3) { int x,y; char longitude[16],latitude[16]; x = src_x + b->x; y = src_y + b->y; longitude_to_nmea(longitude,map_db_x2long(x)); latitude_to_nmea(latitude,map_db_y2lat(y)); printf("%d %d %s,%s\n",y,x,latitude,longitude); } if (b->button == 4) { //printf("Scroll Up\n"); src_y -= WIN_Y/10; mMDS_Refresh(); } if (b->button == 5) { //printf("Scroll Down\n"); src_y += WIN_Y/10; mMDS_Refresh(); } break; case ConfigureNotify: src_x -= (c->width - WIN_X) / 2; src_y -= (c->height - WIN_Y) / 2; WIN_X = c->width; WIN_Y = c->height; mMDS_Refresh(); break; } } } /*We shouldn't reach this point.*/ return EXIT_FAILURE; }