| version 1.16.2.1 | | version 1.1 |
|---|
| | |
| char *rcsid_x11_xutil_c = | | |
| "$Id: xutil.c,v 1.16.2.1 2005/02/23 04:09:28 tanner Exp $"; | | |
| /* | | /* |
| Crossfire client, a client program for the crossfire program. | | * static char *rcsid_xio_c = |
| | | * "$Id: xutil.c,v 1.1 2001/11/02 08:22:03 mwedel Exp $"; |
| Copyright (C) 2001-2003 Mark Wedel & Crossfire Development Team | | * |
| | | * This contains varous 'support' functions. These functions will probably |
| 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., 675 Mass Ave, Cambridge, MA 02139, USA. | | |
| | | |
| The author can be reached via e-mail to crossfire-devel@real-time.com | | |
| */ | | |
| | | |
| /* This contains various 'support' functions. These functions will probably | | |
| * go mostly unaltered between different toolkits, as long as X11 is still | | * go mostly unaltered between different toolkits, as long as X11 is still |
| * used. | | * used. This file is not compiled seperately, rather it is included by |
| | | * x11.c, so all statics will still work fine. |
| */ | | */ |
| | | |
| #include <client.h> | | #include <client.h> |
| #include <item.h> | | #include <item.h> |
| #include <config.h> | | #include <config.h> |
| #include <p_cmd.h> | | |
| | | |
| #ifdef HAVE_LIBXPM | | #ifdef HAVE_LIBXPM |
| #include <X11/xpm.h> | | #include <X11/xpm.h> |
| | |
| "White", /* 1 */ | | "White", /* 1 */ |
| "Navy", /* 2 */ | | "Navy", /* 2 */ |
| "Red", /* 3 */ | | "Red", /* 3 */ |
| "Chocolate", /* 4 was Orange, but impossible to read on DarkSeaGreen */ | | "Orange", /* 4 */ |
| "DodgerBlue", /* 5 */ | | "DodgerBlue", /* 5 */ |
| "DarkOrange2", /* 6 */ | | "DarkOrange2", /* 6 */ |
| "SeaGreen", /* 7 */ | | "SeaGreen", /* 7 */ |
| | |
| char *facetoname[MAXPIXMAPNUM]; | | char *facetoname[MAXPIXMAPNUM]; |
| | | |
| /* Can be set when user is moving to new machine type */ | | /* Can be set when user is moving to new machine type */ |
| uint8 updatekeycodes=FALSE; | | uint8 updatekeycodes=FALSE, keepcache=FALSE; |
| | | |
| #ifndef GDK_XUTIL | | #ifndef GDK_XUTIL |
| /* Initializes the data for image caching */ | | /* Initializes the data for image caching */ |
| void init_cache_data() | | void init_cache_data() |
| { | | { |
| int i; | | int i; |
| Pixmap ptmp; | | |
| #include "pixmaps/question.111" | | |
| | | |
| | | #include "pixmaps/question.111" |
| | | |
| /* Currently, we can cache in all face modes currently supported, | | /* Currently, we can cache in all face modes currently supported, |
| * so I removed the code that did checks on that. | | * so I removed the code that did checks on that. |
| */ | | */ |
| | | |
| pixmaps[0] = malloc(sizeof(struct PixmapInfo)); | | pixmaps[0].mask=None; |
| pixmaps[0]->mask=None; | | pixmaps[0].bitmap=XCreateBitmapFromData(display, |
| ptmp=XCreateBitmapFromData(display,DefaultRootWindow(display), | | RootWindow(display, screen_num), (const char*)question_bits, image_size,image_size); |
| question_bits,question_width,question_height); | | |
| | | |
| /* In xpm mode, XCopyArea is used from this data, so we need to copy | | /* In xpm mode, XCopyArea is used from this data, so we need to copy |
| * the image into an pixmap of appropriate depth. | | * the image into an pixmap of appropriate depth. |
| | | * Note that while are image created is the image size, since we know |
| | | * that are filler image is currently only 24x24, we only copy that much |
| | | * data. |
| */ | | */ |
| pixmaps[0]->pixmap=XCreatePixmap(display, win_root, image_size, image_size, | | pixmaps[0].pixmap=XCreatePixmap(display, win_root, image_size, image_size, |
| DefaultDepth(display,DefaultScreen(display))); | | DefaultDepth(display,DefaultScreen(display))); |
| XCopyPlane(display, ptmp, pixmaps[0]->pixmap, gc_game, | | XCopyPlane(display, pixmaps[0].bitmap, pixmaps[0].pixmap, gc_game, |
| 0,0,image_size,image_size,0,0,1); | | 0,0,24,24,0,0,1); |
| XFreePixmap(display, ptmp); | | |
| | | |
| | | pixmaps[0].bg = 0; |
| | | pixmaps[0].fg = 1; |
| facetoname[0]=NULL; | | facetoname[0]=NULL; |
| | | |
| /* Initialize all the images to be of the same value. */ | | /* Initialize all the images to be of the same value. */ |
| | |
| facetoname[i]=NULL; | | facetoname[i]=NULL; |
| } | | } |
| | | |
| init_common_cache_data(); | | #ifdef IMAGECACHEDIR |
| | | strcpy(facecachedir, IMAGECACHEDIR); |
| | | #else |
| | | sprintf(facecachedir,"%s/.crossfire/images", getenv("HOME")); |
| | | #endif |
| | | |
| | | if (make_path_to_dir(facecachedir)==-1) { |
| | | fprintf(stderr,"Could not create directory %s, exiting\n", facecachedir); |
| | | exit(1); |
| | | } |
| | | |
| } | | } |
| #endif | | #endif |
| | | |
| | | static void requestface(int pnum, char *facename, char *facepath) |
| | | { |
| | | char buf[MAX_BUF]; |
| | | |
| | | facetoname[pnum] = strdup_local(facepath); |
| | | sprintf(buf,"askface %d", pnum); |
| | | cs_write_string(csocket.fd, buf, strlen(buf)); |
| | | /* Need to make sure we have the directory */ |
| | | sprintf(buf,"%s/%c%c", facecachedir, facename[0], facename[1]); |
| | | if (access(buf,R_OK)) make_path_to_dir(buf); |
| | | } |
| /* Rotate right from bsd sum. */ | | /* Rotate right from bsd sum. */ |
| #define ROTATE_RIGHT(c) if ((c) & 01) (c) = ((c) >>1) + 0x80000000; else (c) >>= 1; | | #define ROTATE_RIGHT(c) if ((c) & 01) (c) = ((c) >>1) + 0x80000000; else (c) >>= 1; |
| | | |
| /*#define CHECKSUM_DEBUG*/ | | /*#define CHECKSUM_DEBUG*/ |
| | | |
| | | /* This is common for both face1 and face commands. */ |
| | | void finish_face_cmd(int pnum, uint32 checksum, int has_sum, char *face) |
| | | { |
| | | char buf[MAX_BUF]; |
| | | int fd,len; |
| | | char data[65536]; |
| | | uint32 newsum=0; |
| | | #ifndef GDK_XUTIL |
| | | Pixmap pixmap, mask; |
| | | #endif |
| | | |
| | | /* Check private cache first */ |
| | | sprintf(buf,"%s/.crossfire/gfx/%s", getenv("HOME"), face); |
| | | if (display_mode == Png_Display) |
| | | strcat(buf,".png"); |
| | | |
| | | if ((fd=open(buf, O_RDONLY))!=-1) { |
| | | len=read(fd, data, 65535); |
| | | close(fd); |
| | | has_sum=0; /* Maybe not really true, but we want to use this image |
| | | * and not request a replacement. |
| | | */ |
| | | } else { |
| | | |
| | | /* Hmm. Should we use this file first, or look in our home |
| | | * dir cache first? |
| | | */ |
| | | if (use_private_cache) { |
| | | len = find_face_in_private_cache(face, checksum); |
| | | if ( len > 0 ) { |
| | | #ifdef GDK_XUTIL |
| | | pixmaps[pnum].gdkpixmap = private_cache[len].pixmap; |
| | | pixmaps[pnum].gdkmask = private_cache[len].mask; |
| | | pixmaps[pnum].png_data = private_cache[len].png_data; |
| | | |
| | | #else |
| | | pixmaps[pnum].pixmap = private_cache[len].pixmap; |
| | | pixmaps[pnum].mask = private_cache[len].mask; |
| | | #endif |
| | | /* we may want to find a better match */ |
| | | if (private_cache[len].checksum == checksum || |
| | | !has_sum || keepcache) return; |
| | | } |
| | | } |
| | | |
| | | |
| | | /* To prevent having a directory with 2000 images, we do a simple |
| | | * split on the first 2 characters. |
| | | */ |
| | | sprintf(buf,"%s/%c%c/%s", facecachedir, face[0], face[1],face); |
| | | if (display_mode == Png_Display) |
| | | strcat(buf,".png"); |
| | | |
| | | if ((fd=open(buf, O_RDONLY))==-1) { |
| | | requestface(pnum, face, buf); |
| | | return; |
| | | } |
| | | len=read(fd, data, 65535); |
| | | close(fd); |
| | | } |
| | | |
| | | if (has_sum && !keepcache) { |
| | | for (fd=0; fd<len; fd++) { |
| | | ROTATE_RIGHT(newsum); |
| | | newsum += data[fd]; |
| | | newsum &= 0xffffffff; |
| | | } |
| | | |
| | | if (newsum != checksum) { |
| | | #ifdef CHECKSUM_DEBUG |
| | | fprintf(stderr,"finish_face_command: checksums differ: %s, %x != %x\n", |
| | | face, newsum, checksum); |
| | | #endif |
| | | requestface(pnum, face, buf); |
| | | #ifdef CHECKSUM_DEBUG |
| | | } else { |
| | | fprintf(stderr,"finish_face_command: checksums match: %s, %x == %x\n", |
| | | face, newsum, checksum); |
| | | #endif |
| | | } |
| | | } |
| | | if (display_mode==Png_Display) { |
| | | unsigned long w,h; |
| | | |
| | | /* Fail on this read, we will request a new copy */ |
| | | if (png_to_xpixmap(display, win_game, data, len, |
| | | &pixmap, &mask, &colormap, &w, &h)) { |
| | | requestface(pnum, face, buf); |
| | | } else { |
| | | pixmaps[pnum].pixmap = pixmap; |
| | | pixmaps[pnum].mask = mask; |
| | | } |
| | | |
| | | } else if (display_mode==Pix_Display) { |
| | | pixmaps[pnum].bitmap = XCreateBitmapFromData(display, |
| | | RootWindow(display,DefaultScreen(display)), |
| | | (char*)data,24,24); |
| | | pixmaps[pnum].fg = (data[24] << 24) + (data[25] << 16) + (data[26] << 8) + |
| | | data[27]; |
| | | pixmaps[pnum].bg = (data[28] << 24) + (data[29] << 16 )+ (data[30] << 8 )+ |
| | | data[31]; |
| | | } |
| | | } |
| | | |
| | | |
| | | #ifndef GDK_XUTIL |
| | | |
| int allocate_colors(Display *disp, Window w, long screen_num, | | int allocate_colors(Display *disp, Window w, long screen_num, |
| Colormap *colormap, XColor discolor[16]) | | Colormap *colormap, XColor discolor[16]) |
| | |
| return iscolor; | | return iscolor; |
| } | | } |
| | | |
| | | #endif /* GDK_XUTIL */ |
| | | |
| | | |
| | | |
| | |
| Key_Entry *newkey; | | Key_Entry *newkey; |
| int i, direction=-1; | | int i, direction=-1; |
| | | |
| #if 0 | | |
| /* This is at least a meaningless check on my system that results in | | |
| * a compile warning (always false result), so may was well comment it | | |
| * out - MSW 2005-02-09 | | |
| */ | | |
| if (keycode>MAX_KEYCODE) { | | if (keycode>MAX_KEYCODE) { |
| LOG(LOG_WARNING,"x11::insert_key", "keycode that is passed is greater than 255."); | | fprintf(stderr,"Warning insert_key:keycode that is passed is greater than 255.\n"); |
| keycode=0; /* hopefully the rest of the data is OK */ | | keycode=0; /* hopefully the rest of the data is OK */ |
| } | | } |
| #endif | | |
| if (keys[keycode]==NULL) { | | if (keys[keycode]==NULL) { |
| keys[keycode]=malloc(sizeof(Key_Entry)); | | keys[keycode]=malloc(sizeof(Key_Entry)); |
| keys[keycode]->command=NULL; | | keys[keycode]->command=NULL; |
| | |
| | | |
| if (buf[0]=='#' || buf[0]=='\n') return; | | if (buf[0]=='#' || buf[0]=='\n') return; |
| if ((cpnext = strchr(buf,' '))==NULL) { | | if ((cpnext = strchr(buf,' '))==NULL) { |
| LOG(LOG_WARNING,"x11::parse_keybind_line","Line %d (%s) corrupted.", line,buf); | | fprintf(stderr,"Line %d (%s) corrupted in keybinding file.\n", line,buf); |
| return; | | return; |
| } | | } |
| /* Special keybinding line */ | | /* Special keybinding line */ |
| | |
| while (*cpnext == ' ') ++cpnext; | | while (*cpnext == ' ') ++cpnext; |
| cp = strchr(cpnext, ' '); | | cp = strchr(cpnext, ' '); |
| if (!cp) { | | if (!cp) { |
| LOG(LOG_WARNING,"x11::parse_keybind_line","Line %d (%s) corrupted in keybinding file.", line,buf); | | fprintf(stderr,"Line %d (%s) corrupted in keybinding file.\n", line,buf); |
| return; | | return; |
| } | | } |
| *cp++ = 0; /* Null terminate it */ | | *cp++ = 0; /* Null terminate it */ |
| cp1 = strchr(cp, ' '); | | cp1 = strchr(cp, ' '); |
| if (!cp1) { | | if (!cp1) { |
| LOG(LOG_WARNING,"x11::parse_keybind_line","Line %d (%s) corrupted in keybinding file.", line,buf); | | fprintf(stderr,"Line %d (%s) corrupted in keybinding file.\n", line,buf); |
| return; | | return; |
| } | | } |
| *cp1 ++ = 0;/* Null terminate it */ | | *cp1 ++ = 0;/* Null terminate it */ |
| | |
| keysym = XStringToKeysym(cp); | | keysym = XStringToKeysym(cp); |
| /* As of now, all these keys must have keysyms */ | | /* As of now, all these keys must have keysyms */ |
| if (keysym == NoSymbol) { | | if (keysym == NoSymbol) { |
| LOG(LOG_WARNING,"x11::parse_keybind_line","Could not convert %s into keysym", cp); | | fprintf(stderr,"Could not convert %s into keysym\n", cp); |
| return; | | return; |
| } | | } |
| if (!strcmp(cpnext,"commandkey")) { | | if (!strcmp(cpnext,"commandkey")) { |
| | |
| keysym = XStringToKeysym(buf); | | keysym = XStringToKeysym(buf); |
| cp = cpnext; | | cp = cpnext; |
| if ((cpnext = strchr(cp,' '))==NULL) { | | if ((cpnext = strchr(cp,' '))==NULL) { |
| LOG(LOG_WARNING,"x11::parse_keybind_line","Line %d (%s) corrupted in keybinding file.", line, cp); | | fprintf(stderr,"Line %d (%s) corrupted in keybinding file.\n", line, cp); |
| return; | | return; |
| } | | } |
| *cpnext++ = '\0'; | | *cpnext++ = '\0'; |
| | |
| keycode = atoi(cp); | | keycode = atoi(cp); |
| cp = cpnext; | | cp = cpnext; |
| if ((cpnext = strchr(cp,' '))==NULL) { | | if ((cpnext = strchr(cp,' '))==NULL) { |
| LOG(LOG_WARNING,"x11::parse_keybind_line","Line %d (%s) corrupted in keybinding file.", line, cp); | | fprintf(stderr,"Line %d (%s) corrupted in keybinding file.\n", line, cp); |
| return; | | return; |
| } | | } |
| *cpnext++ = '\0'; | | *cpnext++ = '\0'; |
| | |
| flags |= KEYF_STANDARD; | | flags |= KEYF_STANDARD; |
| break; | | break; |
| default: | | default: |
| LOG(LOG_WARNING,"x11::parse_keybind_line","Unknown flag (%c) line %d in key binding file", | | fprintf(stderr,"Warning: Unknown flag (%c) line %d in key binding file\n", |
| *cp, line); | | *cp, line); |
| } | | } |
| cp++; | | cp++; |
| | |
| * it away, but at least print a warning message. | | * it away, but at least print a warning message. |
| */ | | */ |
| if (keycode==0) { | | if (keycode==0) { |
| LOG(LOG_WARNING,"x11::parse_keybind_line","could not convert keysym %s into keycode, ignoring", | | fprintf(stderr,"Warning: could not convert keysym %s into keycode, ignoring\n", |
| buf); | | buf); |
| } | | } |
| } | | } |
| /* Rest of the line is the actual command. Lets kill the newline */ | | /* Rest of the line is the actual command. Lets kill the newline */ |
| cpnext[strlen(cpnext)-1]='\0'; | | cpnext[strlen(cpnext)-1]='\0'; |
| if (strlen(cpnext)>(sizeof(bind_buf)-1)){ | | |
| cpnext[sizeof(bind_buf)-1]='\0'; | | |
| LOG(LOG_WARNING,"gtk::parse_keybind_line","Had to truncate a too long command"); | | |
| } | | |
| insert_key(keysym, keycode, flags | standard, cpnext); | | insert_key(keysym, keycode, flags | standard, cpnext); |
| } | | } |
| | | |
| | |
| | | |
| sprintf(buf,"%s/.crossfire/keys", getenv("HOME")); | | sprintf(buf,"%s/.crossfire/keys", getenv("HOME")); |
| if ((fp=fopen(buf,"r"))==NULL) { | | if ((fp=fopen(buf,"r"))==NULL) { |
| LOG(LOG_INFO,"x11::init_keys","Could not open ~/.crossfire/keys, trying to load global bindings"); | | fprintf(stderr,"Could not open ~/.crossfire/keys, trying to load global bindings\n"); |
| if (client_libdir==NULL) { | | if (client_libdir==NULL) { |
| init_default_keybindings(); | | init_default_keybindings(); |
| return; | | return; |
| | |
| else if (kc==runkey[0] || ks==runkeysym[0] || | | else if (kc==runkey[0] || ks==runkeysym[0] || |
| kc==runkey[1] || ks==runkeysym[1]) { | | kc==runkey[1] || ks==runkeysym[1]) { |
| cpl.run_on=0; | | cpl.run_on=0; |
| if (use_config[CONFIG_ECHO]) draw_info("stop run",NDI_BLACK); | | if (cpl.echo_bindings) draw_info("stop run",NDI_BLACK); |
| #ifdef GDK_XUTIL | | #ifdef GDK_XUTIL |
| clear_run(); | | clear_run(); |
| gtk_label_set (GTK_LABEL(run_label)," "); | | gtk_label_set (GTK_LABEL(run_label)," "); |
| | |
| * to stop. This should do that. | | * to stop. This should do that. |
| */ | | */ |
| else if (cpl.fire_on) | | else if (cpl.fire_on) |
| | | #ifdef GDK_XUTIL |
| | | clear_fire(); |
| | | #else |
| stop_fire(); | | stop_fire(); |
| | | #endif |
| } | | } |
| | | |
| /* This parses a keypress. It should only be called when in Playing | | /* This parses a keypress. It should only be called when in Playing |
| * mode. | | * mode. |
| */ | | */ |
| void parse_key(char key, KeyCode keycode, KeySym keysym, int repeated) | | void parse_key(char key, KeyCode keycode, KeySym keysym) |
| { | | { |
| Key_Entry *keyentry, *first_match=NULL; | | Key_Entry *keyentry, *first_match=NULL; |
| int present_flags=0; | | int present_flags=0; |
| char buf[MAX_BUF]; | | char buf[MAX_BUF]; |
| | | |
| if (keycode == commandkey && keysym==commandkeysym) { | | if (keycode == commandkey && keysym==commandkeysym) { |
| | | #ifdef GDK_XUTIL |
| | | if (split_windows) { |
| | | gtk_widget_grab_focus (GTK_WIDGET(gtkwin_info)); |
| | | gtk_widget_grab_focus (GTK_WIDGET(entrytext)); |
| | | } else { |
| | | gtk_widget_grab_focus (GTK_WIDGET(entrytext)); |
| | | } |
| | | gtk_entry_set_visibility(GTK_ENTRY(entrytext), 1); |
| | | |
| | | #else |
| draw_prompt(">"); | | draw_prompt(">"); |
| | | #endif |
| cpl.input_state = Command_Mode; | | cpl.input_state = Command_Mode; |
| cpl.no_echo=FALSE; | | cpl.no_echo=FALSE; |
| return; | | return; |
| | |
| run_dir(first_match->direction); | | run_dir(first_match->direction); |
| sprintf(buf,"run %s", first_match->command); | | sprintf(buf,"run %s", first_match->command); |
| } | | } |
| else if (!repeated) { | | else { |
| strcpy(buf,first_match->command); | | strcpy(buf,first_match->command); |
| extended_command(first_match->command); | | extended_command(first_match->command); |
| } | | } |
| else | | if (cpl.echo_bindings) draw_info(buf,NDI_BLACK); |
| sprintf(buf,"move %s (ignored)", first_match->command); | | |
| if (use_config[CONFIG_ECHO]) draw_info(buf,NDI_BLACK); | | |
| } | | } |
| else { | | else { |
| if (use_config[CONFIG_ECHO]) draw_info(first_match->command,NDI_BLACK); | | if (cpl.echo_bindings) draw_info(first_match->command,NDI_BLACK); |
| extended_command(first_match->command); | | extended_command(first_match->command); |
| } | | } |
| return; | | return; |
| | |
| */ | | */ |
| static char * get_key_info(Key_Entry *key, KeyCode kc, int save_mode) | | static char * get_key_info(Key_Entry *key, KeyCode kc, int save_mode) |
| { | | { |
| /* bind buf is the maximum space allowed for a | | static char buf[MAX_BUF]; |
| * binded command. We will add additional datas to | | |
| * it so we increase by MAX_BUF*/ | | |
| static char buf[MAX_BUF+sizeof(bind_buf)]; | | |
| char buff[MAX_BUF]; | | char buff[MAX_BUF]; |
| int bi=0; | | int bi=0; |
| | | |
| | |
| | | |
| | | |
| | | |
| void bind_key(const char *params) | | void bind_key(char *params) |
| { | | { |
| char buf[MAX_BUF]; | | char buf[MAX_BUF]; |
| | | |
| | |
| return; | | return; |
| } | | } |
| | | |
| strncpy(bind_buf, params, sizeof(bind_buf)-1); | | sprintf(buf, "Push key to bind '%s'.", params); |
| bind_buf[sizeof(bind_buf)-1]=0; | | |
| if (strlen(params) >= sizeof(bind_buf)) { | | |
| draw_info("Keybinding too long! Truncated:",NDI_RED); | | |
| draw_info(bind_buf,NDI_RED); | | |
| } | | |
| | | |
| sprintf(buf, "Push key to bind '%s'.", bind_buf); | | |
| draw_info(buf,NDI_BLACK); | | draw_info(buf,NDI_BLACK); |
| | | strcpy(bind_buf, params); |
| bind_keycode=NULL; | | bind_keycode=NULL; |
| cpl.input_state = Configure_Keys; | | cpl.input_state = Configure_Keys; |
| return; | | return; |
| | |
| | | |
| sprintf(buf,"%s/.crossfire/keys", getenv("HOME")); | | sprintf(buf,"%s/.crossfire/keys", getenv("HOME")); |
| if (make_path_to_file(buf)==-1) { | | if (make_path_to_file(buf)==-1) { |
| LOG(LOG_WARNING,"x11::save_keys","Could not create %s", buf); | | fprintf(stderr,"Could not create %s\n", buf); |
| return; | | return; |
| } | | } |
| if ((fp=fopen(buf,"w"))==NULL) { | | if ((fp=fopen(buf,"w"))==NULL) { |
| | |
| draw_info(" -g unbinds a global binding", NDI_BLACK); | | draw_info(" -g unbinds a global binding", NDI_BLACK); |
| } | | } |
| | | |
| void unbind_key(const char *params) | | void unbind_key(char *params) |
| { | | { |
| int count=0, keyentry, onkey,global=0; | | int count=0, keyentry, onkey,global=0; |
| Key_Entry *key, *tmp; | | Key_Entry *key, *tmp; |
| | |
| goto unbinded; | | goto unbinded; |
| } | | } |
| } | | } |
| LOG(LOG_ERROR,"x11::unbind_key","found number entry, but could not find actual key"); | | fprintf(stderr,"unbind_key - found number entry, but could not find actual key\n"); |
| } | | } |
| } | | } |
| } | | } |
| | |
| } | | } |
| | | |
| | | |
| | | /* This code is somewhat from the crossedit/xutil.c. |
| | | * What we do is create a private copy of all the images |
| | | * for ourselves. Then, if we get a request to display |
| | | * a new image, we see if we have it in this cache. |
| | | * |
| | | * This is only supported for PNG images. I see now reason |
| | | * to support the older image formats since they will be |
| | | * going away. |
| | | */ |
| | | |
| | | int ReadImages() { |
| | | |
| | | int len,i,num ; |
| | | FILE *infile; |
| | | char *cp, databuf[10000], *last_cp=NULL; |
| | | unsigned long x; |
| | | #ifndef GDK_XUTIL |
| | | unsigned long y; |
| | | #endif |
| | | |
| | | if ((display_mode != Png_Display) || (image_file[0] == 0)) return 0; |
| | | |
| | | if (!cache_images) { |
| | | cache_images=1; /* we want face commands from server */ |
| | | keepcache=TRUE; /* Reduce requests for new image */ |
| | | } |
| | | |
| | | if ((infile = fopen(image_file,"r"))==NULL) { |
| | | fprintf(stderr,"Unable to open %s\n", image_file); |
| | | return 0; |
| | | } |
| | | for (i=0; i<MAXPIXMAPNUM; i++) |
| | | private_cache[0].name = NULL; |
| | | |
| | | i=0; |
| | | while (fgets(databuf,MAX_BUF,infile)) { |
| | | |
| | | /* First, verify that that image header line is OK */ |
| | | if(strncmp(databuf,"IMAGE ",6)!=0) { |
| | | fprintf(stderr,"ReadImages:Bad image line - not IMAGE, instead\n%s",databuf); |
| | | return 0; |
| | | } |
| | | num = atoi(databuf+6); |
| | | if (num<0 || num > MAXPIXMAPNUM) { |
| | | fprintf(stderr,"Pixmap number less than zero: %d, %s\n",num, databuf); |
| | | return 0; |
| | | } |
| | | /* Skip accross the number data */ |
| | | for (cp=databuf+6; *cp!=' '; cp++) ; |
| | | len = atoi(cp); |
| | | if (len==0 || len>10000) { |
| | | fprintf(stderr,"ReadImages: length not valid: %d\n%s", |
| | | len,databuf); |
| | | return 0; |
| | | } |
| | | /* We need the name so that when an FaceCmd comes in, we can look for |
| | | the matching name. |
| | | */ |
| | | while (*cp!=' ' && *cp!='\n') cp++; /* skip over len */ |
| | | |
| | | /* We only want the last component of the name - not the full path */ |
| | | while (*cp != '\n') { |
| | | if (*cp == '/') last_cp = cp+1; /* don't want the slah either */ |
| | | cp++; |
| | | } |
| | | *cp = '\0'; /* Clear newline */ |
| | | |
| | | private_cache[num].name = strdup_local(last_cp); |
| | | |
| | | if (fread(databuf, 1, len, infile)!=len) { |
| | | fprintf(stderr,"read_client_images: Did not read desired amount of data, wanted %d\n%s", |
| | | len, databuf); |
| | | return 0; |
| | | } |
| | | private_cache[num].checksum=0; |
| | | for (x=0; x<len; x++) { |
| | | ROTATE_RIGHT(private_cache[num].checksum); |
| | | private_cache[num].checksum += databuf[x]; |
| | | private_cache[num].checksum &= 0xffffffff; |
| | | } |
| | | if (num > last_face_num) last_face_num = num; |
| | | #ifdef HAVE_LIBPNG |
| | | #ifdef GDK_XUTIL |
| | | if (pngximage && !(private_cache[num].png_data = png_to_data(databuf, (int)len))) { |
| | | fprintf(stderr,"Got error on png_to_data\n"); |
| | | } |
| | | /* even if using pngximage, we standard image for the inventory list */ |
| | | if (png_to_gdkpixmap(gtkwin_root->window, databuf, len, |
| | | &private_cache[num].pixmap, &private_cache[num].mask, |
| | | gtk_widget_get_colormap(gtkwin_root))) { |
| | | |
| | | fprintf(stderr,"Error loading png file.\n"); |
| | | } |
| | | #else |
| | | if (png_to_xpixmap(display, win_game, databuf, len, |
| | | &private_cache[num].pixmap, &private_cache[num].mask, |
| | | &colormap, &x, &y)) { |
| | | |
| | | fprintf(stderr,"Error loading png file.\n"); |
| | | } |
| | | #endif |
| | | #endif |
| | | } |
| | | fclose(infile); |
| | | use_private_cache=1; |
| | | return 0; |
| | | } |
| | | |
| /* try to find a face in our private cache. We return the face | | /* try to find a face in our private cache. We return the face |
| * number if we find one, -1 for no face match | | * number if we find one, -1 for no face match |
| */ | | */ |
| | |
| return -1; | | return -1; |
| } | | } |
| | | |
| | | |
| void image_update_download_status(int start, int end, int total) | | |
| { | | |
| char buf[MAX_BUF]; | | |
| | | |
| sprintf(buf,"Downloaded %d of %d images", start, total); | | |
| | | |
| draw_info(buf,NDI_BLUE); | | |
| } | | |
| | | |
| /* Start of map handling code. | | /* Start of map handling code. |
| * For the most part, this actually is not window system specific, | | * For the most part, this actually is not window system specific, |
| * but certainly how the client wants to store this may vary. | | * but certainly how the client wants to store this may vary. |
| * | | |
| * At least in the gtk and x11 clients, 95+% of this code | | |
| * is the same - the only think I think is different is | | |
| * that the gtk will call sdl_scroll. This should | | |
| * probably be moved into the common area. | | |
| */ | | */ |
| | | |
| #define MAXFACES 5 | | #define MAXFACES 5 |
| | |
| * FIX ME: Don't assume rectangle | | * FIX ME: Don't assume rectangle |
| */ | | */ |
| | | |
| | | int map_size= 0; |
| PlayerPosition pl_pos; | | PlayerPosition pl_pos; |
| | | |
| | | |
| | |
| */ | | */ |
| void allocate_map( struct Map* new_map, int ax, int ay) | | void allocate_map( struct Map* new_map, int ax, int ay) |
| { | | { |
| | | |
| int i= 0; | | int i= 0; |
| | | |
| if( new_map == NULL) | | if( new_map == NULL) |
| | |
| } | | } |
| | | |
| new_map->cells= (struct MapCell**)calloc( sizeof( struct MapCell*) * ay | | new_map->cells= (struct MapCell**)calloc( sizeof( struct MapCell*) * ay |
| + sizeof( struct MapCell) * ax * ay, 1); | | + sizeof( struct MapCell) * |
| | | map_size * map_size, 1); |
| if( new_map->cells == NULL) | | if( new_map->cells == NULL) |
| return; | | return; |
| | | |
| | |
| /* Finish assigning the beginning of each row relative to the first row | | /* Finish assigning the beginning of each row relative to the first row |
| * assigned above | | * assigned above |
| */ | | */ |
| for( i= 0; i < ay; i++) { | | for( i= 0; i < ay; i++) |
| | | { |
| new_map->cells[i]= new_map->cells[0] + ( i * ax); | | new_map->cells[i]= new_map->cells[0] + ( i * ax); |
| } | | } |
| | | |
| new_map->x= ax; | | new_map->x= ax; |
| new_map->y= ay; | | new_map->y= ay; |
| | | |
| | |
| */ | | */ |
| void reset_map() | | void reset_map() |
| { | | { |
| | | if( fog_of_war == TRUE) |
| | | { |
| int x= 0; | | int x= 0; |
| int y= 0; | | int y= 0; |
| | | |
| pl_pos.x= the_map.x/2; | | pl_pos.x= the_map.x/2; |
| pl_pos.y= the_map.y/2; | | pl_pos.y= the_map.y/2; |
| memset( the_map.cells[0], 0, | | memset( the_map.cells[0], 0, |
| sizeof( struct MapCell) * the_map.x * the_map.y); | | sizeof( struct MapCell) * the_map.x * the_map.y); |
| for( x= pl_pos.x; x < (pl_pos.x + use_config[CONFIG_MAPWIDTH]); x++) | | for( x= pl_pos.x; x < (pl_pos.x + mapx); x++) |
| { | | { |
| for( y= pl_pos.y; y < (pl_pos.y + use_config[CONFIG_MAPHEIGHT]); y++) | | for( y= pl_pos.y; y < (pl_pos.y + mapy); y++) |
| { | | { |
| the_map.cells[x][y].need_update= 1; | | the_map.cells[x][y].need_update= 1; |
| } | | } |
| } | | } |
| cs_print_string(csocket.fd, "mapredraw"); | | } |
| | | else |
| | | { |
| | | int x= 0; |
| | | int y= 0; |
| | | memset( the_map.cells[0], 0, |
| | | sizeof( struct MapCell) * the_map.x * the_map.y); |
| | | for( x= 0; x < mapx; x++) |
| | | { |
| | | for( y= 0; y < mapy; y++) |
| | | { |
| | | the_map.cells[x][y].need_update= 1; |
| | | } |
| | | } |
| | | } |
| | | |
| | | cs_write_string( csocket.fd, "mapredraw", 9); |
| | | |
| | | return; |
| | | } |
| | | |
| | | void display_map_clearcell(long x,long y) |
| | | { |
| | | if( fog_of_war == TRUE) |
| | | { |
| | | /* we don't want to clear out the values yet. We will do that |
| | | * next time we try to write some data to this tile. For now |
| | | * we just mark that it has been cleared. Also mark it for |
| | | * update so we can draw the proper fog cell over it |
| | | */ |
| | | x+= pl_pos.x; |
| | | y+= pl_pos.y; |
| | | the_map.cells[x][y].cleared= 1; |
| | | the_map.cells[x][y].need_update= 1; |
| | | } |
| | | else |
| | | { |
| | | int i; |
| | | the_map.cells[x][y].count = 0; |
| | | the_map.cells[x][y].darkness = 0; |
| | | the_map.cells[x][y].need_update = 1; |
| | | the_map.cells[x][y].have_darkness = 0; |
| | | the_map.cells[x][y].cleared= 0; |
| | | for (i=0; i<MAXFACES; i++) |
| | | the_map.cells[x][y].faces[i] = -1; /* empty/blank face */ |
| | | } |
| | | |
| return; | | return; |
| } | | } |
| | | |
| | |
| int x= 0; | | int x= 0; |
| int y= 0; | | int y= 0; |
| | | |
| for( y= 0; y < use_config[CONFIG_MAPHEIGHT]; y++) | | for( y= 0; y < mapy; y++) |
| { | | { |
| for( x= 0; x < use_config[CONFIG_MAPWIDTH]; x++) | | for( x= 0; x < mapx; x++) |
| { | | { |
| | | if( the_map.cells[x][y].count== 0) |
| | | fprintf( stderr, "[ - ]"); |
| | | else |
| fprintf( stderr, "[%3d]", the_map.cells[x][y].darkness); | | fprintf( stderr, "[%3d]", the_map.cells[x][y].darkness); |
| } | | } |
| fprintf( stderr, "\n"); | | fprintf( stderr, "\n"); |
| | |
| int y= 0; | | int y= 0; |
| int z= 0; | | int z= 0; |
| | | |
| int local_mapx = pl_pos.x + use_config[CONFIG_MAPWIDTH]; | | int local_mapx; |
| int local_mapy = pl_pos.y + use_config[CONFIG_MAPHEIGHT]; | | int local_mapy; |
| | | |
| if( use_config[CONFIG_FOGWAR] == TRUE) | | if( fog_of_war == TRUE) |
| { | | { |
| | | local_mapx= pl_pos.x + mapx; |
| | | local_mapy= pl_pos.y + mapy; |
| printf( " Current X pos: %d -- Current Y pos: %d\n", | | printf( " Current X pos: %d -- Current Y pos: %d\n", |
| pl_pos.x, pl_pos.y); | | pl_pos.x, pl_pos.y); |
| } | | } |
| | | else |
| | | { |
| | | local_mapx= mapx; |
| | | local_mapy= mapy; |
| | | } |
| | | |
| fprintf( stderr, "-----------------------\n"); | | fprintf( stderr, "-----------------------\n"); |
| for( y= pl_pos.y ; y < local_mapy; y++) | | for( y= (fog_of_war == TRUE ? pl_pos.y : 0); y < local_mapy; y++) |
| { | | { |
| for( z= 0; z < MAXFACES; z++) | | for( z= 0; z < MAXFACES; z++) |
| { | | { |
| for( x= pl_pos.x ; x < local_mapx; x++) | | for( x= (fog_of_war == TRUE ? pl_pos.x : 0); x < local_mapx; x++) |
| { | | { |
| if(the_map.cells[x][y].heads[z].face <= 0) | | if( the_map.cells[x][y].count == 0) |
| fprintf( stderr, "[ -- ]"); | | fprintf( stderr, "[ -- ]"); |
| else | | else |
| fprintf( stderr, "[%4d]", the_map.cells[x][y].heads[z].face); | | fprintf( stderr, "[%4d]", the_map.cells[x][y].faces[z]); |
| } | | } |
| fprintf( stderr, "\n"); | | fprintf( stderr, "\n"); |
| } | | } |
| | |
| | | |
| void set_map_darkness(int x, int y, uint8 darkness) | | void set_map_darkness(int x, int y, uint8 darkness) |
| { | | { |
| | | if( fog_of_war == TRUE) |
| | | { |
| x+= pl_pos.x; | | x+= pl_pos.x; |
| y+= pl_pos.y; | | y+= pl_pos.y; |
| | | } |
| | | |
| the_map.cells[x][y].have_darkness = 1; | | the_map.cells[x][y].have_darkness = 1; |
| if (darkness != (255 - the_map.cells[x][y].darkness )) { | | if (darkness != (255 - the_map.cells[x][y].darkness )) { |
| the_map.cells[x][y].darkness = 255 - darkness; | | the_map.cells[x][y].darkness = 255 - darkness; |
| the_map.cells[x][y].need_update = 1; | | the_map.cells[x][y].need_update = 1; |
| | | #ifdef GDK_XUTIL |
| /* pretty ugly - since the light code with pngximage uses | | /* pretty ugly - since the light code with pngximage uses |
| * neighboring spaces to adjust the darkness, we now need to | | * neighboring spaces to adjust the darkness, we now need to |
| * let the neighbors know they should update their darkness | | * let the neighbors know they should update their darkness |
| * now. | | * now. |
| */ | | */ |
| if (use_config[CONFIG_SDL]) { | | if (pngximage || sdlimage) { |
| if (x-1>0) the_map.cells[x-1][y].need_update = 1; | | if (x-1>0) the_map.cells[x-1][y].need_update = 1; |
| if (y-1>0) the_map.cells[x][y-1].need_update = 1; | | if (y-1>0) the_map.cells[x][y-1].need_update = 1; |
| if (x+1<use_config[CONFIG_MAPWIDTH]) the_map.cells[x+1][y].need_update = 1; | | if (x+1<mapx) the_map.cells[x+1][y].need_update = 1; |
| if (y+1<use_config[CONFIG_MAPHEIGHT]) the_map.cells[x][y+1].need_update = 1; | | if (y+1<mapy) the_map.cells[x][y+1].need_update = 1; |
| | | } |
| | | #endif /* GDK_XUTIL */ |
| | | } |
| | | } |
| | | |
| | | /* sets the face at layer to some value. We just can't |
| | | * restact arbitrarily, as the server now sends faces only |
| | | * for layers that change, and not the entire space. |
| | | */ |
| | | void set_map_face(int x, int y, int layer, int face) |
| | | { |
| | | if( fog_of_war == TRUE) |
| | | { |
| | | x+= pl_pos.x; |
| | | y+= pl_pos.y; |
| | | } |
| | | |
| | | if( (fog_of_war == TRUE) && (the_map.cells[x][y].cleared == 1) ) |
| | | { |
| | | /* This cell has been cleared previously but now we are |
| | | * writing new data to do. So we have to clear it for real now |
| | | */ |
| | | int i= 0; |
| | | the_map.cells[x][y].count= 0; |
| | | the_map.cells[x][y].darkness= 0; |
| | | the_map.cells[x][y].need_update= 1; |
| | | the_map.cells[x][y].have_darkness= 0; |
| | | the_map.cells[x][y].cleared= 0; |
| | | for (i=0; i<MAXFACES; i++) |
| | | the_map.cells[x][y].faces[i]= -1; /* empty/blank face */ |
| | | } |
| | | |
| | | the_map.cells[x][y].faces[layer] = face; |
| | | if ((layer+1) > the_map.cells[x][y].count) |
| | | the_map.cells[x][y].count = layer+1; |
| | | the_map.cells[x][y].need_update = 1; |
| | | the_map.cells[x][y].have_darkness = 1; |
| } | | } |
| | | |
| | | |
| | | void display_map_addbelow(long x,long y,long face) |
| | | { |
| | | |
| | | if( fog_of_war == TRUE) |
| | | { |
| | | x+= pl_pos.x; |
| | | y+= pl_pos.y; |
| } | | } |
| | | |
| | | if( (fog_of_war == TRUE) && (the_map.cells[x][y].cleared == 1) ) |
| | | { |
| | | /* This cell has been cleared previously but now we are |
| | | * writing new data to do. So we have to clear it for real now |
| | | */ |
| | | int i= 0; |
| | | the_map.cells[x][y].count= 0; |
| | | the_map.cells[x][y].darkness= 0; |
| | | the_map.cells[x][y].need_update= 1; |
| | | the_map.cells[x][y].have_darkness= 0; |
| | | the_map.cells[x][y].cleared= 0; |
| | | for (i=0; i<MAXFACES; i++) |
| | | the_map.cells[x][y].faces[i]= -1; /* empty/blank face */ |
| } | | } |
| | | |
| | | the_map.cells[x][y].faces[the_map.cells[x][y].count] = face&0xFFFF; |
| | | the_map.cells[x][y].count ++; |
| | | the_map.cells[x][y].need_update = 1; |
| | | } |
| | | |
| /* | | /* |
| * Returns true if virtual view is about to butt up against | | * Returns true if virtual view is about to butt up against |
| | |
| */ | | */ |
| static int need_recenter_map( int dx, int dy) | | static int need_recenter_map( int dx, int dy) |
| { | | { |
| if( pl_pos.x + dx + use_config[CONFIG_MAPWIDTH] + MAX_MAP_OFFSET >= the_map.x || | | |
| pl_pos.y + dy + use_config[CONFIG_MAPHEIGHT] + MAX_MAP_OFFSET >= the_map.y || | | if( pl_pos.x + dx + mapx >= the_map.x || |
| | | pl_pos.y + dx + mapy >= the_map.y || |
| pl_pos.x + dx <= 0 || | | pl_pos.x + dx <= 0 || |
| pl_pos.y + dy <= 0 ) | | pl_pos.y + dy <= 0 ) |
| { | | { |
| | |
| * virtual maps with large views this could happen before our 0,0 view | | * virtual maps with large views this could happen before our 0,0 view |
| * coordinate is within 1/4 of the edge) we shift to the center. | | * coordinate is within 1/4 of the edge) we shift to the center. |
| */ | | */ |
| if( pl_pos.x <= (map->x/4) || (pl_pos.x +MAX_MAP_OFFSET) >= (map->x*3/4) || | | if( pl_pos.x <= (map->x/4) || pl_pos.x >= (map->x*3/4) || |
| pl_pos.x + use_config[CONFIG_MAPWIDTH] + 1 >= map->x ) | | pl_pos.x + mapx + 1 >= map->x ) |
| { | | { |
| x_shift= map->x/2 - pl_pos.x; | | x_shift= map->x/2 - pl_pos.x; |
| } | | } |
| if( pl_pos.y <= (map->y/4) || (pl_pos.y + MAX_MAP_OFFSET) >= (map->y*3/4) || | | if( pl_pos.y <= (map->y/4) || pl_pos.y >= (map->y*3/4) || |
| pl_pos.y + use_config[CONFIG_MAPHEIGHT] + 1 >= map->y ) | | pl_pos.y + mapy + 1 >= map->y ) |
| { | | { |
| y_shift= map->y/2 - pl_pos.y; | | y_shift= map->y/2 - pl_pos.y; |
| } | | } |
| | |
| void display_mapscroll(int dx,int dy) | | void display_mapscroll(int dx,int dy) |
| { | | { |
| int x,y; | | int x,y; |
| | | static struct Map newmap; |
| int local_mapx= 0, local_mapy= 0; | | int local_mapx= 0, local_mapy= 0; |
| | | |
| | | if( fog_of_war == TRUE) |
| | | { |
| /* We don't need to memcopy any of this stuff around cause | | /* We don't need to memcopy any of this stuff around cause |
| * we are keeping it in memory. We do need to update our | | * we are keeping it in memory. We do need to update our |
| * virtual position though | | * virtual position though |
| */ | | */ |
| | | |
| if( need_recenter_map( dx, dy) == TRUE) | | if( need_recenter_map( dx, dy) == TRUE) |
| | | { |
| recenter_virtual_map_view( &the_map); | | recenter_virtual_map_view( &the_map); |
| | | } |
| | | |
| pl_pos.x+= dx; | | pl_pos.x+= dx; |
| pl_pos.y+= dy; | | pl_pos.y+= dy; |
| local_mapx= pl_pos.x + use_config[CONFIG_MAPWIDTH]; | | local_mapx= pl_pos.x + mapx; |
| local_mapy= pl_pos.y + use_config[CONFIG_MAPHEIGHT]; | | local_mapy= pl_pos.y + mapy; |
| | | |
| /* | | /* |
| * For cells about to enter the view, mark them as | | * For cells about to enter the view, mark them as |
| | |
| * the image data around. This is needed for proper | | * the image data around. This is needed for proper |
| * drawing of blank or black tiles coming into view | | * drawing of blank or black tiles coming into view |
| */ | | */ |
| for( x= pl_pos.x; x < pl_pos.x + use_config[CONFIG_MAPWIDTH]; x++) { | | for( x= pl_pos.x; x < pl_pos.x + mapx; x++) { |
| for( y= pl_pos.y; y < pl_pos.y + use_config[CONFIG_MAPHEIGHT]; y++) { | | for( y= pl_pos.y; y < pl_pos.y + mapy; y++) { |
| the_map.cells[x][y].need_update= 1; | | if( (x + dx) < pl_pos.x || (x + dx) >= (mapx + pl_pos.x) || |
| if( (x + dx) < pl_pos.x || (x + dx) >= (use_config[CONFIG_MAPWIDTH] + pl_pos.x) || | | (y + dy) < pl_pos.y || (y + dy) >= (mapy + pl_pos.y) ) |
| (y + dy) < pl_pos.y || (y + dy) >= (use_config[CONFIG_MAPHEIGHT] + pl_pos.y) ) | | { |
| | | if( x < 0 || y < 0 || x >= the_map.x || |
| | | y >= the_map.y) |
| { | | { |
| if( x < 0 || y < 0 || x >= the_map.x || y >= the_map.y) | | |
| continue; | | continue; |
| | | } |
| | | |
| the_map.cells[x][y].cleared= 1; | | |
| the_map.cells[x][y].need_update= 1; | | the_map.cells[x][y].need_update= 1; |
| the_map.cells[x][y].keephead = 1;/*otherwise we will also mark the multipart as cleared*/ | | the_map.cells[x][y].cleared= 1; |
| } | | } |
| } /* for y */ | | } /* for y */ |
| } /* for x */ | | } /* for x */ |
| | | } |
| | | else |
| | | { |
| | | local_mapx= mapx; |
| | | local_mapy= mapy; |
| | | } |
| | | |
| | | if( newmap.cells == NULL) |
| | | allocate_map( &newmap, map_size, map_size); |
| | | |
| | | /* Check to see if map_size changed since we allocated newmap */ |
| | | if( newmap.x != map_size) |
| | | { |
| | | if( newmap.cells) |
| | | free( newmap.cells); |
| | | |
| | | allocate_map( &newmap, map_size, map_size); |
| | | } |
| | | |
| | | if( fog_of_war == FALSE) { |
| | | for(x=0;x<mapx;x++) { |
| | | for(y=0;y<mapy;y++) { |
| | | /* In case its own of range, set the count to zero */ |
| | | if (x+dx < 0 || x+dx >= mapx ||y+dy < 0 || y+dy >= mapy) { |
| | | memset((char*)&newmap.cells[x][y], 0, sizeof(struct MapCell)); |
| | | #ifdef GDK_XUTIL |
| | | /* basically, if using pngximage, don't want to update it, |
| | | * since the scrolling below will effectively take care of |
| | | * our redraw |
| | | * |
| | | * Changed my smacfiggen 6/20/2001 -- When new cells come onto |
| | | * the map and we aren't using the new map command we want to |
| | | * mark these as updated or else blank tiles get blitted with |
| | | * old info. |
| | | * |
| | | */ |
| | | if ( !map1cmd) |
| | | newmap.cells[x][y].need_update=1; |
| | | #else |
| | | newmap.cells[x][y].need_update=1; |
| | | #endif |
| | | |
| | | } else { |
| | | memcpy((char*)&(newmap.cells[x][y]), (char*)&(the_map.cells[x+dx][y+dy]), |
| | | sizeof(struct MapCell)); |
| | | #ifdef GDK_XUTIL |
| | | /* if using pngximage, we will instead set the map_did_scroll |
| | | * to 1 - we don't want to regen the backing image |
| | | */ |
| | | if (!pngximage) { |
| | | #ifdef HAVE_SDL |
| | | if( !sdlimage) |
| | | #endif |
| | | newmap.cells[x][y].need_update=1; |
| | | } |
| | | #else |
| | | newmap.cells[x][y].need_update=1; /* new space needs to be redrawn */ |
| | | #endif |
| | | } |
| | | } |
| | | } |
| | | memcpy((char*)the_map.cells[0],(char*)newmap.cells[0], |
| | | sizeof(struct MapCell)*newmap.x*newmap.y ); |
| | | } |
| | | #ifdef GDK_XUTIL |
| | | if (pngximage ) { |
| | | /* move the screen data around - this is more efficient than re-calculating it all |
| | | * memmove does support moving around overlapping data, so this is safe. |
| | | * |
| | | */ |
| | | if (dy<0) { |
| | | int offset = -dy * mapx * image_size * image_size * BPP; |
| | | memmove(screen +offset, screen, mapx * (mapy + dy)* image_size * image_size * BPP); |
| | | } else if (dy>0) { |
| | | int offset = dy * mapx * image_size * image_size * BPP; |
| | | memmove(screen, screen + offset, mapx * (mapy + dy)* image_size * image_size * BPP); |
| | | } |
| | | if (dx) { |
| | | int y; |
| | | |
| | | for (y=0; y < mapy * image_size; y++) { |
| | | if (dx<0) |
| | | /* -dx because dx is already negative, so this effective adds */ |
| | | memmove(screen + y * mapx * image_size * BPP - dx * image_size * BPP, |
| | | screen + y * mapx * image_size * BPP, |
| | | (mapx + dx) * image_size * BPP); |
| | | else /* dx is positive */ |
| | | memmove(screen + y * mapx * image_size * BPP, |
| | | screen + y * mapx * image_size * BPP + dx * image_size * BPP, |
| | | (mapx - dx) * image_size * BPP); |
| | | } |
| | | } |
| | | map_did_scroll=1; |
| | | } |
| | | #ifdef HAVE_SDL |
| | | if( sdlimage) |
| | | { |
| | | /* a copy of what pngximage does except sdl specfic |
| | | * mapsurface->pitch is the length of a scanline in bytes |
| | | * including alignment padding |
| | | */ |
| | | |
| | | SDL_LockSurface( mapsurface); |
| | | if( dy < 0) |
| | | { |
| | | int offset= mapsurface->pitch * (-dy*image_size); |
| | | memmove( mapsurface->pixels + offset, mapsurface->pixels, |
| | | mapsurface->pitch * (mapsurface->h + dy*image_size) ); |
| | | } |
| | | else if( dy > 0) |
| | | { |
| | | int offset= mapsurface->pitch * (dy*image_size); |
| | | memmove( mapsurface->pixels, mapsurface->pixels + offset, |
| | | mapsurface->pitch * (mapsurface->h - dy*image_size) ); |
| | | } |
| | | |
| | | if( dx) |
| | | { |
| | | int y; |
| | | for( y= 0; y < mapsurface->h; y++) |
| | | { |
| | | if( dx < 0) |
| | | { |
| | | char* start_of_row= mapsurface->pixels + mapsurface->pitch * y; |
| | | int offset= ( mapsurface->format->BytesPerPixel * image_size * -dx); |
| | | memmove( start_of_row + offset, start_of_row, |
| | | mapsurface->pitch - offset); |
| | | } |
| | | else |
| | | { |
| | | char* start_of_row= mapsurface->pixels + mapsurface->pitch * y; |
| | | int offset= ( mapsurface->format->BytesPerPixel * image_size * dx); |
| | | memmove( start_of_row, start_of_row + offset, |
| | | mapsurface->pitch - offset); |
| | | } |
| | | } |
| | | } |
| | | SDL_UnlockSurface( mapsurface); |
| | | |
| | | map_did_scroll= 1; |
| | | } |
| | | |
| | | #endif /* HAVE_SDL */ |
| | | |
| | | /* fprintf(stderr,"scroll command: %d %d\n", dx, dy);*/ |
| | | #endif |
| } | | } |
| | | |
| | | |
| | |
| */ | | */ |
| void reset_map_data() | | void reset_map_data() |
| { | | { |
| | | if( fog_of_war == TRUE) |
| | | { |
| int x= 0; | | int x= 0; |
| int y= 0; | | int y= 0; |
| | | |
| pl_pos.x= the_map.x/2; | | pl_pos.x= the_map.x/2; |
| pl_pos.y= the_map.y/2; | | pl_pos.y= the_map.y/2; |
| memset( the_map.cells[0], 0, | | memset( the_map.cells[0], 0, |
| sizeof( struct MapCell) * the_map.x * the_map.y); | | sizeof( struct MapCell) * the_map.x * the_map.y); |
| for( x= pl_pos.x; x < (pl_pos.x + use_config[CONFIG_MAPWIDTH]); x++) | | for( x= pl_pos.x; x < (pl_pos.x + mapx); x++) |
| { | | { |
| for( y= pl_pos.y; y < (pl_pos.y + use_config[CONFIG_MAPHEIGHT]); y++) | | for( y= pl_pos.y; y < (pl_pos.y + mapy); y++) |
| { | | { |
| the_map.cells[x][y].need_update= 1; | | the_map.cells[x][y].need_update= 1; |
| } | | } |
| } | | } |
| } | | } |
| | | else |
| | | { |
| | | int x= 0; |
| | | int y= 0; |
| | | memset( the_map.cells[0], 0, |
| | | sizeof( struct MapCell) * the_map.x * the_map.y); |
| | | for( x= 0; x < mapx; x++) |
| | | { |
| | | for( y= 0; y < mapy; y++) |
| | | { |
| | | the_map.cells[x][y].need_update= 1; |
| | | } |
| | | } |
| | | } |
| | | } |