[crossfire] [PATCH (big)] Basic X11 client overhaul
Edgar Toernig
froese at gmx.de
Sun Mar 12 12:21:42 CST 2006
Hi all!
The standard font in the basic X11 client (8x13) was too small
for my taste and when trying to use a bigger one I noticed, that
this is not really supported. I decided to fix that.
What started as a simple patch to support arbitrary font sizes
became a major overhaul of the drawing routines of clclient.
The resulting features: arbitrary font sizes, proper window
resizing, dedicated input box with history, non-square map
sizes, sorted resistancies/skills, X11 window classes, and a
couple of minor tweaks. On the way I cleaned up the code a
little bit.
As far as I can tell, the only lost feature is the non-scrolling
info window. The patch shouldn't break anything - if it does,
holler.
Sorry that the patch got that big.
Ciao, ET.
PS: At the moment I'm reading the ml via gmane. mailman.metalforge.org
seems to be down.
common/client.c | 10
common/commands.c | 20
common/external.h | 1
common/p_cmd.c | 2
x11/xutil.c | 8
x11/x11.h | 2
x11/x11proto.h | 3
x11/x11.c | 2289 +++++++++++++++++++-------------------------
8 files changed, 1051 insertions(+), 1284 deletions(-)
diff -rup crossfire-client-1.9.0-orig/common/client.c crossfire-client-1.9.0/common/client.c
--- crossfire-client-1.9.0-orig/common/client.c 2006-02-26 08:45:46 +0100
+++ crossfire-client-1.9.0/common/client.c 2006-03-02 02:01:01 +0100
@@ -61,11 +61,11 @@ Client_Player cpl;
ClientSocket csocket;
const char *const resists_name[NUM_RESISTS] = {
-"armor", "magic", "fire", "elec",
-"cold", "conf", "acid", "drain",
-"ghit", "pois", "slow", "para",
-"t undead", "fear", "depl","death",
-"hword", "blind"};
+"Armor", "Magic", "Fire", "Elec",
+"Cold", "Conf", "Acid", "Drain",
+"GhHit", "Pois", "Slow", "Para",
+"TUnd", "Fear", "Depl","Death",
+"HWord", "Blind"};
typedef void (*CmdProc)(unsigned char *, int len);
diff -rup crossfire-client-1.9.0-orig/common/commands.c crossfire-client-1.9.0/common/commands.c
--- crossfire-client-1.9.0-orig/common/commands.c 2006-02-26 08:45:46 +0100
+++ crossfire-client-1.9.0/common/commands.c 2006-03-09 20:06:18 +0100
@@ -442,13 +442,11 @@ void DrawInfoCmd(char *data, int len)
LOG(LOG_WARNING,"common::DrawInfoCmd","got no data");
buf="";
}
- else buf++;
- if (color!=NDI_BLACK)
- draw_color_info(color, buf);
else
- draw_info(buf,NDI_BLACK);
-
+ buf++;
+ draw_info(buf, color);
}
+
TextManager* firstTextManager = NULL;
void setTextManager(int type, ExtTextManager callback){
@@ -634,7 +632,7 @@ void StatsCmd(unsigned char *data, int l
void handle_query (char *data, int len)
{
- char *buf,*cp;
+ char *buf,*cp=0;
uint8 flags = atoi(data);
(void)len; /* __UNUSED__ */
@@ -649,16 +647,16 @@ void handle_query (char *data, int len)
/* The actual text is optional */
buf = strchr(data,' ');
- if (buf) buf++;
/* If we just get passed an empty string, why draw this? */
if (buf) {
- cp = buf;
+ cp = ++buf;
while ((buf=strchr(buf,'\n'))!=NULL) {
*buf++='\0';
draw_info(cp, NDI_BLACK);
cp = buf;
}
+ }
/* Yes/no - don't do anything with it now */
if (flags & CS_QUERY_YESNO) {}
@@ -668,10 +666,10 @@ void handle_query (char *data, int len)
else
cpl.input_state = Reply_Many;
- if (cp) draw_prompt(cp);
- }
+ cpl.input_text[0] = 0;
+ draw_prompt(cp ? cp : "");
- LOG(0,"commands.c","Received query. Input state now %d\n", cpl.input_state);
+ LOG(0,"commands.c","Received query. Input state now %d\n", cpl.input_state);
}
/* Sends a reply to the server. text contains the null terminated
diff -rup crossfire-client-1.9.0-orig/common/external.h crossfire-client-1.9.0/common/external.h
--- crossfire-client-1.9.0-orig/common/external.h 2006-02-19 04:26:53 +0100
+++ crossfire-client-1.9.0/common/external.h 2006-03-09 20:07:33 +0100
@@ -46,7 +46,6 @@ extern void draw_magic_map(void);
/* Info related functions */
extern void draw_info(const char *str, int color);
-extern void draw_color_info(int colr, const char *buf);
extern void draw_prompt(const char *str);
extern void x_set_echo(void);
extern void set_scroll(const char *s);
diff -rup crossfire-client-1.9.0-orig/common/p_cmd.c crossfire-client-1.9.0/common/p_cmd.c
--- crossfire-client-1.9.0-orig/common/p_cmd.c 2006-02-19 04:26:53 +0100
+++ crossfire-client-1.9.0/common/p_cmd.c 2006-03-02 02:01:15 +0100
@@ -405,7 +405,7 @@ static void do_resist(const char * ignor
int i;
char buf[256];
for (i=0; i<NUM_RESISTS; i++) {
- sprintf(buf,"%-20s %+4d",
+ sprintf(buf,"%-10s %+4d",
resists_name[i], cpl.stats.resists[i]);
draw_info(buf, NDI_BLACK);
}
diff -rup crossfire-client-1.9.0-orig/x11/xutil.c crossfire-client-1.9.0/x11/xutil.c
--- crossfire-client-1.9.0-orig/x11/xutil.c 2006-02-26 08:45:47 +0100
+++ crossfire-client-1.9.0/x11/xutil.c 2006-03-12 16:14:23 +0100
@@ -419,7 +419,7 @@ void parse_keybind_line(char *buf, int l
* it may be able to use it in the future. As such, don't throw
* it away, but at least print a warning message.
*/
- if (keycode==0) {
+ if (0) if (keycode==0) {
LOG(LOG_WARNING,"x11::parse_keybind_line","could not convert keysym %s into keycode, ignoring",
buf);
}
@@ -584,9 +584,10 @@ void parse_key(char key, KeyCode keycode
char buf[MAX_BUF];
if (keycode == commandkey && keysym==commandkeysym) {
- draw_prompt(">");
cpl.input_state = Command_Mode;
+ cpl.input_text[0] = 0;
cpl.no_echo=FALSE;
+ draw_prompt(">");
return;
}
if (keycode == firekey[0] || keysym==firekeysym[0] ||
@@ -640,8 +641,7 @@ void parse_key(char key, KeyCode keycode
gtk_entry_set_text(GTK_ENTRY(entrytext),buf);
gtk_widget_grab_focus (GTK_WIDGET(entrytext));
#else
- sprintf(buf,">%s", cpl.input_text);
- draw_prompt(buf);
+ draw_prompt(">");
#endif
return;
}
diff -rup crossfire-client-1.9.0-orig/x11/x11.h crossfire-client-1.9.0/x11/x11.h
--- crossfire-client-1.9.0-orig/x11/x11.h 2005-09-06 08:39:17 +0200
+++ crossfire-client-1.9.0/x11/x11.h 2006-03-07 19:53:13 +0100
@@ -40,7 +40,7 @@ struct PixmapInfo {
extern struct PixmapInfo *pixmaps[MAXPIXMAPNUM];
extern Display *display;
-extern uint8 image_size;
+extern int image_size;
extern Window win_root,win_game;
extern GC gc_game;
extern Colormap colormap;
diff -rup crossfire-client-1.9.0-orig/x11/x11proto.h crossfire-client-1.9.0/x11/x11proto.h
--- crossfire-client-1.9.0-orig/x11/x11proto.h 2006-02-15 09:03:14 +0100
+++ crossfire-client-1.9.0/x11/x11proto.h 2006-03-09 20:07:11 +0100
@@ -15,10 +15,8 @@ extern void SoundCmd(unsigned char *data
extern int error_handler(Display *dp, XErrorEvent *xe);
extern void event_loop(void);
extern void end_windows(void);
-extern void write_ch(char key);
extern void draw_prompt(const char *str);
extern void draw_info(const char *str, int color);
-extern void draw_color_info(int colr, const char *buf);
extern void draw_stats(int redraw);
extern void draw_message_window(int redraw);
extern void open_container(item *op);
@@ -40,7 +38,6 @@ extern void x_set_echo(void);
extern void display_map_doneupdate(int redraw, int notice);
extern int display_mapscroll(int dx, int dy);
extern int associate_cache_entry(Cache_Entry *ce, int pixnum);
-extern void redisplay_stats(void);
extern void display_map_startupdate(void);
extern void draw_magic_map(void);
extern void magic_map_flash_pos(void);
diff -rup crossfire-client-1.9.0-orig/x11/x11.c crossfire-client-1.9.0/x11/x11.c
--- crossfire-client-1.9.0-orig/x11/x11.c 2006-02-26 08:45:47 +0100
+++ crossfire-client-1.9.0/x11/x11.c 2006-03-12 17:57:57 +0100
@@ -37,6 +37,7 @@ const char *rcsid_x11_x11_c =
*/
#define X_PROG_NAME "cfclient"
+#define X_CLASS "CFClient"
/* Most functions in this file are private. Here is a list of
* the global functions:
@@ -83,6 +84,7 @@ const char *rcsid_x11_x11_c =
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include <X11/keysym.h>
#include "mapdata.h"
#include "x11proto.h"
@@ -120,126 +122,137 @@ typedef struct {
GC gc_icon;
GC gc_status;
- uint8 show_icon:1; /* show status icons */
- uint8 show_weight:1; /* show item's weight */
+ int show_icon:1; /* show status icons */
+ int show_weight:1; /* show item's weight */
char format_nw[20]; /* sprintf-format for text (name and weight) */
char format_nwl[20]; /* sprintf-format for text (name, weight, limit) */
char format_n[20]; /* sprintf-format for text (only name) */
- sint16 text_len; /* How wide the text-field is */
- sint16 width; /* How wide the window is in pixels */
- sint16 height; /* How height the window is in pixels */
+ int width; /* How wide the window is in pixels */
+ int height; /* How height the window is in pixels */
- sint16 item_pos; /* The sequence number of the first drawn item */
- sint16 item_used; /* How many items actually drawn. (0 - size) */
+ int item_pos; /* The sequence number of the first drawn item */
+ int item_used; /* How many items actually drawn. (0 - size) */
- sint16 size; /* How many items there is room to display */
- sint16 *faces; /* [size] */
- sint8 *icon1; /* status icon : locked */
- sint8 *icon2; /* status icon : applied / unpaid */
- sint8 *icon3; /* status icon : magic */
- sint8 *icon4; /* status icon : damned / cursed */
+ int size; /* How many items there is room to display */
+ int *faces; /* [size] */
+ char *icon1; /* status icon : locked */
+ char *icon2; /* status icon : applied / unpaid */
+ char *icon3; /* status icon : magic */
+ char *icon4; /* status icon : damned / cursed */
char **names; /* [size][NAME_LEN] */
/* The scrollbar */
- sint16 bar_length; /* the length of scrollbar in pixels */
- sint16 bar_size; /* the current size of scrollbar in pixels */
- sint16 bar_pos; /* the starting position of scrollbar in pixels */
+ int bar_length; /* the length of scrollbar in pixels */
+ int bar_size; /* the current size of scrollbar in pixels */
+ int bar_y; /* the starting position of scrollbar in pixels */
+
inventory_show show_what; /* What to show in inventory */
- uint32 weight_limit; /* Weight limit for this list - used for title */
+ int weight_limit; /* Weight limit for this list - used for title */
} itemlist;
-int noautorepeat = FALSE; /* turn off autorepeat detection */
-
-static char *font_name="8x13", **gargv;
-
-#define SCROLLBAR_WIDTH 16 /* +2+2 for border on each side */
-#define INFOCHARS 50
-#define INFOLINES 36
-/* Perhaps decent defaults, but not quite right */
-static int FONTWIDTH= 8;
-static int FONTHEIGHT= 13;
-#define MAX_INFO_WIDTH 80
-#define MAXNAMELENGTH 50
-
/* What follows is various constants (or calculations) for various
* window sizes.
*/
-/* Width (and height) of the game window */
-#define GAME_WIDTH (image_size * use_config[CONFIG_MAPWIDTH] + 5)
+#define GAP 3 /* spacing between windows */
+#define BW 3 /* internal border width */
+
+#define SCROLLBAR_WIDTH 14 /* total width including border */
+
+/* status bars (+2 for each border) */
+#define BAR_WIDTH 10
+#define BAR_HEIGHT (MSG_HEIGHT - BW - BW - 4)
+#define BAR_TOTAL_WIDTH (FONT_WIDTH + 2 + BAR_WIDTH+4 + FONT_WIDTH)
+
+static int FONT_WIDTH = 8;
+static int FONT_HEIGHT = 13;
+static int FONT_BASE = 13; /* offset from top to baseline - aka ascent */
+
+#define GAME_WIDTH (image_size * use_config[CONFIG_MAPWIDTH])
+#define GAME_HEIGHT (image_size * use_config[CONFIG_MAPHEIGHT])
+
+#define STAT_HEIGHT (BW + 10 * FONT_HEIGHT + BW)
+#define STAT_WIDTH (BW + 29 * FONT_WIDTH + BW)
+
+#define MSG_HEIGHT (BW + 5*FONT_HEIGHT + BW)
+#define MSG_WIDTH (BW + 4*BAR_TOTAL_WIDTH + 16*FONT_WIDTH + BW)
+
+#define INPUT_HEIGHT (1 + BW + FONT_HEIGHT + BW)
+
+#define INFO_WIDTH (BW + 50*FONT_WIDTH + BW)
+#define INFO_HEIGHT (STAT_HEIGHT + GAP + GAME_HEIGHT + GAP + MSG_HEIGHT)
+#define INFO_CHARS 80 /* max chars per line */
-#define STAT_HEIGHT 140
/* Width of the inventory and look window */
-#define INV_WIDTH 300
-/* spacing between windows */
-#define WINDOW_SPACING 3
-/* Height of the master (root) window */
-#define ROOT_HEIGHT 522
+#define INV_WIDTH (BW + image_size + 24 + 21*FONT_WIDTH + BW+SCROLLBAR_WIDTH+BW)
-static int gargc, old_mapx=11, old_mapy=11;
+static int gargc;
+static char **gargv;
+
+static int noautorepeat = FALSE; /* turn off autorepeat detection */
+
+static char *font_name="8x13";
+
+static int old_mapx=11, old_mapy=11;
Display *display;
static Window def_root; /* default root window */
static long def_screen; /* default screen number */
static unsigned long foreground,background;
-Window win_stats,win_message;
-Window win_root,win_game;
+static Window win_stats, win_message;
+Window win_root, win_game;
Colormap colormap;
static XColor discolor[16];
static XFontStruct *font; /* Font loaded to display in the windows */
static XEvent event;
-static XSizeHints messagehint, roothint;
+static XSizeHints roothint;
static Atom wm_delete_window;
/* This struct contains the information to draw 1 line of data. */
typedef struct {
- char *info; /* Actual character data for a line */
- uint8 color; /* Color to draw that line */
+ char text[INFO_CHARS+1]; /* Actual character data for a line */
+ uint8 color; /* Color to draw that line */
} InfoLine;
/* This contains all other information for the info window */
typedef struct {
- uint16 info_chars; /* width in chars of info window */
- uint16 max_info_chars; /* Max value of info_chars */
- uint16 infopos; /* Where in the info arry to put new data */
- uint16 infoline; /* Where on the window to draw the line */
- uint16 scroll_info_window:1; /* True if we should scroll the window */
- uint16 numlines; /* How many have been stored the array */
- uint16 maxlines; /* Maxlines (how large the array below is) */
- uint16 maxdisp; /* How many lines can be displayed at once */
- uint8 lastcolor; /* Last color text was drawn in */
- InfoLine *data; /* An array of lines */
- Window win_info; /* Actual info window */
- GC gc_info; /* GC for this window */
+ int width,height; /* width and height of window (pixels) */
+ int cwidth, cheight;/* width and height in characters */
+ int lines; /* number of lines in line[] */
+ int pos; /* 'current' line in line[], always at bottom of win */
+ InfoLine *line; /* An array of lines */
+
+ Window win; /* Actual info window */
+ GC gc; /* GC for this window */
+
/* The scrollbar */
- sint16 bar_length; /* the max length of scrollbar in pixels */
- sint16 bar_size; /* the current size (length) of scrollbar in pixels */
- sint16 bar_pos; /* the starting position of scrollbar. This is
- * an offset, which is the number of lines from
- * 0 for the text to end out.*/
- sint16 bar_y; /* X starting position of scrollbar */
- uint16 has_scrollbar:1;/* True if there is a scrollbar in the window */
- sint16 width,height; /* Width and height of window */
+ int bar_length; /* the max length of scrollbar in pixels */
+ int bar_pos; /* when bar_pos==pos bar is at the bottom */
+
+ char prompt[INFO_CHARS+1]; /* the current prompt */
} InfoData;
-InfoData infodata = {0, 0, 0, 0, 0, 0, INFOLINES, INFOLINES, NDI_BLACK,
- NULL, 0, 0,0,0,0,0,0,0,0};
+static InfoData info;
-uint8 image_size=24;
+#define HISTORY_SIZE 100 /* number of history lines */
+static struct {
+ int pos;
+ char *line[HISTORY_SIZE];
+} history;
+int image_size=24;
-static char stats_buff[7][600];
struct PixmapInfo *pixmaps[MAXPIXMAPNUM];
+
/* Off the 'free' space in the window, this floating number is the
* portion that the info takes up.
*/
static float info_ratio=0;
-#define INFOLINELEN 500
#define XPMGCS 100
enum {
@@ -262,11 +275,31 @@ static GC gc_copy; /* used for copying
static itemlist look_list, inv_list;
/* Used to know what stats has changed */
-static Stats last_stats = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+static Stats last_stats;
+
+/*********************************************************************/
-/* info win */
-#define INFOCHARS 50
+static void *
+xmalloc(size_t size)
+{
+ void *x;
+ x = malloc(size ? size : 1);
+ if (x)
+ return x;
+ fprintf(stderr, "Not enough memory to allocate %ud bytes\n", size);
+ exit(1);
+}
+
+/* XDrawRectangle draws to x+w/y+h inclusive - not what one expects. */
+#define DrawRectangle(dpy, d, gc, x, y, w, h) \
+ XDrawRectangle((dpy), (d), (gc), (x), (y), (w)-1, (h)-1)
+
+static void
+DrawText(Drawable d, GC gc, int x, int y, const char *str)
+{
+ XDrawImageString(display, d, gc, x, y + FONT_BASE, str, strlen(str));
+}
/* This is the loop that the client goes through once all the
* initialization is done. Basically, it checks for input and
@@ -278,8 +311,6 @@ static Stats last_stats = {0,0,0,0,0,0,0
* check_x_events takes all the events that are waiting.
*/
-extern int maxfd;
-
/* Handle errors. I really needed this when debugging
* the crashes with the big image stuff - I need to know
* what function is causing the crash.
@@ -301,6 +332,7 @@ int error_handler(Display *dp, XErrorEve
void event_loop()
{
fd_set tmp_read;
+ int maxfd;
int pollret;
struct timeval timeout;
@@ -311,7 +343,8 @@ void event_loop()
}
maxfd = csocket.fd + 1;
while (1) {
- if (csocket.fd==-1) return;
+ if (csocket.fd==-1)
+ return;
/* Do a quick check here for better performance */
check_x_events();
@@ -368,7 +401,7 @@ static void gen_draw_face(Drawable where
total++;
mask = pixmaps[face]->mask;
/* Lets see if we can find a stored mask with matching gc */
- for(gcnum=0;gcnum<XPMGCS;gcnum++) {
+ for (gcnum=0;gcnum<XPMGCS;gcnum++) {
if (xpm_masks[gcnum] == mask)
break;
}
@@ -384,7 +417,7 @@ static void gen_draw_face(Drawable where
* at position 0. Thus, the one in the last position was the least
* used entry
*/
- for(i=gcnum-1;i>=0;i--) {
+ for (i=gcnum-1;i>=0;i--) {
xpm_masks[i+1] = xpm_masks[i];
gc_xpm[i+1] = gc_xpm[i];
}
@@ -406,7 +439,7 @@ void end_windows()
XFreeGC(display, gc_game);
XFreeGC(display, gc_copy);
XFreeGC(display, gc_stats);
- XFreeGC(display, infodata.gc_info);
+ XFreeGC(display, info.gc);
XFreeGC(display, inv_list.gc_text);
XFreeGC(display, inv_list.gc_icon);
XFreeGC(display, inv_list.gc_status);
@@ -431,20 +464,18 @@ void end_windows()
static int get_game_display(void) {
XSizeHints gamehint;
+ XClassHint classhint;
int i;
- gamehint.x=INV_WIDTH + WINDOW_SPACING;
- gamehint.y=STAT_HEIGHT + WINDOW_SPACING;
-
- gamehint.width=GAME_WIDTH;
- gamehint.height=gamehint.width;
-
- gamehint.max_width=gamehint.min_width=gamehint.width;
- gamehint.max_height=gamehint.min_height=gamehint.height;
+ gamehint.x = INV_WIDTH + GAP;
+ gamehint.y = STAT_HEIGHT + GAP;
+ gamehint.width = GAME_WIDTH;
+ gamehint.height = GAME_HEIGHT;
gamehint.flags=PPosition | PSize;
+
win_game=XCreateSimpleWindow(display,win_root,
- gamehint.x,gamehint.y,gamehint.width,gamehint.height,2,
- background,foreground);
+ gamehint.x,gamehint.y,gamehint.width,gamehint.height,0,
+ foreground,foreground);
icon=XCreateBitmapFromData(display,win_game,
(_Xconst char *) crossfire_bits,
(unsigned int) crossfire_width, (unsigned int)crossfire_height);
@@ -456,8 +487,11 @@ static int get_game_display(void) {
} else
XSetWindowColormap(display, win_game, colormap);
- XSetStandardProperties(display,win_game,X_PROG_NAME, X_PROG_NAME,
- icon,gargv,gargc, &(gamehint));
+ XSetStandardProperties(display,win_game,"Crossfire - map", "crossmap",
+ icon,gargv,gargc, &gamehint);
+ classhint.res_name = "map";
+ classhint.res_class = X_CLASS;
+ XSetClassHint(display, win_game, &classhint);
gc_game=XCreateGC(display,win_game,0,0);
XSetForeground(display,gc_game,discolor[0].pixel);
@@ -465,7 +499,7 @@ static int get_game_display(void) {
XSetGraphicsExposures(display, gc_game, False);
gc_copy=XCreateGC(display,win_game,0,0);
- XSetGraphicsExposures(display, gc_game, True);
+ XSetGraphicsExposures(display, gc_copy, True);
gc_floor = XCreateGC(display,win_game,0,0);
XSetGraphicsExposures(display, gc_floor, False);
gc_blank = XCreateGC(display,win_game,0,0);
@@ -502,599 +536,300 @@ static int get_game_display(void) {
static int get_info_display(void) {
XSizeHints infohint;
+ XClassHint classhint;
int i;
- /* The following could happen if bad values are given. */
- if (infodata.maxlines<INFOLINES) infodata.maxlines=INFOLINES;
- infohint.x=INV_WIDTH + GAME_WIDTH + WINDOW_SPACING*2;
- infohint.y=0;
- infohint.width=infodata.width=6+INFOCHARS*FONTWIDTH;
- infohint.height=infodata.height=roothint.height;
- infodata.maxdisp = roothint.height/FONTHEIGHT;
-
- infohint.min_width=100;
- infohint.min_height=30;
+ infohint.x = INV_WIDTH + GAP + GAME_WIDTH + GAP;
+ infohint.y = 0;
+ infohint.width = info.width = INFO_WIDTH;
+ infohint.height = info.height = INFO_HEIGHT;
infohint.flags=PPosition | PSize;
- infodata.win_info=XCreateSimpleWindow(display, win_root,
- infohint.x,infohint.y,infohint.width,infohint.height,2,
+
+ info.win=XCreateSimpleWindow(display, win_root,
+ infohint.x,infohint.y,infohint.width,infohint.height,0,
foreground,background);
- XSetWindowColormap(display, infodata.win_info, colormap);
- icon=XCreateBitmapFromData(display,infodata.win_info,
+ XSetWindowColormap(display, info.win, colormap);
+ icon=XCreateBitmapFromData(display,info.win,
(_Xconst char *) crossfire_bits,
(unsigned int) crossfire_width, (unsigned int)crossfire_height);
- XSetStandardProperties(display,infodata.win_info,"Crossfire - text",
+ XSetStandardProperties(display,info.win,"Crossfire - text",
"Crosstext",icon,gargv,gargc,&(infohint));
- infodata.gc_info=XCreateGC(display,infodata.win_info,0,0);
- XSetForeground(display,infodata.gc_info,foreground);
- XSetBackground(display,infodata.gc_info,background);
+ classhint.res_name = "text";
+ classhint.res_class = X_CLASS;
+ XSetClassHint(display, info.win, &classhint);
- XSetFont(display,infodata.gc_info,font->fid);
+ info.gc=XCreateGC(display,info.win,0,0);
+ XSetForeground(display,info.gc,foreground);
+ XSetBackground(display,info.gc,background);
- XSelectInput(display,infodata.win_info,
+ XSetFont(display,info.gc,font->fid);
+
+ XSelectInput(display,info.win,
ButtonPressMask|KeyPressMask|KeyReleaseMask|ExposureMask|
StructureNotifyMask);
- XSetWMProtocols(display, infodata.win_info, &wm_delete_window, 1);
- XMapRaised(display,infodata.win_info);
- if (infodata.maxlines>infodata.maxdisp) infodata.has_scrollbar=1;
- infodata.info_chars = (infohint.width/FONTWIDTH)-1;
- if (infodata.has_scrollbar) infodata.info_chars -=3;
- infodata.max_info_chars=infodata.info_chars;
- infodata.data=(InfoLine *) malloc(sizeof(InfoLine) * infodata.maxlines);
- infodata.bar_length=infodata.height - 8;
- for (i=0; i<infodata.maxlines; i++) {
- infodata.data[i].info = malloc(sizeof(char)* (infodata.info_chars+1));
- infodata.data[i].info[0]='\0';
- infodata.data[i].color=0;
+ XSetWMProtocols(display, info.win, &wm_delete_window, 1);
+ XMapRaised(display,info.win);
+
+ info.bar_length = info.height-BW-BW-INPUT_HEIGHT-4;
+ info.cheight = (info.height-BW-BW-INPUT_HEIGHT) / FONT_HEIGHT;
+ info.cwidth = (info.width-BW-BW-SCROLLBAR_WIDTH-BW)/FONT_WIDTH;
+ if (info.cwidth > INFO_CHARS)
+ info.cwidth = INFO_CHARS;
+
+ if (info.lines < 4*info.cheight)
+ info.lines = 4*info.cheight;
+ info.line = xmalloc(sizeof(InfoLine) * info.lines);
+ for (i=0; i<info.lines; i++) {
+ info.line[i].text[0] = '\0';
+ info.line[i].text[INFO_CHARS] = '\0';
+ info.line[i].color = 0;
}
+ info.pos = info.bar_pos = 0;
return 0;
}
-static void delete_ch(void) {
- if(strlen(cpl.input_text)==0)
- return;
- cpl.input_text[strlen(cpl.input_text)-1] = '\0';
+static int
+DrawInfoText(int y, const char *str)
+{
+ int l = strlen(str);
- /* If not on the first line but backspacing to the front, we need to
- * do some special handling.
- */
- if ((strlen(cpl.input_text)>3) &&
- strlen(infodata.data[infodata.infopos].info)<3) {
- int line=infodata.infopos-1;
- if (line<0) line=infodata.numlines;
- strcpy(infodata.data[infodata.infopos].info,
- infodata.data[line].info);
- infodata.data[infodata.infopos].info[
- strlen(infodata.data[infodata.infopos].info)-1]=0;
- XDrawImageString(display,infodata.win_info,infodata.gc_info,
- FONTWIDTH, (infodata.infoline+1)*FONTHEIGHT,
- infodata.data[infodata.infopos].info,
- strlen(infodata.data[infodata.infopos].info));
- } else {
- infodata.data[infodata.infopos].info[
- strlen(infodata.data[infodata.infopos].info)-1]=0;
- XDrawImageString(display,infodata.win_info,infodata.gc_info,
- (strlen(infodata.data[infodata.infopos].info)+1)*FONTWIDTH,
- (infodata.infoline+1)*FONTHEIGHT," ",1);
- }
+ if (l > info.cwidth) /* clip to avoid overwriting scroll bar */
+ l = info.cwidth;
+ XDrawImageString(display, info.win, info.gc,
+ BW, BW + FONT_BASE + y*FONT_HEIGHT, str, l);
+ return l * FONT_WIDTH;
}
-/* Writes one character to the screen. Used when player is typing
- * stuff we that we want to appear, or used to give prompts.
- */
-
-void write_ch(char key)
+static void
+DrawInput(void)
{
- char c2[2];
+ int x = BW;
+ int y = info.height - BW - FONT_HEIGHT;
+ int width = (info.width - BW - BW) / FONT_WIDTH;
+ const char *str = cpl.input_text;
+ int l1 = strlen(info.prompt);
+ int l2 = strlen(str);
+ int o;
- /* Sort of a gross hack, but this gets it so that we actually put
- * the command into the buffer.
- */
- if (key==13) {
- /* We turn off command mode for the draw_info call, because
- * it has special handling for normal output during command
- * mode; but we do this manually now.
- */
- Input_State old_state = cpl.input_state;
- cpl.input_state = Playing;
- draw_info(infodata.data[infodata.infopos].info,NDI_BLACK);
- cpl.input_state = old_state;
- return;
- }
-
- if (infodata.lastcolor!=NDI_BLACK) {
- XSetForeground(display,infodata.gc_info,discolor[NDI_BLACK].pixel);
- infodata.lastcolor=NDI_BLACK;
- }
-
- if (key == 9) { /* Tab */
- const char *str = complete_command(infodata.data[infodata.infopos].info);
-
- /* +1 so that we keep our > at start of line. Don't
- * recopy the data on top of ourself.
- */
- if (str != (infodata.data[infodata.infopos].info+1)) {
- strcpy(infodata.data[infodata.infopos].info+1, str);
- strcpy(cpl.input_text,str);
- }
- } else {
-
- if ((key < 32 || (unsigned char) key > 127) && key != 8)
- return;
- c2[0] = key;
- c2[1] ='\0';
+ XSetForeground(display,info.gc,discolor[NDI_BLACK].pixel);
+ XDrawLine(display, info.win, info.gc,
+ x, y-BW-1, info.width-BW-1, y-BW-1);
+ if (cpl.input_state != Metaserver_Select &&
+ cpl.input_state != Reply_One &&
+ cpl.input_state != Reply_Many &&
+ cpl.input_state != Command_Mode)
+ goto clear;
- if(key==8||key==127) {
- /* By backspacking enough, let them get out of command mode */
- if (cpl.input_text[0]=='\0' && cpl.input_state==Command_Mode) {
- cpl.input_state=Playing;
- /* Erase the prompt */
- XDrawImageString(display,infodata.win_info,infodata.gc_info,
- FONTWIDTH,(infodata.infoline+1)*FONTHEIGHT," ",1);
- }
- delete_ch();
- return;
- }
- /* Give some leeway here */
- if(strlen(cpl.input_text)>=(MAX_BUF-15))
- return;
-
- strcat(cpl.input_text,c2);
+ if (cpl.no_echo) {
+ static const char noecho[] = "????????????????????????????????????????"
+ "????????????????????????????????????????";
+ if (l2 > sizeof(noecho)-1)
+ l2 = sizeof(noecho)-1;
+ str = noecho + sizeof(noecho)-1 - l2;
}
-
- if(strlen(infodata.data[infodata.infopos].info)>=(infodata.info_chars-2)) {
- /* Draw the currently line and scroll down one */
- /* We turn off command mode for the draw_info call, because
- * it has special handling for normal output during command
- * mode; but we do this manually now.
- */
- cpl.input_state = Playing;
- draw_info(infodata.data[infodata.infopos].info,NDI_BLACK);
- cpl.input_state = Command_Mode;
- infodata.data[infodata.infopos].info[0]=(((strlen(cpl.input_text)/
- infodata.info_chars))%10)+49;
- infodata.data[infodata.infopos].info[1]='>';
- infodata.data[infodata.infopos].info[2]=0;
- XDrawImageString(display,infodata.win_info,infodata.gc_info,
- FONTWIDTH,(infodata.infoline+1)*FONTHEIGHT,
- infodata.data[infodata.infopos].info,
- strlen(infodata.data[infodata.infopos].info));
+ o = l1 + l2 + 1 - width;
+ if (o < 0)
+ o = 0;
+ if (o < l1) {
+ XSetForeground(display, info.gc, discolor[NDI_NAVY].pixel);
+ DrawText(info.win, info.gc, x, y, info.prompt + o);
+ x += (l1 - o) * FONT_WIDTH;
+ o = l1;
}
+ o -= l1;
+ if (o < l2) {
+ XSetForeground(display, info.gc, discolor[NDI_BLACK].pixel);
+ DrawText(info.win, info.gc, x, y, str + o);
+ x += (l2 - o) * FONT_WIDTH;
+ }
+ /*cursor*/
+ XSetForeground(display, info.gc, discolor[NDI_RED].pixel);
+ XFillRectangle(display, info.win, info.gc, x, y, 2, FONT_HEIGHT);
+ x += 2;
- if (key != 9 ) strcat(infodata.data[infodata.infopos].info,(cpl.no_echo? "?": c2));
-
- XDrawImageString(display,infodata.win_info,infodata.gc_info,
- FONTWIDTH,(infodata.infoline+1)*FONTHEIGHT,
- infodata.data[infodata.infopos].info,
- strlen(infodata.data[infodata.infopos].info));
+ clear:
+ XClearArea(display, info.win, x, y, info.width-x, FONT_HEIGHT, False);
}
-
-
-/* This is similar to draw_info below, but doesn't advance to a new
- * line. Generally, queries use this function to draw the prompt for
- * the name, password, etc.
- * This also starts from character position 0. Thus, only 1 call of this
- * per a given line is useful
- */
-
-void draw_prompt(const char *str)
+void
+draw_prompt(const char *str)
{
- if (infodata.lastcolor!=NDI_BLACK) {
- XSetForeground(display,infodata.gc_info,discolor[NDI_BLACK].pixel);
- infodata.lastcolor=NDI_BLACK;
- }
-
- strncpy(infodata.data[infodata.infopos].info,str,infodata.info_chars);
- infodata.data[infodata.infopos].info[infodata.info_chars] = '\0';
- infodata.data[infodata.infopos].color=NDI_BLACK;
- XDrawImageString(display,infodata.win_info,
- infodata.gc_info,FONTWIDTH,(infodata.infoline+1)*FONTHEIGHT,
- infodata.data[infodata.infopos].info,
- strlen(infodata.data[infodata.infopos].info));
+ strncpy(info.prompt, str, INFO_CHARS);
+ info.prompt[INFO_CHARS] = 0;
+ history.pos = 0;
+ DrawInput();
}
-/* If redarew is true, draw the scrollbar no matter what */
-static void draw_info_scrollbar(int redraw)
+static void
+draw_info_scrollbar(int redraw)
{
- static int last_length=0, last_y=0;
+ static int last_size = -1, last_y = -1;
+ int pos, size, y;
- if (!infodata.has_scrollbar) return;
+ pos = info.bar_pos - info.pos - info.cheight;
+ pos = (pos + 2*info.lines) % info.lines;
- if (infodata.numlines <infodata.maxdisp) {
- infodata.bar_size=infodata.bar_length;
- infodata.bar_y=0;
- }
- else {
- infodata.bar_size=infodata.bar_length*infodata.maxdisp/infodata.numlines;
- infodata.bar_y=infodata.bar_length*(infodata.bar_pos-infodata.maxdisp)/infodata.numlines;
- if (infodata.bar_y<0) infodata.bar_y=0;
- }
-/*
- if ((infodata.bar_size+infodata.bar_y)>infodata.bar_length) {
- infodata.bar_y=infodata.bar_length-infodata.bar_size;
- }
-*/
- if (!redraw && last_length==infodata.bar_size && last_y==infodata.bar_y) return;
+ size = (info.bar_length * info.cheight + info.lines-1) / info.lines;
+ y = info.bar_length * pos / info.lines;
- last_y=infodata.bar_y;
- last_length=infodata.bar_size;
+ if (size < 1)
+ size = 1;
- /* Note - with the way this is set up, it wouldn't be too hard to make
- * the scrollbar color customizable
- */
- if (infodata.lastcolor!=NDI_BLACK) {
- XSetForeground(display,infodata.gc_info,discolor[NDI_BLACK].pixel);
- infodata.lastcolor=NDI_BLACK;
- }
-
- XDrawRectangle(display, infodata.win_info,
- infodata.gc_info, infodata.width-SCROLLBAR_WIDTH-6,
- 3, 20,
- infodata.height -6);
- XClearArea(display, infodata.win_info,
- infodata.width-SCROLLBAR_WIDTH-4, 4, 16,
- infodata.bar_length, False);
-
- XFillRectangle(display, infodata.win_info, infodata.gc_info,
- infodata.width - SCROLLBAR_WIDTH-4,4+infodata.bar_y,
- 16, infodata.bar_size);
-}
+ if (!redraw && last_size == size && last_y == y)
+ return;
-/* draw_info adds a line to the info window. */
+ last_y = y;
+ last_size = size;
-void draw_info(const char *str, int color) {
- char *cp;
- uint16 new_infopos = (infodata.infopos+1)% infodata.maxlines ;
+ XSetForeground(display, info.gc, discolor[NDI_BLACK].pixel);
- if(str == (char *) NULL) {
- draw_info("[NULL]",color);
- return;
- }
+ DrawRectangle(display, info.win, info.gc,
+ info.width-BW-SCROLLBAR_WIDTH, BW,
+ SCROLLBAR_WIDTH, info.bar_length+4);
+ XClearArea(display, info.win,
+ info.width-BW-SCROLLBAR_WIDTH+2, BW+2,
+ SCROLLBAR_WIDTH-4, info.bar_length, False);
+
+ XFillRectangle(display, info.win, info.gc,
+ info.width-BW-SCROLLBAR_WIDTH+2, BW+2+y,
+ SCROLLBAR_WIDTH-4, size);
+}
- if((cp=strchr(str,'\n'))!=NULL) {
- /* 4096 is probably way overkill, but 1024 could very well be too small.
- * And I don't see the need to malloc and then free this either -
- * this is a single user program.
- */
- char obuf[4096],*buf = obuf;
+/* draw_info adds a line to the info window. */
- strncpy(buf,str, 4095);
- do {
- if ((cp = strchr(buf, '\n'))) {
- *cp='\0';
- draw_info(buf,color);
- buf = cp +1;
- } else
- draw_info(buf,color);
- } while (cp!=NULL);
- return;
- }
+void
+draw_info(const char *str, int color)
+{
+ char *p, buf[256];
+ InfoLine *lp;
+ int l;
- /* Lets do the word wrap for messages - MSW */
- if ((int)strlen(str) >= infodata.info_chars) {
- int i=infodata.info_chars-1;
-
- /* i=last space (or ')' for armor. Wrap armor, because
- otherwise, the two sets of ()() can be about half the line */
- while ((str[--i]!=' ') && (str[i]!=')') && (i!=0)) ;
- /* if i==0, string has no space. Just let it be truncated */
- if (i!=0) {
- char *buf = (char *)malloc(sizeof(char)*(i+2));
- int j;
-
- i++; /* want to keep the ')'. This also keeps
- the space, but that really doesn't matter */
- strncpy(buf, str, i);
- buf[i]='\0';
- draw_info(buf,color);
- free(buf);
-
- for (j=i; j < (int)strlen(str); j++) /* if the wrap portion is */
- if (str[j]!=' ') break; /* only space, don't wrap it*/
- if ((((strlen(str)-i)!=1) || (str[i]!='.')) && (j!=strlen(str)))
- draw_info((str+i),color);
- return;
+ if (str == NULL)
+ str = "[NULL]";
+
+ /* split lines */
+ while ((p = strchr(str,'\n'))) {
+ if (p - str < sizeof(buf)) {
+ memcpy(buf, str, p - str);
+ buf[p - str] = 0;
+ draw_info(buf, color);
}
- }
-
- /* This is the real code here - stuff above is just formating and making
- * it look nice. This stuff here is actually drawing the code
- */
-
- /* clear the new last line in window */
- memset(infodata.data[new_infopos].info, 32, infodata.info_chars-1);
- if(cpl.input_state == Command_Mode)
- {
- /* we copy the last command line to the new last line in window */
- strcpy(infodata.data[new_infopos].info, infodata.data[infodata.infopos].info);
- }
- infodata.data[new_infopos].info[infodata.info_chars] = '\0';
-
- strncpy(infodata.data[infodata.infopos].info,str,infodata.info_chars);
- infodata.data[infodata.infopos].info[infodata.info_chars] = '\0';
- infodata.data[infodata.infopos].color=color;
-
- /* This area is for scrollbar handling. The first check is to see if
- * the scrollbar is at the very end, if it is, then we don't care about this.
- * IF not at the end, then see if it is at the end of the window. If
- * so, increase the bar position so that that view area keeps up with what
- * is being drawn. If we are not at the end of the buffer, then decrease
- * the bar position - in this way, we keep the same viewable area visible
- * for redraws.
- *
- * A couple notes: If jump to end was desired on output, then this
- * code just needs to be replaced with a line like infodata.bar_pos=
- * infodata.numlines.
- * If it is desired for the window to scroll up as new output is printed
- * out, then the second case would need to be removed, and a draw_all_info
- * call added instead.
- */
- if (infodata.bar_pos<infodata.maxlines) {
- if (infodata.bar_pos==infodata.numlines) {
- infodata.bar_pos++;
- }
- else if (infodata.numlines==infodata.maxlines) {
- infodata.bar_pos--;
- if (infodata.bar_pos<infodata.maxdisp)
- infodata.bar_pos=infodata.maxdisp;
- }
- }
- if (infodata.numlines<infodata.maxlines) infodata.numlines++;
-
- /* Basically, if we don't have a scrollbar, or we are at the end of it,
- * then do the drawing stuff, otherwise don't.
- */
- if (!infodata.has_scrollbar || infodata.bar_pos>=infodata.numlines) {
- /*
- * The XDrawImageString draws the line.
- */
- if (infodata.lastcolor!=color) {
- XSetForeground(display,infodata.gc_info,discolor[color].pixel);
- infodata.lastcolor=color;
+ str = p + 1;
}
-
- XDrawImageString(display,infodata.win_info,
- infodata.gc_info,FONTWIDTH,(infodata.infoline+1)*FONTHEIGHT,
- infodata.data[infodata.infopos].info,
- strlen(infodata.data[infodata.infopos].info));
- /* Now it gets potentially more complicated - now we have to handle
- * wrapping and stuff like that.
- */
+ /* word wrap */
+ while (strlen(str) > info.cwidth) {
+ int i = info.cwidth;
- if(++(infodata.infoline)>=infodata.maxdisp){
- if (infodata.scroll_info_window) {
- XCopyArea(display,infodata.win_info,infodata.win_info,
- infodata.gc_info,0,FONTHEIGHT,infodata.info_chars*FONTWIDTH,
- infodata.maxdisp*FONTHEIGHT,0,0);
- infodata.infoline--;
- }
- else
- infodata.infoline=0;
- }
- }
+ /* split at last ' ' or ')' */
+ while (i && str[i] != ' ' && str[i-1] != ')')
+ i--;
- infodata.infopos = new_infopos;
+ if (i == 0) /* no split point -> hard break */
+ i = info.cwidth;
- if (!infodata.has_scrollbar || infodata.bar_pos>=infodata.numlines) {
- if(cpl.input_state == Command_Mode)
- {
- uint8 endpos = strlen(infodata.data[infodata.infopos].info);
-
- infodata.data[infodata.infopos].info[endpos] = ' ';
- XDrawImageString(display,infodata.win_info,
- infodata.gc_info,FONTWIDTH,(infodata.infoline+1)*FONTHEIGHT,
- infodata.data[infodata.infopos].info, infodata.info_chars-1);
- infodata.data[infodata.infopos].info[endpos] = '\0';
- }
- else
- {
- XDrawImageString(display,infodata.win_info,
- infodata.gc_info,FONTWIDTH,(infodata.infoline+1)*FONTHEIGHT,
- infodata.data[infodata.infopos].info, infodata.info_chars-1);
- }
- }
-
- /* If in a reply state, grab the input buffer and store it.
- */
- if (cpl.input_state==Reply_Many) {
- strncpy(infodata.data[infodata.infopos].info, cpl.input_text,
- infodata.info_chars);
- infodata.data[infodata.infopos].info[infodata.info_chars] = '\0';
-
- XDrawImageString(display,infodata.win_info,infodata.gc_info,
- FONTWIDTH,(infodata.infoline+1)*FONTHEIGHT,
- infodata.data[infodata.infopos].info,
- strlen(infodata.data[infodata.infopos].info));
- }
- /* We should have some intelligent checks so it is not drawn unnecessarily */
- draw_info_scrollbar(FALSE);
-}
+ if (i < sizeof(buf)) {
+ memcpy(buf, str, i);
+ buf[i] = 0;
+ draw_info(buf, color);
+ }
+ str += i;
+ while (*str == ' ')
+ str++;
-/* This is pretty much print_message, but the name is changed, and some
- * unnecessary code has been removed.
- */
+ /* if the rest of the line is empty or only a single '.' abort */
+ if (*str == 0 || (*str == '.' && str[1] == 0))
+ return;
+ }
-void draw_color_info(int colr, const char *buf){
- draw_info(buf,colr);
-}
+ /* This is the real code here - stuff above is just formating and making
+ * it look nice. This stuff here is actually drawing the code
+ */
+ /* insert new line */
+ info.pos = (info.pos + 1) % info.lines;
+ strncpy(info.line[info.pos].text,str,INFO_CHARS);
+ info.line[info.pos].color=color;
+
+ /* adjust scrollbar position */
+ info.bar_pos = (info.bar_pos + 1) % info.lines;
+
+ /* scroll up */
+ XCopyArea(display, info.win, info.win, info.gc,
+ BW, BW+FONT_HEIGHT,
+ info.cwidth*FONT_WIDTH, (info.cheight - 1) * FONT_HEIGHT,
+ BW, BW);
+
+ /* redraw the bottom line */
+ lp = info.line + info.bar_pos;
+ l = strlen(lp->text);
+ if (l < info.cwidth) // have to redraw the whole line, fill it up
+ memset(lp->text + l, ' ', info.cwidth - l);
+ XSetForeground(display, info.gc, discolor[lp->color].pixel);
+ DrawInfoText(info.cheight - 1, lp->text);
+ if (l < info.cwidth)
+ lp->text[l] = 0;
+}
/*
* draw_all_info is only needed for redraws, which includes scrollbar
* movement
*/
+static void
+draw_all_info(void)
+{
+ int i;
-static void draw_all_info(void) {
- int i;
-
- XClearWindow(display,infodata.win_info);
- if (infodata.numlines>=infodata.maxdisp) {
- int startline=infodata.infopos-infodata.maxdisp-
- (infodata.numlines-infodata.bar_pos)+1,displine=0;
-
- if (startline<0) startline+=infodata.maxlines;
-
- /* If we are scrolling back (bar_pos<numlines), then we want to
- * start drawing from the top, and want to keep displine 0.
- */
- if (!infodata.scroll_info_window) {
- if (infodata.bar_pos>=infodata.numlines) {
- displine=(infodata.infoline+1) % infodata.maxdisp;
- /* So that when we now that we have scrolled back */
-
- }
- else infodata.infoline=infodata.maxdisp-1;
- }
+ XClearWindow(display,info.win);
- for (i=0; i<infodata.maxdisp; i++) {
- if (infodata.lastcolor!=infodata.data[startline].color) {
- XSetForeground(display,infodata.gc_info,
- discolor[infodata.data[startline].color].pixel);
- infodata.lastcolor=infodata.data[startline].color;
- }
- XDrawImageString(display,infodata.win_info,
- infodata.gc_info,FONTWIDTH,(displine+1)*FONTHEIGHT,
- infodata.data[startline].info,
- strlen(infodata.data[startline].info));
- startline++;
- startline %= infodata.maxlines;
- displine++;
- displine %= infodata.maxdisp;
- }
- }
- else {
- for(i=0;i<=infodata.numlines;i++) {
- if (infodata.lastcolor!=infodata.data[i].color) {
- XSetForeground(display,infodata.gc_info,
- discolor[infodata.data[i].color].pixel);
- infodata.lastcolor=infodata.data[i].color;
- }
- XDrawImageString(display,infodata.win_info,
- infodata.gc_info,FONTWIDTH,(i+1)*FONTHEIGHT,
- infodata.data[i].info,strlen(infodata.data[i].info));
- }
- }
- draw_info_scrollbar(TRUE);
+ for (i = 0; i < info.cheight; ++i) {
+ InfoLine *lp = info.line + (info.bar_pos - info.cheight + 1 + i
+ + info.lines) % info.lines;
+ XSetForeground(display,info.gc,discolor[lp->color].pixel);
+ DrawInfoText(i, lp->text);
+ }
+ DrawInput();
+ draw_info_scrollbar(TRUE);
}
-static void resize_win_message(int width, int height) {
- messagehint.width = width;
- messagehint.height = height;
-}
static void resize_win_info(int width, int height) {
- int chars=(width/FONTWIDTH)-1;
- int lines=(height/FONTHEIGHT)-1;
- int i;
- InfoLine *newlines;
-
- if (infodata.width==width &&
- infodata.height==height) return;
-
- if(chars<3 || lines<3)
- return;
-
- infodata.width=width;
- infodata.height=height;
- infodata.bar_length=infodata.height - 8;
- if (infodata.has_scrollbar) chars-=3;
-
+ int chars, lines, i;
- /* We have a scrollback buffer. All we need to change then is maxdisp */
- if (infodata.maxdisp != infodata.maxlines && lines<infodata.maxlines) {
- /* Move insert line to bottom of the screen if we are already there
- * or it would otherwise be off the screen.
- */
- if (((infodata.infoline+1) == infodata.maxdisp) ||
- (infodata.infoline >= lines)) infodata.infoline = lines - 1;
- infodata.maxdisp=lines;
- }
- /* The window has changed size, but the amount of data we can display
- * has not. so just redraw the window and return.
- */
- if (chars == infodata.info_chars && lines == infodata.maxdisp) {
- draw_all_info();
- return;
- }
+ if (width < BW + 3*FONT_WIDTH + BW + SCROLLBAR_WIDTH + BW)
+ width = BW + 3*FONT_WIDTH + BW + SCROLLBAR_WIDTH + BW;
+ if (height < BW + 2*FONT_HEIGHT + BW + INPUT_HEIGHT)
+ height = BW + 2*FONT_HEIGHT + BW + INPUT_HEIGHT;
- /* Either we have a scrollbar (as above), or the window has not
- * changed in height, so we just need to change the size of the
- * buffers.
- */
- if (lines == infodata.maxdisp) {
- for (i=0; i<infodata.maxlines; i++) {
- if (chars>infodata.max_info_chars) {
- infodata.data[i].info= realloc(infodata.data[i].info, sizeof(char) * (chars+1));
- }
- /* Terminate buffer in both cases */
- infodata.data[i].info[chars]='\0';
- }
- infodata.info_chars=chars;
- draw_all_info();
+ if (info.width == width && info.height == height)
return;
- }
- /* IF we get here, the window has grown or shrunk, and we don't have
- * a scrollbar. This code is a lot simpler than what was here before,
- * but probably is not as efficient (But with the number of resize
- * events likely, this should not be a big deal).
- */
- /* First, allocate new storage */
- newlines = malloc(sizeof(InfoLine) * lines);
- for (i=0; i<lines; i++) {
- newlines[i].info = malloc(sizeof(char) * (chars +1));
- newlines[i].info[0]='\0';
- newlines[i].color=0;
- }
- /* First case - we can keep all the old data. Note that the old
- * buffer could have been filled up, so we still need to do some
- * checking to find the start
- */
- if (infodata.numlines <= lines) {
- int start=0,k;
-
- /* Buffer was full, so the start could be someplace else */
- if (infodata.numlines == infodata.maxlines) {
- start = infodata.infopos+1;
- }
- for (i=0; i<infodata.numlines; i++) {
- k= (start+i) % infodata.maxlines;
- strncpy(newlines[i].info, infodata.data[k].info, chars);
- newlines[i].info[chars]=0;
- newlines[i].color = infodata.data[k].color;
+ lines = (height - BW - BW - INPUT_HEIGHT) / FONT_HEIGHT;
+ chars = (width - BW - BW - SCROLLBAR_WIDTH - BW) / FONT_WIDTH;
+ if (chars > INFO_CHARS)
+ chars = INFO_CHARS;
+
+ info.width = width;
+ info.height = height;
+ info.bar_length = height - BW - BW - INPUT_HEIGHT - 4;
+ info.cwidth = chars;
+ info.cheight = lines;
+
+ if (lines > info.lines) { /* grow scrollback buffer */
+ lines *= 4;
+ info.line = realloc(info.line, sizeof(InfoLine) * lines);
+ for (i = info.lines; i < lines; ++i) {
+ info.line[i].text[0] = '\0';
+ info.line[i].text[INFO_CHARS] = '\0';
+ info.line[i].color = 0;
}
+ info.lines = lines;
}
- else {
- /* We have to lose data, so keep the most recent. */
- int start=infodata.infopos-lines,k;
-
- if (start<0) start += infodata.maxlines;
- for (i=0; i<lines; i++) {
- k= (start+i) % infodata.maxlines;
- strncpy(newlines[i].info, infodata.data[k].info, chars);
- newlines[i].info[chars]=0;
- newlines[i].color = infodata.data[k].color;
- }
- infodata.infopos = 0;
- newlines[0].info[0] = '\0';
- infodata.infoline = lines-1;
- infodata.numlines = lines;
- infodata.bar_pos = lines;
- }
- infodata.maxdisp = lines;
- for (i=0; i<infodata.maxlines; i++) {
- free(infodata.data[i].info);
- }
- free(infodata.data);
- infodata.data = newlines;
- infodata.maxlines = lines;
- infodata.info_chars=chars;
draw_all_info();
}
@@ -1109,16 +844,16 @@ static void resize_win_info(int width, i
static int get_stats_display(void) {
XSizeHints stathint;
+ XClassHint classhint;
- stathint.x=INV_WIDTH + WINDOW_SPACING;
- stathint.y=0;
- stathint.width=GAME_WIDTH;
- stathint.height=STAT_HEIGHT;
- stathint.min_width=stathint.max_width=stathint.width;
- stathint.min_height=stathint.max_height=stathint.height;
+ stathint.x = INV_WIDTH + GAP;
+ stathint.y = 0;
+ stathint.width = STAT_WIDTH;
+ stathint.height = STAT_HEIGHT;
stathint.flags=PPosition | PSize;
+
win_stats=XCreateSimpleWindow(display,win_root,
- stathint.x,stathint.y,stathint.width,stathint.height,2,
+ stathint.x,stathint.y,stathint.width,stathint.height,0,
foreground,background);
XSetWindowColormap(display, win_stats, colormap);
icon=XCreateBitmapFromData(display,win_stats,
@@ -1126,6 +861,9 @@ static int get_stats_display(void) {
(unsigned int) crossfire_width, (unsigned int)crossfire_height);
XSetStandardProperties(display,win_stats,"Crossfire - status",
"crosstatus",icon,gargv,gargc, &(stathint));
+ classhint.res_name = "status";
+ classhint.res_class = X_CLASS;
+ XSetClassHint(display, win_stats, &classhint);
gc_stats=XCreateGC(display,win_stats,0,0);
XSetForeground(display,gc_stats,foreground);
@@ -1137,6 +875,25 @@ static int get_stats_display(void) {
return 0;
}
+static int
+sort_skills(const void *_a, const void *_b)
+{
+ int a = *(int *)_a;
+ int b = *(int *)_b;
+ int x;
+
+ x = cpl.stats.skill_exp[b] - cpl.stats.skill_exp[a];
+ if (x == 0)
+ x = strcasecmp(skill_names[a], skill_names[b]);
+ return x;
+}
+
+static void
+DrawStatText(int y, const char *str)
+{
+ DrawText(win_stats, gc_stats, BW, BW + y*FONT_HEIGHT, str);
+}
+
/* This draws the stats window. If redraw is true, it means
* we need to redraw the entire thing, and not just do an
* updated.
@@ -1148,40 +905,35 @@ void draw_stats(int redraw) {
int i;
char *s;
- if (strcmp(cpl.title, last_name) || redraw) {
+ if (redraw || strcmp(cpl.title, last_name)) {
strcpy(last_name,cpl.title);
strcpy(buff,cpl.title);
strcat(buff," ");
- XDrawImageString(display,win_stats,
- gc_stats,10,10, buff,strlen(buff));
+ DrawStatText(0, buff);
}
- if(redraw || cpl.stats.exp!=last_stats.exp ||
+ if (redraw || cpl.stats.exp!=last_stats.exp ||
cpl.stats.level!=last_stats.level) {
- sprintf(buff,"Score: %5lld Level: %d",cpl.stats.exp,
- cpl.stats.level);
- strcat(buff," ");
- XDrawImageString(display,win_stats,
- gc_stats,10,24, buff,strlen(buff));
+ sprintf(buff,"Score: %lld Level: %d ",
+ cpl.stats.exp, cpl.stats.level);
+ DrawStatText(1, buff);
last_stats.exp = cpl.stats.exp;
last_stats.level = cpl.stats.level;
}
- if(redraw ||
+ if (redraw ||
cpl.stats.hp!=last_stats.hp || cpl.stats.maxhp!=last_stats.maxhp ||
cpl.stats.sp!=last_stats.sp || cpl.stats.maxsp!=last_stats.maxsp ||
cpl.stats.grace!=last_stats.grace ||
cpl.stats.maxgrace!=last_stats.maxgrace) {
- sprintf(buff,"Hp %d/%d Sp %d/%d Gr %d/%d",
+ sprintf(buff,"Hp %d/%d Sp %d/%d Gr %d/%d ",
cpl.stats.hp, cpl.stats.maxhp,
cpl.stats.sp, cpl.stats.maxsp,
cpl.stats.grace, cpl.stats.maxgrace);
- strcat(buff," ");
- XDrawImageString(display,win_stats,
- gc_stats,10,38, buff,strlen(buff));
+ DrawStatText(2, buff);
last_stats.hp=cpl.stats.hp;
last_stats.maxhp=cpl.stats.maxhp;
last_stats.sp=cpl.stats.sp;
@@ -1190,19 +942,17 @@ void draw_stats(int redraw) {
last_stats.maxgrace=cpl.stats.maxgrace;
}
- if(redraw || cpl.stats.Dex!=last_stats.Dex ||
+ if (redraw || cpl.stats.Dex!=last_stats.Dex ||
cpl.stats.Con!=last_stats.Con || cpl.stats.Str!=last_stats.Str ||
cpl.stats.Int!=last_stats.Int || cpl.stats.Wis!=last_stats.Wis ||
cpl.stats.Cha!=last_stats.Cha || cpl.stats.Pow!=last_stats.Pow) {
- sprintf(buff,"S%2d D%2d Co%2d I%2d W%2d P%2d Ch%2d",
+ sprintf(buff,"S%-2d D%-2d Co%-2d I%-2d W%-2d P%-2d Ch%-2d ",
cpl.stats.Str,cpl.stats.Dex,cpl.stats.Con,
cpl.stats.Int,cpl.stats.Wis,cpl.stats.Pow,
cpl.stats.Cha);
- strcat(buff," ");
- XDrawImageString(display,win_stats,
- gc_stats,10,52, buff,strlen(buff));
+ DrawStatText(3, buff);
last_stats.Str=cpl.stats.Str;
last_stats.Con=cpl.stats.Con;
@@ -1213,17 +963,15 @@ void draw_stats(int redraw) {
last_stats.Pow=cpl.stats.Pow;
}
- if(redraw || cpl.stats.wc!=last_stats.wc ||
+ if (redraw || cpl.stats.wc!=last_stats.wc ||
cpl.stats.ac!=last_stats.ac ||
cpl.stats.resists[0]!=last_stats.resists[0] ||
cpl.stats.dam!=last_stats.dam) {
- sprintf(buff,"Wc:%3d Dam:%3d Ac:%3d Arm:%3d",
- cpl.stats.wc,cpl.stats.dam,cpl.stats.ac,
+ sprintf(buff,"Wc:%3d Dam:%3d Ac:%3d Arm:%3d ",
+ cpl.stats.wc, cpl.stats.dam, cpl.stats.ac,
cpl.stats.resists[0]);
- strcat(buff," ");
- XDrawImageString(display,win_stats,
- gc_stats,10,66, buff,strlen(buff));
+ DrawStatText(4, buff);
last_stats.wc=cpl.stats.wc;
last_stats.ac=cpl.stats.ac;
@@ -1231,7 +979,7 @@ void draw_stats(int redraw) {
last_stats.resists[0] = cpl.stats.resists[0];
}
- if(redraw || last_stats.speed!=cpl.stats.speed ||
+ if (redraw || last_stats.speed!=cpl.stats.speed ||
cpl.stats.food!=last_stats.food ||
cpl.stats.weapon_sp != last_stats.weapon_sp) {
/* since both speed and weapon speed have been multiplied by
@@ -1242,28 +990,27 @@ void draw_stats(int redraw) {
double weap_sp;
/* Seems that weapon_sp can be 0 in some cases which caused SIGFPE's */
- if (cpl.stats.weapon_sp ==0) weap_sp = 0;
- else weap_sp = (float) cpl.stats.speed/ ((float)cpl.stats.weapon_sp);
+ if (cpl.stats.weapon_sp == 0)
+ weap_sp = 0;
+ else
+ weap_sp = (float)cpl.stats.speed / (float)cpl.stats.weapon_sp;
/* The following is generating an FPE on alpha systems - changed
* everything to be doubles to see if that might make some
* difference.
*/
- if(cpl.stats.food<100 && (cpl.stats.food&4)) {
- sprintf(buff,"Speed: %3.2f (%1.2f) Food: *%d* HUNGRY!",
- (double)cpl.stats.speed/FLOAT_MULTF,
- weap_sp,cpl.stats.food);
- if (use_config[CONFIG_FOODBEEP] && (cpl.stats.food%4==3)) XBell(display, 0);
+ if (cpl.stats.food<100 && (cpl.stats.food&4)) {
+ sprintf(buff,"Speed: %3.2f (%1.2f) Food: *%d* HUNGRY! ",
+ (double)cpl.stats.speed/FLOAT_MULTF, weap_sp, cpl.stats.food);
+ if (use_config[CONFIG_FOODBEEP] && cpl.stats.food%4==3)
+ XBell(display, 0);
} else {
- sprintf(buff,"Speed: %3.2f (%1.2f) Food: %3d",
- (float)cpl.stats.speed/FLOAT_MULTF,
- weap_sp, cpl.stats.food);
- if (use_config[CONFIG_FOODBEEP] && cpl.stats.food<1) XBell(display,100);
+ sprintf(buff,"Speed: %3.2f (%1.2f) Food: %3d ",
+ (double)cpl.stats.speed/FLOAT_MULTF, weap_sp, cpl.stats.food);
+ if (use_config[CONFIG_FOODBEEP] && cpl.stats.food<1)
+ XBell(display,100);
}
-
- strcat(buff," ");
- XDrawImageString(display,win_stats,
- gc_stats,10,80, buff,strlen(buff));
+ DrawStatText(5, buff);
last_stats.food=cpl.stats.food;
last_stats.speed = cpl.stats.speed;
@@ -1272,45 +1019,44 @@ void draw_stats(int redraw) {
if (redraw || strcmp(cpl.range, last_range)) {
strcpy(last_range, cpl.range);
strcpy(buff,cpl.range);
- strcat(buff," ");
- XDrawImageString(display,win_stats,
- gc_stats,10,94, buff,strlen(buff));
+ strcat(buff," ");
+ DrawStatText(6, buff);
}
- if (redraw) {
+ if (redraw)
i = 0;
- } else {
+ else
for (i=0; i<MAX_SKILL; i++) {
if ((cpl.stats.skill_level[i] != last_stats.skill_level[i] ||
cpl.stats.skill_exp[i] != last_stats.skill_exp[i]) &&
skill_names[i] && cpl.stats.skill_exp[i])
break;
}
- }
if (i < MAX_SKILL) {
- int on_skill=0;
+ int map[MAX_SKILL], n;
+
+ for (i = n = 0; i < MAX_SKILL; ++i)
+ if (skill_names[i] && cpl.stats.skill_exp[i])
+ map[n++] = i;
+ qsort(map, n, sizeof(int), sort_skills);
- *buff = '\0';
s = buff;
- for (i=0; i<MAX_SKILL; i++) {
- if (!skill_names[i] || !cpl.stats.skill_exp[i]) continue;
+ for (i = 0; i < n; ++i) {
+ int j = map[i];
- last_stats.skill_level[i] = cpl.stats.skill_level[i];
- last_stats.skill_exp[i] = cpl.stats.skill_exp[i];
- s += sprintf(s,"%.3s: %7lld (%d) ", skill_names[i], cpl.stats.skill_exp[i],
- cpl.stats.skill_level[i]);
- if ((on_skill % 2) == 1) {
- XDrawImageString(display,win_stats,gc_stats,10,
- 108 + (14 * (on_skill / 2)), buff,strlen(buff));
- *buff = '\0';
+ last_stats.skill_level[j] = cpl.stats.skill_level[j];
+ last_stats.skill_exp[j] = cpl.stats.skill_exp[j];
+ s += sprintf(s,"%c%.2s:%6lld (%d) ",
+ skill_names[j][0] & ~0x20, skill_names[j]+1,
+ cpl.stats.skill_exp[j], cpl.stats.skill_level[j]);
+ if (i & 1) {
+ DrawStatText(7 + i/2, buff);
s = buff;
}
- on_skill++;
}
- if (*buff)
- XDrawImageString(display,win_stats,gc_stats,10,
- 108 + (14 * (on_skill / 2)), buff,strlen(buff));
+ if (i & 1)
+ DrawStatText(7 + i/2, buff);
}
}
@@ -1321,25 +1067,27 @@ void draw_stats(int redraw) {
***********************************************************************/
static int get_message_display(void) {
+ XSizeHints messagehint;
+ XClassHint classhint;
- messagehint.x=INV_WIDTH + WINDOW_SPACING;
- /* Game window is square so we can use the width */
- messagehint.y=GAME_WIDTH + STAT_HEIGHT+WINDOW_SPACING*2;
- messagehint.width=GAME_WIDTH;
- messagehint.height=roothint.height - messagehint.y;
- messagehint.max_width=messagehint.min_width=messagehint.width;
- messagehint.max_height=STAT_HEIGHT;
- messagehint.min_height=messagehint.height;
+ messagehint.x = INV_WIDTH + GAP;
+ messagehint.y = STAT_HEIGHT + GAP + GAME_HEIGHT + GAP;
+ messagehint.width = MSG_WIDTH;
+ messagehint.height = MSG_HEIGHT;
messagehint.flags=PPosition | PSize;
+
win_message=XCreateSimpleWindow(display,win_root,
messagehint.x,messagehint.y,messagehint.width,
- messagehint.height,2,foreground,background);
+ messagehint.height,0,foreground, background);
XSetWindowColormap(display, win_message, colormap);
icon=XCreateBitmapFromData(display,win_message,
(_Xconst char *) crossfire_bits,
(unsigned int) crossfire_width, (unsigned int)crossfire_height);
XSetStandardProperties(display,win_message,"Crossfire - vitals",
- "crossvitals",icon, gargv,gargc,&(messagehint));
+ "crossvitals",icon, gargv,gargc,&messagehint);
+ classhint.res_name = "vitals";
+ classhint.res_class = X_CLASS;
+ XSetClassHint(display, win_message, &classhint);
gc_message=XCreateGC(display,win_message,0,0);
XSetForeground(display,gc_message,foreground);
XSetBackground(display,gc_message,background);
@@ -1351,34 +1099,64 @@ static int get_message_display(void) {
return 0;
}
-static void xwritedown(const char *txt, int x) {
- int y=13;
- for(;*txt!='\0';txt++,y+=13)
- XDrawImageString(display,win_message,
- look_list.gc_text,x,y,txt,1);
+static void resize_win_message(int width, int height) {
}
-#define MAX_BARS_MESSAGE 80
+static void
+draw_stat_bar(int bar_nr, int val, int maxval, int *lastval, int force,
+ char *label)
+{
+ int height = BAR_HEIGHT;
+ int alert = val <= maxval/4;
+ int x = BW + BAR_TOTAL_WIDTH * bar_nr;
+ int y = BW;
+ int h;
+
+ if (val < maxval)
+ height = (val * BAR_HEIGHT) / maxval;
+ if (height < 0)
+ height = 0;
+ if (height == *lastval && !force)
+ return;
+ *lastval = height;
-static void draw_stat_bar(int bar_pos, int height, int is_alert)
-{
- if(height!=MAX_BARS_MESSAGE) /* clear the top of the bar */
- XClearArea(display,win_message, bar_pos, 4,
- 10, MAX_BARS_MESSAGE-height, 0);
+ if (alert)
+ XSetForeground(display,look_list.gc_text, discolor[3].pixel);
- if(height==0) /* empty bar */
- return;
+ h = BAR_HEIGHT - height;
+ if (h)
+ XClearArea(display,win_message,
+ x + FONT_WIDTH+2 + 2, y + 2, BAR_WIDTH, h, 0);
+ if (height)
+ XFillRectangle(display,win_message, look_list.gc_text,
+ x + FONT_WIDTH+2 + 2, y + 2 + h, BAR_WIDTH, height);
+
+ if (alert)
+ XSetForeground(display,look_list.gc_text, foreground);
+
+ if (force) {
+ char buf[2];
+ DrawRectangle(display,win_message, look_list.gc_text,
+ x + FONT_WIDTH+2, y, BAR_WIDTH + 4, BAR_HEIGHT + 4);
+ buf[1] = 0;
+ while ((buf[0] = *label++)) {
+ DrawText(win_message, look_list.gc_text, x, y, buf);
+ y += FONT_BASE+1; //FONT_HEIGHT is too much.
+ }
+ }
+}
+
+static int
+sort_resists(const void *_a, const void *_b)
+{
+ int a = *(int *)_a;
+ int b = *(int *)_b;
+ int x;
- if(is_alert) /* this should have its own gc */
- XSetForeground(display,look_list.gc_text,
- discolor[3].pixel);
-
- XFillRectangle(display,win_message,
- look_list.gc_text, bar_pos, 4+MAX_BARS_MESSAGE-height, 10, height);
-
- if(is_alert)
- XSetForeground(display,look_list.gc_text,
- foreground);
+ x = cpl.stats.resists[b] - cpl.stats.resists[a];
+ if (x == 0)
+ x = strcasecmp(resists_name[a], resists_name[b]);
+ return x;
}
@@ -1387,140 +1165,53 @@ static void draw_stat_bar(int bar_pos, i
*/
void draw_message_window(int redraw) {
- int bar,is_alert,flags;
- static uint16 oldflags=0;
- static uint16 scrollsize_hp=0, scrollsize_sp=0, scrollsize_food=0,
- scrollsize_grace=0;
- static uint8 scrollhp_alert=FALSE, scrollsp_alert=FALSE,
- scrollfood_alert=FALSE, scrollgrace_alert=FALSE;
-
- /* draw hp bar */
- if(cpl.stats.maxhp>0)
- {
- bar=(cpl.stats.hp*MAX_BARS_MESSAGE)/cpl.stats.maxhp;
- if(bar<0)
- bar=0;
- is_alert=(cpl.stats.hp <= cpl.stats.maxhp/4);
- }
- else
- {
- bar=0;
- is_alert=0;
- }
- if (redraw || scrollsize_hp!=bar || scrollhp_alert!=is_alert)
- draw_stat_bar(20, bar, is_alert);
- scrollsize_hp=bar;
- scrollhp_alert=is_alert;
-
- /* draw sp bar. spellpoints can go above max
- * spellpoints via supercharging with the transferrance spell,
- * or taking off items that raise max spellpoints.
- */
- if (cpl.stats.sp>cpl.stats.maxsp)
- bar = MAX_BARS_MESSAGE;
- else
- bar=(cpl.stats.sp*MAX_BARS_MESSAGE)/cpl.stats.maxsp;
- if(bar<0)
- bar=0;
-
- is_alert=(cpl.stats.sp <= cpl.stats.maxsp/4);
-
- if (redraw || scrollsize_sp!=bar || scrollsp_alert!=is_alert)
- draw_stat_bar(60, bar, is_alert);
-
- scrollsize_sp=bar;
- scrollsp_alert=is_alert;
-
- /* draw sp bar. grace can go above max or below min */
- if (cpl.stats.grace>cpl.stats.maxgrace)
- bar = MAX_BARS_MESSAGE;
- else
- bar=(cpl.stats.grace*MAX_BARS_MESSAGE)/cpl.stats.maxgrace;
- if(bar<0)
- bar=0;
-
- is_alert=(cpl.stats.grace <= cpl.stats.maxgrace/4);
-
- if (redraw || scrollsize_grace!=bar || scrollgrace_alert!=is_alert)
- draw_stat_bar(100, bar, is_alert);
-
- scrollsize_grace=bar;
- scrollgrace_alert=is_alert;
-
- /* draw food bar */
- bar=(cpl.stats.food*MAX_BARS_MESSAGE)/999;
- if(bar<0)
- bar=0;
- is_alert=(cpl.stats.food <= 999/4);
-
- if (redraw || scrollsize_food!=bar || scrollfood_alert!=is_alert)
- draw_stat_bar(140, bar, is_alert);
-
- scrollsize_food=bar;
- scrollfood_alert=is_alert;
+ static int oldflags=0;
+ static int hp = -1, sp = -1, gr = -1, food = -1;
+ int flags;
+ int x = BW + 4 * BAR_TOTAL_WIDTH;
+ int y = BW;
+ char buf[64];
+
+ draw_stat_bar(0, cpl.stats.hp, cpl.stats.maxhp, &hp, redraw, "HP");
+ draw_stat_bar(1, cpl.stats.sp, cpl.stats.maxsp, &sp, redraw, "Mana");
+ draw_stat_bar(2, cpl.stats.grace, cpl.stats.maxgrace, &gr, redraw, "Grace");
+ draw_stat_bar(3, cpl.stats.food, 999, &food, redraw, "Food");
flags = cpl.stats.flags;
-
if (cpl.fire_on) flags |= SF_FIREON;
if (cpl.run_on) flags |= SF_RUNON;
-
- if ((flags & SF_FIREON ) != (oldflags & SF_FIREON)) {
- if (flags & SF_FIREON)
- XDrawImageString(display, win_message,
- look_list.gc_text, 180, 15, "Fire On", 7);
- else
- XClearArea(display, win_message,
- 180, 0, 60, 15, False);
- }
- if ((flags & SF_RUNON ) != (oldflags & SF_RUNON)) {
- if (flags & SF_RUNON)
- XDrawImageString(display, win_message,
- look_list.gc_text, 180, 30, "Run On", 6);
- else
- XClearArea(display, win_message,
- 180, 15, 60, 15, False);
+ if (redraw || flags != oldflags) {
+ DrawText(win_message, look_list.gc_text,
+ x + 12*FONT_WIDTH, y,
+ (flags & SF_FIREON) ? "Fire" : " ");
+ DrawText(win_message, look_list.gc_text,
+ x + 12*FONT_WIDTH, y + FONT_HEIGHT,
+ (flags & SF_RUNON) ? "Run" : " ");
+ oldflags = flags;
}
- oldflags = flags;
+
if (redraw || cpl.stats.resist_change) {
- int x=180, y=45,i;
- char buf[40];
+ int i, j, map[NUM_RESISTS];
- cpl.stats.resist_change=0;
- XClearArea(display, win_message, 180, 30, messagehint.width-180, messagehint.height-30, False);
- for (i=0; i<NUM_RESISTS; i++) {
- if (cpl.stats.resists[i]) {
- XDrawImageString(display, win_message,
- look_list.gc_text, x, y, resists_name[i],
- strlen(resists_name[i]));
- sprintf(buf,"%+4d", cpl.stats.resists[i]);
- XDrawImageString(display, win_message,
- look_list.gc_text, x+40, y, buf, strlen(buf));
- y+=15;
- /* Move to the next draw position. If we run
- * out of space, just break out of the function.
- */
- if (y>messagehint.height) break;
- } /* If we have a resistance with value */
- } /* For loop of resistances */
- } /* If we need to draw the resistances */
+ for (i = 0; i < NUM_RESISTS; ++i)
+ map[i] = i;
+ qsort(map, NUM_RESISTS, sizeof(int), sort_resists);
+
+ for (i = 0; i < NUM_RESISTS && cpl.stats.resists[j = map[i]]; ++i) {
+ sprintf(buf, "%-5.5s%+4d", resists_name[j],
+ cpl.stats.resists[j]);
+ DrawText(win_message, look_list.gc_text, x, y, buf);
+ y += FONT_HEIGHT;
+ }
+ XClearArea(display, win_message, x, y, 10*FONT_WIDTH, 999, False);
+ cpl.stats.resist_change = 0;
+ }
}
-static void draw_all_message(void) {
-
+static void draw_all_message(void)
+{
XClearWindow(display,win_message);
- xwritedown("HP",06);
- XDrawRectangle(display,win_message,
- look_list.gc_text,18,2,14,MAX_BARS_MESSAGE+4);
- xwritedown("Mana",46);
- XDrawRectangle(display,win_message,
- look_list.gc_text,58,2,14,MAX_BARS_MESSAGE+4);
- xwritedown("Grace",86);
- XDrawRectangle(display,win_message,
- look_list.gc_text,98,2,14,MAX_BARS_MESSAGE+4);
- xwritedown("Food",126);
- XDrawRectangle(display,win_message,
- look_list.gc_text,138,2,14,MAX_BARS_MESSAGE+4);
draw_message_window(1);
}
@@ -1578,7 +1269,8 @@ static void create_status_icons(void)
int x, y;
GC tmpgc;
- if (hasinit) return;
+ if (hasinit)
+ return;
hasinit=1;
#define CREATEPM(name,data) \
@@ -1619,139 +1311,142 @@ static void create_status_icons(void)
* adjacent dark2 image. dark3 results in diagonal stripes. OTOH, these will
* change depending on the image size.
*/
- if ((x+y) % 2) {
+ if ((x+y) % 2)
XDrawPoint(display, dark1, tmpgc, x, y);
- }
- if ((x+y) %3) {
+ if ((x+y) % 3)
XDrawPoint(display, dark2, tmpgc, x, y);
- }
- if ((x+y) % 4) {
+ if ((x+y) % 4)
XDrawPoint(display, dark3, tmpgc, x, y);
- }
}
}
XFreeGC(display, tmpgc);
}
+
/*
* draw_list redraws changed item to the window and updates a scrollbar
*/
static void draw_list (itemlist *l)
{
- int i, items, size, pos;
+ int i, items, size;
item *tmp;
char buf[MAX_BUF], buf2[MAX_BUF];
+ int y = BW;
/* draw title */
strcpy(buf2, l->title);
if (l->show_what & show_mask) {
- strcat(buf2," (");
- if (l->show_what & show_applied) strcat(buf2,"applied, ");
- if (l->show_what & show_unapplied) strcat(buf2,"unapplied, ");
- if (l->show_what & show_unpaid) strcat(buf2,"unpaid, ");
- if (l->show_what & show_cursed) strcat(buf2,"cursed, ");
- if (l->show_what & show_magical) strcat(buf2,"magical, ");
- if (l->show_what & show_nonmagical) strcat(buf2,"nonmagical, ");
- if (l->show_what & show_locked) strcat(buf2,"locked, ");
- if (l->show_what & show_unlocked) strcat(buf2,"unlocked, ");
+ strcpy(buf2,"(");
+ if (l->show_what & show_applied) strcat(buf2,"applied, ");
+ if (l->show_what & show_unapplied) strcat(buf2,"unapplied, ");
+ if (l->show_what & show_unpaid) strcat(buf2,"unpaid, ");
+ if (l->show_what & show_cursed) strcat(buf2,"cursed, ");
+ if (l->show_what & show_magical) strcat(buf2,"magical, ");
+ if (l->show_what & show_nonmagical) strcat(buf2,"nonmagical, ");
+ if (l->show_what & show_locked) strcat(buf2,"locked, ");
+ if (l->show_what & show_unlocked) strcat(buf2,"unlocked, ");
/* want to kill the comma we put in above. Replace it with the paren */
buf2[strlen(buf2)-2]=')';
buf2[strlen(buf2)-1]='\0';
}
- if(l->env->weight < 0 || l->show_weight == 0)
- sprintf (buf, l->format_n, buf2);
+ if (l->env->weight < 0 || l->show_weight == 0)
+ sprintf(buf, l->format_n, buf2);
else if (!l->weight_limit)
- sprintf (buf, l->format_nw, buf2, l->env->weight);
+ sprintf(buf, l->format_nw, buf2, l->env->weight);
else
- sprintf(buf, l->format_nwl, buf2, l->env->weight,
- l->weight_limit/1000);
+ sprintf(buf, l->format_nwl, buf2, l->env->weight, l->weight_limit);
- if (strcmp (buf, l->old_title)) {
- XCopyPlane(display, icons[l->env->open ? close_icon : no_icon],
- l->win, l->gc_status, 0,0, image_size,13, 2,2, 1);
+ if (strcmp(buf, l->old_title)) {
strcpy (l->old_title, buf);
- XDrawImageString(display, l->win, l->gc_text,
- (l->show_icon ? image_size+24+4 : image_size+4),
- 13, buf, strlen(buf));
+ XCopyPlane(display, icons[l->env->open ? close_icon : no_icon],
+ l->win, l->gc_status, 0,0, 24,13,
+ BW, y + (FONT_HEIGHT-13)/2, 1);
+ DrawText(l->win, l->gc_text,
+ BW + image_size + (l->show_icon ? 24 : 0), y, buf);
}
/* Find how many objects we should draw. */
- for(tmp = l->env->inv, items=0; tmp ;tmp=tmp->next)
- if (show_object(tmp, l->show_what)) items++;
+ for (tmp = l->env->inv, items=0; tmp ;tmp=tmp->next)
+ if (show_object(tmp, l->show_what))
+ items++;
- if(l->item_pos > items - l->size)
+ if (l->item_pos > items - l->size)
l->item_pos = items - l->size;
- if(l->item_pos < 0)
+ if (l->item_pos < 0)
l->item_pos = 0;
/* Fast forward to the appropriate item location */
- for(tmp = l->env->inv, i=l->item_pos; tmp && i; tmp=tmp->next)
- if (show_object(tmp, l->show_what)) i--;
-
- for(i=0; tmp && i < l->size; tmp=tmp->next) {
- if (!show_object(tmp, l->show_what)) continue;
+ for (tmp = l->env->inv, i=l->item_pos; tmp && i; tmp=tmp->next)
+ if (show_object(tmp, l->show_what))
+ i--;
+
+ y += FONT_HEIGHT;
+ for (i=0; tmp && i < l->size; tmp=tmp->next) {
+ if (!show_object(tmp, l->show_what))
+ continue;
/* draw face */
- if(l->faces[i] != tmp->face) {
+ if (l->faces[i] != tmp->face) {
l->faces[i] = tmp->face;
- XClearArea(display, l->win, 4, 16 + image_size * i,
- image_size, image_size, False);
- gen_draw_face (l->win, tmp->face,4, 16 + image_size * i, 0, 0);
+ XClearArea(display, l->win, BW, y, image_size, image_size, False);
+ gen_draw_face(l->win, tmp->face, BW, y, 0, 0);
}
/* draw status icon */
if (l->show_icon) {
- sint8 tmp_icon;
+ int tmp_icon;
tmp_icon = tmp->locked ? locked_icon : no_icon;
if (l->icon1[i] != tmp_icon) {
l->icon1[i] = tmp_icon;
- draw_status_icon (l, image_size+4, 16 + image_size * i, tmp_icon);
+ draw_status_icon(l, BW + image_size, y, tmp_icon);
}
tmp_icon = tmp->applied ? applied_icon :
tmp->unpaid ? unpaid_icon : no_icon;
if (l->icon2[i] != tmp_icon) {
l->icon2[i] = tmp_icon;
- draw_status_icon (l, image_size+4, 22 + image_size * i, tmp_icon);
+ draw_status_icon(l, BW + image_size, y + 6, tmp_icon);
}
tmp_icon = tmp->magical ? magic_icon : no_icon;
if (l->icon3[i] != tmp_icon) {
l->icon3[i] = tmp_icon;
- draw_status_icon (l, image_size+4, 28 + image_size * i, tmp_icon);
+ draw_status_icon(l, BW + image_size, y + 12, tmp_icon);
}
tmp_icon = tmp->damned ? damned_icon :
tmp->cursed ? cursed_icon : no_icon;
if (l->icon4[i] != tmp_icon) {
l->icon4[i] = tmp_icon;
- draw_status_icon (l, image_size+4, 34 + image_size * i, tmp_icon);
+ draw_status_icon(l, BW + image_size, y + 18, tmp_icon);
}
}
/* draw name */
- strcpy (buf2, tmp->d_name);
+ strcpy(buf2, tmp->d_name);
if (l->show_icon == 0)
- strcat (buf2, tmp->flags);
+ strcat(buf2, tmp->flags);
- if(tmp->weight < 0 || l->show_weight == 0)
+ if (tmp->weight < 0 || l->show_weight == 0)
sprintf(buf, l->format_n, buf2);
else
sprintf(buf, l->format_nw, buf2, tmp->nrof * tmp->weight);
- if(!l->names[i] || strcmp(buf, l->names[i])) {
+ if (!l->names[i] || strcmp(buf, l->names[i])) {
copy_name (l->names[i], buf);
- XDrawImageString(display, l->win, l->gc_text,
- (l->show_icon?image_size+24+4:image_size+4),
- 34 + image_size * i, buf, strlen(buf));
+ DrawText(l->win, l->gc_text,
+ BW + image_size + (l->show_icon ? 24 : 0),
+ y + (image_size - FONT_HEIGHT)/2,
+ buf);
}
i++;
+ y += image_size;
}
/* If there are not enough items to fill in the display area,
* then set the unused ares to nothing.
*/
- if(items < l->item_used) {
- XClearArea(display, l->win, 0, 16 + image_size * i, l->width - 23,
- image_size * (l->size - i) , False);
+ if (items < l->item_used) {
+ XClearArea(display, l->win, 0, y,
+ l->width - BW - SCROLLBAR_WIDTH, l->height - y, False);
while (i < l->item_used) {
- copy_name (l->names[i], "");
+ copy_name(l->names[i], "");
l->faces[i] = 0;
l->icon1[i] = l->icon2[i] = l->icon3[i] = l->icon4[i] = 0;
i++;
@@ -1760,21 +1455,22 @@ static void draw_list (itemlist *l)
l->item_used = items > l->size ? l->size : items;
/* draw the scrollbar now */
- if(items < l->size)
+ if (items < l->size)
items = l->size;
size = (long) l->bar_length * l->size / items;
- pos = (long) l->bar_length * l->item_pos / items;
-
- if(l->bar_size != size || pos != l->bar_pos) {
+ y = (long) l->bar_length * l->item_pos / items;
- XClearArea(display, l->win, l->width-20, 17 + l->bar_pos, 16,
- l->bar_size, False);
+ if (l->bar_size != size || y != l->bar_y) {
+ XClearArea(display, l->win,
+ l->width-BW-SCROLLBAR_WIDTH+2, BW+FONT_HEIGHT+2 + l->bar_y,
+ SCROLLBAR_WIDTH-4, l->bar_size, False);
l->bar_size = size;
- l->bar_pos = pos;
+ l->bar_y = y;
- XFillRectangle(display, l->win, l->gc_text, l->width - 20,
- 17 + l->bar_pos, 16, l->bar_size);
+ XFillRectangle(display, l->win, l->gc_text,
+ l->width-BW-SCROLLBAR_WIDTH+2, BW+FONT_HEIGHT+2 + l->bar_y,
+ SCROLLBAR_WIDTH-4, l->bar_size);
}
}
@@ -1788,7 +1484,7 @@ static void draw_all_list(itemlist *l)
strcpy (l->old_title, "");
- for(i=0; i<l->size; i++) {
+ for (i=0; i<l->size; i++) {
copy_name(l->names[i], "");
l->faces[i] = 0;
l->icon1[i] = 0;
@@ -1798,8 +1494,9 @@ static void draw_all_list(itemlist *l)
}
XClearWindow(display, l->win);
- XDrawRectangle(display, l->win, l->gc_text, l->width - 22, 15, 20,
- l->bar_length + 4);
+ DrawRectangle(display, l->win, l->gc_text,
+ l->width - BW - SCROLLBAR_WIDTH, BW + FONT_HEIGHT,
+ SCROLLBAR_WIDTH, l->bar_length + 4);
#if 0
/* Don't reset these - causes window position to reset too often */
@@ -1837,63 +1534,50 @@ void close_container (item *op)
static void resize_list_info(itemlist *l, int w, int h)
{
- int i;
+ int i, len;
- if (l->faces)
- free(l->faces);
- if (l->icon1)
- free(l->icon1);
- if (l->icon2)
- free(l->icon2);
- if (l->icon3)
- free(l->icon3);
- if (l->icon4)
- free(l->icon4);
+ if (w < BW + image_size + 24 + 4*FONT_WIDTH + BW + SCROLLBAR_WIDTH + BW)
+ w = BW + image_size + 24 + 4*FONT_WIDTH + BW + SCROLLBAR_WIDTH + BW;
+ if (h < BW + FONT_HEIGHT + image_size + BW)
+ h = BW + FONT_HEIGHT + image_size + BW;
+
+ free(l->faces);
+ free(l->icon1);
+ free(l->icon2);
+ free(l->icon3);
+ free(l->icon4);
if (l->names) {
for (i=0; i < l->size; i++)
- if (l->names[i])
- free(l->names[i]);
+ free(l->names[i]);
free(l->names);
}
l->width = w;
l->height = h;
- l->size = (l->height - FONTHEIGHT - 8) / image_size;
- l->text_len = (l->width - (l->show_icon ? 84 : 60)) / FONTWIDTH;
- l->bar_length = l->size * image_size;
- sprintf (l->format_nw, "%%-%d.%ds%%6.1f", l->text_len-6, l->text_len-6);
- sprintf (l->format_nwl, "%%-%d.%ds%%6.1f/%%4d", l->text_len-11, l->text_len-11);
- sprintf (l->format_n, "%%-%d.%ds", l->text_len, l->text_len);
+ l->size = (l->height - BW - FONT_HEIGHT - BW) / image_size;
+ l->bar_length = l->size * image_size - 4;
+
+ len = (l->width - BW - image_size - (l->show_icon ? 24 : 0)
+ - BW - SCROLLBAR_WIDTH - BW) / FONT_WIDTH;
+ sprintf(l->format_n, "%%-%d.%ds", len, len);
+ if (len > 6)
+ sprintf(l->format_nw, "%%-%d.%ds%%6.1f", len - 6, len - 6);
+ else
+ strcpy(l->format_nw, l->format_n);
+ if (len > 11)
+ sprintf(l->format_nwl, "%%-%d.%ds%%6.1f/%%4d", len - 11, len - 11);
+ else
+ strcpy(l->format_nwl, l->format_nw);
+
+ l->faces = xmalloc(sizeof(*l->faces) * l->size);
+ l->icon1 = xmalloc(sizeof(*l->icon1) * l->size);
+ l->icon2 = xmalloc(sizeof(*l->icon2) * l->size);
+ l->icon3 = xmalloc(sizeof(*l->icon3) * l->size);
+ l->icon4 = xmalloc(sizeof(*l->icon4) * l->size);
+ l->names = xmalloc(sizeof(*l->names) * l->size);
+
+ for (i=0; i < l->size; i++)
+ l->names[i] = xmalloc(NAME_LEN);
- if ((l->faces = malloc (sizeof (*(l->faces)) * l->size )) == NULL) {
- printf ("Can't allocate memory.\n");
- exit (0);
- }
- if ((l->icon1 = malloc (sizeof (*(l->icon1)) * l->size )) == NULL) {
- printf ("Can't allocate memory.\n");
- exit (0);
- }
- if ((l->icon2 = malloc (sizeof (*(l->icon2)) * l->size )) == NULL) {
- printf ("Can't allocate memory.\n");
- exit (0);
- }
- if ((l->icon3 = malloc (sizeof (*(l->icon3)) * l->size )) == NULL) {
- printf ("Can't allocate memory.\n");
- exit (0);
- }
- if ((l->icon4 = malloc (sizeof (*(l->icon4)) * l->size )) == NULL) {
- printf ("Can't allocate memory.\n");
- exit (0);
- }
- if ((l->names = malloc (sizeof (char *) * l->size )) == NULL) {
- printf ("Can't allocate memory.\n");
- exit (0);
- }
- for (i=0; i < l->size; i++) {
- if ((l->names[i] = malloc (NAME_LEN)) == NULL) {
- printf ("Can't allocate memory.\n");
- exit (0);
- }
- }
draw_all_list(l); /* this also initializes above allocated tables */
}
@@ -1901,6 +1585,7 @@ static void get_list_display(itemlist *l
const char *t, const char *s)
{
XSizeHints hint;
+ XClassHint classhint;
l->faces=NULL;
l->names=NULL;
@@ -1908,17 +1593,19 @@ static void get_list_display(itemlist *l
hint.y = y;
hint.width = w;
hint.height = h;
- hint.min_width = 60 + 10 * FONTWIDTH;
- hint.min_height = FONTHEIGHT + 8 + image_size * 2;
hint.flags = PPosition | PSize;
+
l->win = XCreateSimpleWindow(display, win_root, hint.x, hint.y, hint.width,
- hint.height, 2, foreground, background);
+ hint.height, 0, foreground, background);
XSetWindowColormap(display, l->win, colormap);
icon = XCreateBitmapFromData(display, l->win,
(_Xconst char *) crossfire_bits,
(unsigned int) crossfire_width,
(unsigned int)crossfire_height);
XSetStandardProperties(display, l->win, t, s, icon, gargv, gargc, &(hint));
+ classhint.res_name = (char *)s;
+ classhint.res_class = X_CLASS;
+ XSetClassHint(display, l->win, &classhint);
l->gc_text = XCreateGC (display, l->win, 0, 0);
l->gc_icon = XCreateGC (display, l->win, 0, 0);
l->gc_status = XCreateGC (display, l->win, 0, 0);
@@ -1942,14 +1629,14 @@ static void get_list_display(itemlist *l
static int get_inv_display(void)
{
inv_list.env = cpl.ob;
- strcpy (inv_list.title, ""/*ET: too long: "Inventory:"*/);
+ strcpy (inv_list.title, "Inventory:");
inv_list.show_weight = 1;
inv_list.show_what = show_all;
inv_list.weight_limit=0;
- get_list_display ( &inv_list, 0, 0, INV_WIDTH,
- 2*(roothint.height - WINDOW_SPACING) / 3,
- "Crossfire - inventory",
- "crossinventory");
+ get_list_display( &inv_list, 0, 0,
+ INV_WIDTH,
+ 2*(roothint.height - GAP) / 3,
+ "Crossfire - inventory", "crossinventory");
return 0;
}
@@ -1959,11 +1646,11 @@ static int get_look_display(void)
strcpy (look_list.title, "You see:");
look_list.show_weight = 1;
look_list.show_what = show_all;
- inv_list.weight_limit = 0;
- get_list_display ( &look_list, 0,
- (2*(roothint.height - WINDOW_SPACING) / 3) + WINDOW_SPACING,
+ look_list.weight_limit = 0;
+ get_list_display( &look_list, 0,
+ (2*(roothint.height - GAP) / 3) + GAP,
INV_WIDTH,
- (roothint.height - WINDOW_SPACING) / 3,
+ (roothint.height - GAP) / 3,
"Crossfire - look",
"crosslook");
return 0;
@@ -2009,23 +1696,12 @@ void set_show_weight (const char *s)
void set_weight_limit (uint32 wlim)
{
- inv_list.weight_limit = wlim;
+ inv_list.weight_limit = wlim / 1000;
}
void set_scroll(const char *s)
{
- if (!infodata.scroll_info_window) {
- infodata.scroll_info_window=1;
- if (infodata.numlines>=infodata.maxdisp) {
- infodata.infoline=infodata.maxdisp-1;
- }
- draw_all_info();
- draw_info("Scroll is enabled", NDI_BLACK);
- }
- else {
- draw_info("Scroll is disabled", NDI_BLACK);
- infodata.scroll_info_window=0;
- }
+ draw_info("Scroll cannot be disabled", NDI_BLACK);
}
void set_autorepeat(const char *s)
@@ -2037,7 +1713,7 @@ void set_autorepeat(const char *s)
int get_info_width()
{
- return infodata.info_chars;
+ return info.cwidth;
}
void menu_clear(void)
@@ -2072,7 +1748,9 @@ void item_event_item_changed(item * it)
*/
int sync_display = 0;
-static int get_root_display(char *display_name) {
+static int get_root_display(char *display_name)
+{
+ XClassHint classhint;
char *cp;
display=XOpenDisplay(display_name);
@@ -2118,7 +1796,7 @@ static int get_root_display(char *displa
use_config[CONFIG_ECHO] = FALSE;
}
if ((cp=XGetDefault(display,X_PROG_NAME, "scrollLines"))!=NULL) {
- infodata.maxlines=atoi(cp);
+ info.lines=atoi(cp);
}
if ((cp=XGetDefault(display,X_PROG_NAME,"font")) != NULL) {
font_name = strdup_local(cp);
@@ -2129,29 +1807,24 @@ static int get_root_display(char *displa
fprintf(stderr,"Could not load font %s\n", font_name);
exit(1);
}
- FONTWIDTH=font->max_bounds.width;
- FONTHEIGHT=font->max_bounds.ascent + font->max_bounds.descent;
+ FONT_WIDTH=font->max_bounds.width;
+ FONT_HEIGHT=font->max_bounds.ascent + font->max_bounds.descent;
+ FONT_BASE=font->max_bounds.ascent;
background=WhitePixel(display,def_screen);
foreground=BlackPixel(display,def_screen);
+
roothint.x=0;
roothint.y=0;
- roothint.width=582+6+INFOCHARS*FONTWIDTH;
- roothint.height=ROOT_HEIGHT;
- /* Make up for the extra size of the game window. 88 is
- * 11 tiles * 8 pixels/tile bigger size.
- */
- roothint.width += 88;
- roothint.height+= 88;
- init_pngx_loader(display);
-
- roothint.max_width=roothint.min_width=roothint.width;
- roothint.max_height=roothint.min_height=roothint.height;
+ roothint.width = INV_WIDTH +GAP+ GAME_WIDTH +GAP+ INFO_WIDTH;
+ roothint.height = STAT_HEIGHT +GAP+ GAME_HEIGHT +GAP+ MSG_HEIGHT;
roothint.flags=PSize; /*ET: no PPosition. let window manager handle that. */
- if(!want_config[CONFIG_SPLITWIN]) {
+ init_pngx_loader(display);
+
+ if (!want_config[CONFIG_SPLITWIN]) {
win_root=XCreateSimpleWindow(display,def_root,
- roothint.x,roothint.y,roothint.width,roothint.height,2,
+ roothint.x,roothint.y,roothint.width,roothint.height,0,
background,foreground);
allocate_colors(display, win_root, def_screen, &colormap, discolor);
@@ -2160,8 +1833,11 @@ static int get_root_display(char *displa
icon=XCreateBitmapFromData(display,win_root,
(_Xconst char *) crossfire_bits,
(unsigned int) crossfire_width, (unsigned int)crossfire_height);
- XSetStandardProperties(display,win_root,X_PROG_NAME,X_PROG_NAME,
- icon,gargv,gargc,&(roothint));
+ XSetStandardProperties(display,win_root,"Crossfire X11 Client V"
+ VERSION, "crossfire", icon,gargv,gargc,&roothint);
+ classhint.res_name = "root";
+ classhint.res_class = X_CLASS;
+ XSetClassHint(display, win_root, &classhint);
gc_root=XCreateGC(display,win_root,0,0);
XSetForeground(display,gc_root,foreground);
XSetBackground(display,gc_root,background);
@@ -2169,64 +1845,67 @@ static int get_root_display(char *displa
XSelectInput(display,win_root,KeyPressMask|
KeyReleaseMask|ExposureMask|StructureNotifyMask);
XMapRaised(display,win_root);
- XNextEvent(display,&event); /*ET: this is bogus */
- XSetWMProtocols(display, win_root, &wm_delete_window, 1);
+ XSetWMProtocols(display, win_root, &wm_delete_window, 1);
}
else
win_root = def_root;
return 0;
}
-static void resize_win_root(XEvent *event) {
- int width, inv_width, info_width;
+static void resize_win_root(int width, int height)
+{
+ int info_width, inv_width, inv_height, stat_height, msg_height;
+ int x;
if (want_config[CONFIG_SPLITWIN]) {
fprintf(stderr,"Got a resize root window in split windows mode\n");
return;
}
- /* The middle 3 windows don't really benefit from the resize, so keep
- * them the same size, and use the leftover equally between the left
- * and right windows.
- */
- width = (event->xconfigure.width - GAME_WIDTH -WINDOW_SPACING*2);
- info_width = width * info_ratio;
- inv_width = width - info_width;
-
- /* With png (and 32x32 images), the message window can get scrunched,
- * so lets make it taller if we can - there is no reason not to, as otherwise
- * that space is lost anyways.
- */
- XMoveResizeWindow(display, win_message, inv_width + WINDOW_SPACING,
- GAME_WIDTH + STAT_HEIGHT + WINDOW_SPACING*2, GAME_WIDTH,
- event->xconfigure.height - GAME_WIDTH + STAT_HEIGHT + WINDOW_SPACING*2);
- messagehint.width=GAME_WIDTH;
- messagehint.height=event->xconfigure.height - GAME_WIDTH + STAT_HEIGHT + WINDOW_SPACING*2;
-
- /* These windows just need to be relocated. The y constants are
- * hardcoded - those windows don't really benefit from being resized
- * (actually, no code in place to currently do it), so no reason
- * to get trick with those just now.
- */
-
- XMoveWindow(display, win_game, inv_width + WINDOW_SPACING, STAT_HEIGHT + WINDOW_SPACING);
- XMoveWindow(display, win_stats, inv_width + WINDOW_SPACING, 0);
-
- /* Resize the info window */
- XMoveResizeWindow(display, infodata.win_info,
- inv_width + GAME_WIDTH + WINDOW_SPACING * 2, 0,
- info_width, event->xconfigure.height);
-
-
- /* Resize the inventory, message window */
- XResizeWindow(display, inv_list.win, inv_width,
- 2 * (event->xconfigure.height - WINDOW_SPACING) / 3);
-
-
- XMoveResizeWindow(display, look_list.win, 0,
- (2*(event->xconfigure.height - WINDOW_SPACING) / 3) + WINDOW_SPACING,
- inv_width,
- (event->xconfigure.height - WINDOW_SPACING) / 3);
+ /* some sanity checks to make sure all sizes stay positive */
+ if (width < 6*BW + 2*GAP + GAME_WIDTH + 20*FONT_WIDTH)
+ width = 6*BW + 2*GAP + GAME_WIDTH + 20*FONT_WIDTH;
+ if (height < 2*GAP + STAT_HEIGHT + GAME_HEIGHT)
+ height = 2*GAP + STAT_HEIGHT + GAME_HEIGHT;
+
+ x = width - GAP - GAME_WIDTH - GAP;
+ info_width = x * info_ratio;
+ inv_width = x - info_width;
+
+ x = height - BW - FONT_HEIGHT - BW - GAP - BW - FONT_HEIGHT - BW;
+ inv_height = BW + FONT_HEIGHT + x / image_size * 2/3 * image_size + BW;
+
+ x = height - STAT_HEIGHT - GAP - GAME_HEIGHT - GAP - MSG_HEIGHT;
+ if (x < 0)
+ x = 0;
+ stat_height = STAT_HEIGHT + x / 2;
+
+ msg_height = height - stat_height - GAP - GAME_HEIGHT - GAP;
+ if (msg_height < MSG_HEIGHT)
+ msg_height = MSG_HEIGHT;
+
+ XResizeWindow(display, inv_list.win,
+ inv_width, inv_height);
+
+ XMoveResizeWindow(display, look_list.win,
+ 0, inv_height + GAP,
+ inv_width, height - inv_height - GAP);
+
+ XMoveResizeWindow(display, win_stats,
+ inv_width + GAP, 0,
+ GAME_WIDTH, stat_height);
+
+ XMoveResizeWindow(display, win_game,
+ inv_width + GAP, stat_height + GAP,
+ GAME_WIDTH, GAME_HEIGHT);
+
+ XMoveResizeWindow(display, win_message,
+ inv_width + GAP, GAME_HEIGHT + GAP + stat_height + GAP,
+ GAME_WIDTH, msg_height);
+
+ XMoveResizeWindow(display, info.win,
+ inv_width + GAP + GAME_WIDTH + GAP, 0,
+ info_width, height);
/* The Resize requests will generate events. As such, we don't call
* the resize functions here - the event handler would get those anyways,
@@ -2245,12 +1924,12 @@ static void parse_game_button_press(int
{
int dx, dy, i, xmidl, xmidh, ymidl, ymidh;
- dx = (x-2)/image_size-use_config[CONFIG_MAPWIDTH]/2;
- dy= (y-2)/image_size-use_config[CONFIG_MAPHEIGHT]/2;
- xmidl=(use_config[CONFIG_MAPWIDTH]/2) * image_size;
- xmidh=(use_config[CONFIG_MAPWIDTH]/2 + 1) * image_size;
- ymidl=(use_config[CONFIG_MAPHEIGHT]/2) * image_size;
- ymidh=(use_config[CONFIG_MAPHEIGHT]/2 + 1) * image_size;
+ dx = x/image_size - use_config[CONFIG_MAPWIDTH]/2;
+ dy = y/image_size - use_config[CONFIG_MAPHEIGHT]/2;
+ xmidl = (use_config[CONFIG_MAPWIDTH]/2) * image_size;
+ xmidh = (use_config[CONFIG_MAPWIDTH]/2 + 1) * image_size;
+ ymidl = (use_config[CONFIG_MAPHEIGHT]/2) * image_size;
+ ymidh = (use_config[CONFIG_MAPHEIGHT]/2 + 1) * image_size;
switch (button) {
case 1:
@@ -2258,17 +1937,22 @@ static void parse_game_button_press(int
/* Its unlikely this will happen, but if the window is
* resized, its possible to be out of bounds.
*/
- if(dx<(-use_config[CONFIG_MAPWIDTH]/2)||dx>(use_config[CONFIG_MAPWIDTH]/2)||dy<(-use_config[CONFIG_MAPHEIGHT]/2)||dy>(use_config[CONFIG_MAPHEIGHT]/2)) return;
+ if (dx < -use_config[CONFIG_MAPWIDTH]/2 ||
+ dx > use_config[CONFIG_MAPWIDTH]/2 ||
+ dy < -use_config[CONFIG_MAPHEIGHT]/2 ||
+ dy > use_config[CONFIG_MAPHEIGHT]/2)
+ return;
look_at(dx,dy);
+ break;
}
- break;
case 2:
case 3:
if (x<xmidl)
i = 0;
else if (x>xmidh)
i = 6;
- else i =3;
+ else
+ i = 3;
if (y>ymidh)
i += 2;
@@ -2330,7 +2014,7 @@ static void do_key_press(int repeated)
cpl.showmagic=0;
display_map_doneupdate(TRUE, FALSE);
}
- if(!XLookupString(&event.xkey,text,10, &gkey,NULL)) {
+ if (!XLookupString(&event.xkey,text,10, &gkey,NULL)) {
/*
* This happens quite a bit - most modifier keys (shift, control, etc)
* can not be mapped to a value.
@@ -2343,12 +2027,10 @@ static void do_key_press(int repeated)
}
switch(cpl.input_state) {
case Playing:
- parse_key(text[0],event.xkey.keycode,gkey,repeated);
+ parse_key(text[0] & 0xff, event.xkey.keycode, gkey, repeated);
break;
case Reply_One:
- /* Don't send modifier keys as reply to query. Tries to prevent
- * from getting into the "...state is not ST_PLAYING" state. */
if (text[0]) {
text[1]='\0';
send_reply(text);
@@ -2363,31 +2045,71 @@ static void do_key_press(int repeated)
case Reply_Many:
case Command_Mode:
case Metaserver_Select:
- if (text[0]==13) {
- enum Input_State old_state=cpl.input_state;
- if (cpl.input_state==Metaserver_Select) {
- cpl.input_state=Playing;
- return;
- }
- if (cpl.input_state==Reply_Many)
+ if (text[0] == 13 || text[0] == 10) {
+ if (*cpl.input_text && !cpl.no_echo) /* add to history */
+ if (!history.line[1] || /* but no dups */
+ strcmp(history.line[1], cpl.input_text))
+ {
+ free(history.line[HISTORY_SIZE-1]);
+ memmove(history.line+2, history.line+1,
+ (HISTORY_SIZE-2) * sizeof(char *));
+ history.line[1] = strdup(cpl.input_text);
+ }
+ if (cpl.input_state == Metaserver_Select) {
+ cpl.input_state = Playing;
+ } else if (cpl.input_state == Reply_Many) {
+ cpl.input_state = Playing;
send_reply(cpl.input_text);
- else {
- write_ch(13);
+ } else {
+ cpl.input_state = Playing;
+ draw_info(cpl.input_text, NDI_RED);
extended_command(cpl.input_text);
}
- /* Only set state to playing if the state has otherwise
- * not changed - this check is needed because 'bind
- * changes the state, and we don't want to change to playing
- * again.
- */
- if (old_state==cpl.input_state)
+ cpl.no_echo = 0; /* By default, start echoing thing again */
+ history.pos = 0;
+ } else if (text[0] == 8 || text[0] == 127) {
+ int l = strlen(cpl.input_text);
+ if (l)
+ cpl.input_text[l-1] = 0;
+ else if (cpl.input_state == Command_Mode)
cpl.input_state = Playing;
- cpl.input_text[0]='\0';
- cpl.no_echo=0; /* By default, start echoing thing again */
- }
- else {
- write_ch(text[0]);
+ else
+ XBell(display, 100);
+ } else if (text[0] == 9 && cpl.input_state == Command_Mode) {
+ const char *str = complete_command(cpl.input_text);
+ if (str != cpl.input_text) {
+ strcpy(cpl.input_text, str);
+ strcat(cpl.input_text, " ");
+ } else
+ XBell(display, 100);
+ } else if (text[0] == 27) {
+ cpl.input_text[0] = 0;
+ if (cpl.input_state == Command_Mode)
+ cpl.input_state = Playing;
+ } else if (gkey == XK_Up || text[0] == ('P' & 0x1f)) {
+ if (history.pos == 0) { // save current line
+ free(history.line[0]);
+ history.line[0] = strdup(cpl.input_text);
+ }
+ if (history.pos+1 < HISTORY_SIZE && history.line[history.pos+1])
+ strcpy(cpl.input_text, history.line[++history.pos]);
+ else
+ XBell(display, 100);
+ } else if (gkey == XK_Down || text[0] == ('N' & 0x1f)) {
+ if (history.pos > 0)
+ strcpy(cpl.input_text, history.line[--history.pos]);
+ else
+ XBell(display, 100);
+ } else if (text[0] >= 32 && (text[0] & 0xff) <= 127) {
+ int l = strlen(cpl.input_text);
+ if (l < MAX_BUF - 15) {
+ cpl.input_text[l++] = text[0];
+ cpl.input_text[l] = 0;
+ }
+ else
+ XBell(display, 100);
}
+ DrawInput();
break;
default:
@@ -2398,47 +2120,47 @@ static void do_key_press(int repeated)
static void buttonpress_in_info(XButtonEvent *xbutton)
{
- int y = xbutton->y-16, x=xbutton->x, button = xbutton->button,dy,pos=0;
+ int y = xbutton->y - BW - 2;
+ int x = xbutton->x;
+ int button = xbutton->button;
+ int dy, pos;
- if (!infodata.has_scrollbar)
+ if (button < 4 && x < info.width-BW-SCROLLBAR_WIDTH)
return;
- if (button < 4 && x <= infodata.width-SCROLLBAR_WIDTH-4)
- return;
+ dy = y / FONT_HEIGHT > 0 ? y / FONT_HEIGHT : 1;
- dy = y / FONTHEIGHT > 0 ? y / FONTHEIGHT : 1;
+ pos = (info.pos - info.bar_pos + info.lines) % info.lines;
switch(button) {
case 1:
- pos = infodata.bar_pos - dy;
+ pos += dy;
break;
case 2:
- pos = y * infodata.numlines / infodata.bar_length;
+ pos = info.lines-info.cheight/2 - y * info.lines / info.bar_length;
break;
case 3:
- pos = infodata.bar_pos + dy;
+ pos -= dy;
break;
case 4:
- pos = infodata.bar_pos - 1;
+ pos++;
break;
case 5:
- pos = infodata.bar_pos + 1;
+ pos--;
break;
}
- if (pos<infodata.maxdisp) {
- if (infodata.numlines<infodata.maxdisp)
- pos=infodata.numlines;
- else
- pos=infodata.maxdisp;
- }
- if (pos>infodata.numlines) pos=infodata.numlines;
- if (pos != infodata.bar_pos) {
- infodata.bar_pos = pos;
+ if (pos < 0)
+ pos = 0;
+ if (pos > info.lines - info.cheight)
+ pos = info.lines - info.cheight;
+ pos = (info.pos - pos + info.lines) % info.lines;
+ if (pos != info.bar_pos) {
+ info.bar_pos = pos;
draw_all_info();
}
}
@@ -2454,11 +2176,13 @@ static void buttonpress_in_info(XButtonE
static int buttonpress_in_list (itemlist *l, XButtonEvent *xbutton)
{
item *tmp;
- int y = xbutton->y - 16, x=xbutton->x, button = xbutton->button;
+ int y = xbutton->y - BW - FONT_HEIGHT - 2;
+ int x = xbutton->x;
+ int button = xbutton->button;
int items, pos=0, dy;
if (y < 0 && l->env->open) /* close the sack */
- client_send_apply (l->env->tag);
+ client_send_apply(l->env->tag);
if (y < 0 || y > image_size * l->size)
return 1;
@@ -2473,8 +2197,9 @@ static int buttonpress_in_list (itemlist
return 1;
}
- if (x > l->width-23) { /* scrollbar */
+ if (x >= l->width - BW - SCROLLBAR_WIDTH) { /* scrollbar */
+ y -= 2;
dy = y / image_size > 0 ? y / image_size : 1;
switch(button) {
@@ -2483,7 +2208,7 @@ static int buttonpress_in_list (itemlist
break;
case 2:
- for(tmp=l->env->inv, items=0; tmp; tmp=tmp->next)
+ for (tmp=l->env->inv, items=0; tmp; tmp=tmp->next)
items++;
pos = y * items / l->bar_length;
break;
@@ -2501,9 +2226,11 @@ static int buttonpress_in_list (itemlist
}
pos = l->item_pos + y / image_size;
- for(tmp=l->env->inv, items=0; tmp; tmp=tmp->next) {
- if (show_object(tmp, l->show_what)) items++;
- if (items>pos) break;
+ for (tmp=l->env->inv, items=0; tmp; tmp=tmp->next) {
+ if (show_object(tmp, l->show_what))
+ items++;
+ if (items>pos)
+ break;
}
if (tmp) {
switch(button) {
@@ -2542,23 +2269,15 @@ static int buttonpress_in_list (itemlist
*/
char *get_metaserver()
{
- static char ret_buf[MAX_BUF];
-
cpl.input_state = Metaserver_Select;
+ cpl.input_text[0] = 0;
draw_prompt(":");
while (cpl.input_state == Metaserver_Select) {
check_x_events();
usleep(50000); /* 1/20 sec */
} /* while input state is metaserver select. */
- /* We need to clear out cpl.input_text - otherwise the next
- * long input (like player name) won't work right.
- * so copy it to a private buffer and return.
- */
- strncpy(ret_buf, cpl.input_text, MAX_BUF-1);
- ret_buf[MAX_BUF-1]=0;
- cpl.input_text[0]=0;
- return ret_buf;
+ return cpl.input_text;
}
@@ -2592,7 +2311,8 @@ void check_x_events() {
if (want_config[CONFIG_CACHE] && lastupdate>5 && newimages) {
update_icons_list(&inv_list);
update_icons_list(&look_list);
- if (!cpl.showmagic) display_map_doneupdate(TRUE, FALSE);
+ if (!cpl.showmagic)
+ display_map_doneupdate(TRUE, FALSE);
newimages=0;
lastupdate=0;
}
@@ -2609,53 +2329,64 @@ void check_x_events() {
XNextEvent(display,&event);
switch(event.type) {
- case ConfigureNotify:
- if(event.xconfigure.window==infodata.win_info)
- resize_win_info(event.xconfigure.width, event.xconfigure.height);
- else if(event.xconfigure.window==inv_list.win)
- resize_list_info(&inv_list, event.xconfigure.width,
- event.xconfigure.height);
- else if(event.xconfigure.window==look_list.win)
- resize_list_info(&look_list, event.xconfigure.width,
- event.xconfigure.height);
- else if(event.xconfigure.window==win_root)
- resize_win_root(&event);
- else if(event.xconfigure.window==win_message)
- resize_win_message(event.xconfigure.width, event.xconfigure.height);
+ case ConfigureNotify: {
+ int win = event.xconfigure.window;
+ int w = event.xconfigure.width;
+ int h = event.xconfigure.height;
+
+ if (win == info.win)
+ resize_win_info(w, h);
+ else if (win == inv_list.win)
+ resize_list_info(&inv_list, w, h);
+ else if (win == look_list.win)
+ resize_list_info(&look_list, w, h);
+ else if (win == win_root)
+ resize_win_root(w, h);
+ else if (win == win_message)
+ resize_win_message(w, h);
break;
-
- case Expose:
- /* No point redrawing windows if there are more Expose's to
- * come.
- */
- if (event.xexpose.count!=0) continue;
- if(event.xexpose.window==win_stats) {
- XClearWindow(display,win_stats);
- draw_stats(1);
- } else if(event.xexpose.window==infodata.win_info)
- draw_all_info();
- else if(event.xexpose.window==inv_list.win)
- draw_all_list(&inv_list);
- else if(event.xexpose.window==look_list.win)
- draw_all_list(&look_list);
- else if(event.xexpose.window==win_message)
- draw_all_message();
- else if(event.xexpose.window==win_game) {
- if (cpl.showmagic) draw_magic_map();
- else display_map_doneupdate(TRUE, FALSE);
- } else if(want_config[CONFIG_SPLITWIN]==FALSE && event.xexpose.window==win_root) {
- XClearWindow(display,win_root);
}
- break;
+ case Expose:
+ /* No point redrawing windows if there are more Expose's to
+ * come.
+ */
+ if (event.xexpose.count!=0)
+ continue;
+
+ if (event.xexpose.window==win_stats) {
+ XClearWindow(display,win_stats);
+ draw_stats(1);
+ } else if (event.xexpose.window==info.win)
+ draw_all_info();
+ else if (event.xexpose.window==inv_list.win)
+ draw_all_list(&inv_list);
+ else if (event.xexpose.window==look_list.win)
+ draw_all_list(&look_list);
+ else if (event.xexpose.window==win_message)
+ draw_all_message();
+ else if (event.xexpose.window==win_game) {
+ if (cpl.showmagic)
+ draw_magic_map();
+ else
+ display_map_doneupdate(TRUE, FALSE);
+ } else if (want_config[CONFIG_SPLITWIN]==FALSE &&
+ event.xexpose.window==win_root) {
+ XClearWindow(display,win_root);
+ }
+ break;
case GraphicsExpose:
/* No point redrawing windows if there are more GraphicExpose's
* to come.
*/
- if (event.xgraphicsexpose.count!=0) continue;
- if(event.xgraphicsexpose.drawable==win_game) {
- if (cpl.showmagic) draw_magic_map();
- else display_map_doneupdate(TRUE, FALSE);
+ if (event.xgraphicsexpose.count!=0)
+ continue;
+
+ if (event.xgraphicsexpose.drawable==win_game) {
+ if (cpl.showmagic)
+ draw_magic_map();
+ else
+ display_map_doneupdate(TRUE, FALSE);
}
break;
@@ -2665,25 +2396,23 @@ void check_x_events() {
case ButtonPress:
- /* Most of these will try to send requests to the server - since we
- * are not connected, this will probably fail in some bad way.
+ /*
+ * Most of these will try to send requests to the server.
+ * Since we are not connected, this will probably fail in
+ * some bad way.
*/
- if (cpl.input_state != Metaserver_Select) {
-
- if(event.xbutton.window==win_game) {
- parse_game_button_press(event.xbutton.button,event.xbutton.x,
- event.xbutton.y);
- } else if(event.xbutton.window==inv_list.win) {
+ if (event.xbutton.window==info.win)
+ buttonpress_in_info(&event.xbutton);
+ else if (cpl.input_state != Metaserver_Select) {
+ if (event.xbutton.window==win_game)
+ parse_game_button_press(event.xbutton.button,
+ event.xbutton.x, event.xbutton.y);
+ else if (event.xbutton.window==inv_list.win)
buttonpress_in_list(&inv_list, &event.xbutton);
-
- } else if(event.xbutton.window==look_list.win) {
+ else if (event.xbutton.window==look_list.win)
buttonpress_in_list(&look_list, &event.xbutton);
- }
- else if (event.xbutton.window==infodata.win_info) {
- buttonpress_in_info(&event.xbutton);
- }
- break;
}
+ break;
case KeyRelease:
parse_key_release(event.xkey.keycode, gkey);
@@ -2699,12 +2428,13 @@ void check_x_events() {
else
do_key_press(0); /* regular key */
break;
+
case ClientMessage:
- if(event.xclient.data.l[0] == wm_delete_window){
+ if (event.xclient.data.l[0] == wm_delete_window) {
LOG(LOG_INFO,"x11::check_x_events","Window closed. Exiting.");
exit(0);
}
- break;
+ break;
}
}
/* Below does not apply if we're not connected */
@@ -2718,7 +2448,8 @@ void check_x_events() {
*/
/* Need to do this to show the players position */
- if (cpl.showmagic) magic_map_flash_pos();
+ if (cpl.showmagic)
+ magic_map_flash_pos();
clear_fire_run();
}
/* a good place to check for childs */
@@ -2828,7 +2559,8 @@ int init_windows(int argc, char **argv)
}
x = atoi(argv[on_arg]);
for (cp = argv[on_arg]; *cp!='\0'; cp++)
- if (*cp == 'x' || *cp == 'X') break;
+ if (*cp == 'x' || *cp == 'X')
+ break;
if (*cp==0) {
fprintf(stderr,"-mapsize requires both and X and Y value (ie, XxY - note the\nx in between.\n");
@@ -2920,7 +2652,7 @@ int init_windows(int argc, char **argv)
fprintf(stderr,"-scrolllines requires a number\n");
return 1;
}
- infodata.maxlines = atoi(argv[on_arg]);
+ info.lines = atoi(argv[on_arg]);
continue;
}
else if (!strcmp(argv[on_arg],"-font")) {
@@ -2953,6 +2685,13 @@ int init_windows(int argc, char **argv)
return 1;
}
}
+
+#ifndef HAVE_LIBPNG
+ fprintf(stderr,"Client not configured with Png display mode enabled\n");
+ fprintf(stderr,"Install the png library and try recompiling.\n");
+ exit(1);
+#endif
+
/* Moving processing and setting of display attributes down here.
* This is because a default display mode may also require special
* handling.
@@ -2960,14 +2699,8 @@ int init_windows(int argc, char **argv)
* we just fall back to pixmap mode. But I don't really want to get into
* a big nest of #ifdefs checking/setting modes.
*/
-#ifndef HAVE_LIBPNG
- fprintf(stderr,"Client not configured with Png display mode enabled\n");
- fprintf(stderr,"Install the png library and try recompiling.\n");
- exit(1);
-#else
- image_size=32;
-#endif
+ image_size=32;
mapdata_init();
/* Finished parsing all the command line options. Now start
@@ -2988,7 +2721,8 @@ int init_windows(int argc, char **argv)
init_keys();
init_cache_data();
set_window_pos();
- info_ratio=(float) infodata.width/ (float) (infodata.width + INV_WIDTH);
+ info_ratio = (float)info.width / (float)(info.width + INV_WIDTH);
+ XFlush(display);
return 0;
}
@@ -3079,16 +2813,18 @@ void resize_map_window(int x, int y)
* but does a reasonable job. Don't do shrinks
*/
- if (use_config[CONFIG_MAPWIDTH] > old_mapx) width = (use_config[CONFIG_MAPWIDTH] - old_mapx)* image_size;
+ if (use_config[CONFIG_MAPWIDTH] > old_mapx)
+ width = (use_config[CONFIG_MAPWIDTH] - old_mapx) * image_size;
- if (use_config[CONFIG_MAPHEIGHT] > old_mapy) height = (use_config[CONFIG_MAPHEIGHT] - old_mapy)* image_size;
+ if (use_config[CONFIG_MAPHEIGHT] > old_mapy)
+ height = (use_config[CONFIG_MAPHEIGHT] - old_mapy) * image_size;
/* if somethign to do */
- if (width>0 || height > 0) {
+ if (width > 0 || height > 0) {
XGetWindowAttributes(display, win_root, &attrib);
width += attrib.width;
height += attrib.height;
- XResizeWindow(display, win_game, x*image_size, y*image_size);
+ // resize other windows via configure root event
XResizeWindow(display, win_root, width, height);
}
old_mapx=use_config[CONFIG_MAPWIDTH];
@@ -3112,9 +2848,8 @@ void display_map_doneupdate(int redraw,
{
int ax,ay, mx, my;
- if(notice) {
+ if (notice)
return;
- }
if (cpl.showmagic) {
magic_map_flash_pos();
@@ -3122,8 +2857,8 @@ void display_map_doneupdate(int redraw,
}
XSetClipMask(display,gc_floor,None);
- for(ax=0;ax<use_config[CONFIG_MAPWIDTH];ax++) {
- for(ay=0;ay<use_config[CONFIG_MAPHEIGHT];ay++) {
+ for (ax=0;ax<use_config[CONFIG_MAPWIDTH];ax++) {
+ for (ay=0;ay<use_config[CONFIG_MAPHEIGHT];ay++) {
mx = pl_pos.x+ax;
my = pl_pos.y+ay;
if (redraw || the_map.cells[mx][my].need_update) {
@@ -3147,10 +2882,10 @@ int display_mapscroll(int dx, int dy)
dsty = dy < 0 ? image_size : 0;
w = use_config[CONFIG_MAPWIDTH];
- if(dx != 0)
+ if (dx != 0)
w--;
h = use_config[CONFIG_MAPHEIGHT];
- if(dy != 0)
+ if (dy != 0)
h--;
XCopyArea(display, win_game, win_game, gc_copy,
srcx, srcy,
@@ -3173,16 +2908,6 @@ int associate_cache_entry(Cache_Entry *c
return 0;
}
-void redisplay_stats()
-{
- int i;
- for(i=0;i<7;i++) {
- XDrawImageString(display,win_stats,
- gc_stats,10,i*14+10, stats_buff[i],strlen(stats_buff[i]));
-}
- XFlush(display);
-}
-
void display_map_startupdate()
{
}
@@ -3213,8 +2938,8 @@ void draw_magic_map()
*/
XClearWindow(display,win_game);
- cpl.mapxres = (win_info.width-4)/cpl.mmapx;
- cpl.mapyres = (win_info.height-4)/cpl.mmapy;
+ cpl.mapxres = win_info.width/cpl.mmapx;
+ cpl.mapyres = win_info.height/cpl.mmapy;
if (cpl.mapxres < 1 || cpl.mapyres<1) {
fprintf(stderr,"magic map resolution less than 1, map is %dx%d\n",
cpl.mmapx, cpl.mmapy);
@@ -3224,8 +2949,10 @@ void draw_magic_map()
* it probably makes sense to keep them the same value.
* Need to take the smaller value.
*/
- if (cpl.mapxres>cpl.mapyres) cpl.mapxres=cpl.mapyres;
- else cpl.mapyres=cpl.mapxres;
+ if (cpl.mapxres>cpl.mapyres)
+ cpl.mapxres=cpl.mapyres;
+ else
+ cpl.mapyres=cpl.mapxres;
if (cpl.mapxres>24) {
cpl.mapxres=24;
@@ -3236,7 +2963,7 @@ void draw_magic_map()
*/
for (y = 0; y < cpl.mmapy; y++) {
for (x = 0; x < cpl.mmapx; x++) {
- uint8 val = cpl.magicmap[y*cpl.mmapx + x];
+ int val = cpl.magicmap[y*cpl.mmapx + x];
XSetForeground(display,gc_game,
discolor[val&FACE_COLOR_MASK].pixel);
XFillRectangle(display,win_game,
@@ -3248,7 +2975,8 @@ void draw_magic_map()
/* Basically, this just flashes the player position on the magic map */
void magic_map_flash_pos()
{
- if (!cpl.showmagic) return;
+ if (!cpl.showmagic)
+ return;
cpl.showmagic ^=2;
if (cpl.showmagic & 2) {
XSetForeground(display, gc_game, foreground);
@@ -3332,7 +3060,7 @@ void save_winpos()
fprintf(fp,"win_game: %d %d %d %d\n", wx,wy, w, h);
get_window_coord(win_stats, &x,&y, &wx,&wy,&w,&h);
fprintf(fp,"win_stats: %d %d %d %d\n", wx,wy, w, h);
- get_window_coord(infodata.win_info, &x,&y, &wx,&wy,&w,&h);
+ get_window_coord(info.win, &x,&y, &wx,&wy,&w,&h);
fprintf(fp,"win_info: %d %d %d %d\n", wx,wy, w, h);
get_window_coord(inv_list.win, &x,&y, &wx,&wy,&w,&h);
fprintf(fp,"win_inv: %d %d %d %d\n", wx,wy, w, h);
@@ -3355,14 +3083,17 @@ void set_window_pos()
char buf[MAX_BUF],*cp;
FILE *fp;
- if (!want_config[CONFIG_SPLITWIN]) return;
+ if (!want_config[CONFIG_SPLITWIN])
+ return;
sprintf(buf,"%s/.crossfire/winpos", getenv("HOME"));
- if (!(fp=fopen(buf,"r"))) return;
+ if (!(fp=fopen(buf,"r")))
+ return;
while(fgets(buf,MAX_BUF-1, fp)!=NULL) {
buf[MAX_BUF-1]='\0';
- if (!(cp=strchr(buf,' '))) continue;
+ if (!(cp=strchr(buf,' ')))
+ continue;
*cp++='\0';
if (sscanf(cp,"%d %d %d %d",&xwc.x,&xwc.y,&xwc.width,&xwc.height)!=4)
continue;
@@ -3371,7 +3102,7 @@ void set_window_pos()
if (!strcmp(buf,"win_stats:"))
XConfigureWindow(display,win_stats,xwc_mask, &xwc);
if (!strcmp(buf,"win_info:"))
- XConfigureWindow(display,infodata.win_info,xwc_mask, &xwc);
+ XConfigureWindow(display,info.win,xwc_mask, &xwc);
if (!strcmp(buf,"win_inv:"))
XConfigureWindow(display,inv_list.win,xwc_mask, &xwc);
if (!strcmp(buf,"win_look:"))
@@ -3390,14 +3121,17 @@ void load_defaults()
FILE *fp;
sprintf(path,"%s/.crossfire/defaults", getenv("HOME"));
- if ((fp=fopen(path,"r"))==NULL) return;
+ if ((fp=fopen(path,"r"))==NULL)
+ return;
while (fgets(inbuf, MAX_BUF-1, fp)) {
inbuf[MAX_BUF-1]='\0';
inbuf[strlen(inbuf)-1]='\0'; /* kill newline */
- if (inbuf[0]=='#') continue;
+ if (inbuf[0]=='#')
+ continue;
/* IF no colon, then we certainly don't have a real value, so just skip */
- if (!(cp=strchr(inbuf,':'))) continue;
+ if (!(cp=strchr(inbuf,':')))
+ continue;
*cp='\0';
cp+=2; /* colon, space, then value */
@@ -3410,32 +3144,60 @@ void load_defaults()
continue;
}
if (!strcmp(inbuf,"cacheimages")) {
- if (!strcmp(cp,"True")) want_config[CONFIG_CACHE]=TRUE;
- else want_config[CONFIG_CACHE]=FALSE;
+ if (!strcmp(cp,"True"))
+ want_config[CONFIG_CACHE]=TRUE;
+ else
+ want_config[CONFIG_CACHE]=FALSE;
continue;
}
if (!strcmp(inbuf,"split")) {
- if (!strcmp(cp,"True")) want_config[CONFIG_SPLITWIN]=TRUE;
- else want_config[CONFIG_SPLITWIN]=FALSE;
+ if (!strcmp(cp,"True"))
+ want_config[CONFIG_SPLITWIN]=TRUE;
+ else
+ want_config[CONFIG_SPLITWIN]=FALSE;
continue;
}
if (!strcmp(inbuf,"showicon")) {
- if (!strcmp(cp,"True")) inv_list.show_icon=TRUE;
- else inv_list.show_icon=FALSE;
+ if (!strcmp(cp,"True"))
+ inv_list.show_icon=TRUE;
+ else
+ inv_list.show_icon=FALSE;
+ continue;
+ }
+ if (!strcmp(inbuf,"showicon.look")) {
+ if (!strcmp(cp,"True"))
+ look_list.show_icon=TRUE;
+ else
+ look_list.show_icon=FALSE;
+ continue;
+ }
+ if (!strcmp(inbuf,"showweight")) {
+ if (!strcmp(cp,"True"))
+ inv_list.show_weight=TRUE;
+ else
+ inv_list.show_weight=FALSE;
+ continue;
+ }
+ if (!strcmp(inbuf,"showweight.look")) {
+ if (!strcmp(cp,"True"))
+ look_list.show_weight=TRUE;
+ else
+ look_list.show_weight=FALSE;
continue;
}
if (!strcmp(inbuf,"scrolllines")) {
- infodata.maxlines = atoi(cp);
+ info.lines = atoi(cp);
continue;
}
if (!strcmp(inbuf,"scrollinfo")) {
- if (!strcmp(cp,"True")) infodata.scroll_info_window=TRUE;
- else infodata.scroll_info_window=FALSE;
+ /* silently ignored */
continue;
}
if (!strcmp(inbuf,"sound")) {
- if (!strcmp(cp,"True")) want_config[CONFIG_SOUND]=TRUE;
- else want_config[CONFIG_SOUND]=FALSE;
+ if (!strcmp(cp,"True"))
+ want_config[CONFIG_SOUND]=TRUE;
+ else
+ want_config[CONFIG_SOUND]=FALSE;
continue;
}
if (!strcmp(inbuf,"command_window")) {
@@ -3445,19 +3207,31 @@ void load_defaults()
continue;
}
if (!strcmp(inbuf,"foodbeep")) {
- if (!strcmp(cp,"True")) use_config[CONFIG_FOODBEEP]=TRUE;
- else use_config[CONFIG_FOODBEEP]=FALSE;
+ if (!strcmp(cp,"True"))
+ use_config[CONFIG_FOODBEEP]=TRUE;
+ else
+ use_config[CONFIG_FOODBEEP]=FALSE;
continue;
}
if (!strcmp(inbuf,"noautorepeat")) {
- if (!strcmp(cp,"True")) noautorepeat=TRUE;
- else noautorepeat=FALSE;
+ if (!strcmp(cp,"True"))
+ noautorepeat=TRUE;
+ else
+ noautorepeat=FALSE;
continue;
}
if (!strcmp(inbuf,"font")) {
font_name = strdup_local(cp);
continue;
}
+ if (!strcmp(inbuf,"mapsize")) {
+ int w,h;
+ if (sscanf(cp, "%dx%d", &w, &h) == 2) {
+ want_config[CONFIG_MAPWIDTH] = w;
+ want_config[CONFIG_MAPHEIGHT] = h;
+ }
+ continue;
+ }
fprintf(stderr,"Got line we did not understand: %s: %s\n", inbuf, cp);
}
fclose(fp);
@@ -3485,11 +3259,15 @@ void save_defaults()
fprintf(fp,"port: %d\n", use_config[CONFIG_PORT]);
fprintf(fp,"server: %s\n", server);
fprintf(fp,"font: %s\n", font_name);
+ fprintf(fp,"mapsize: %dx%d\n", want_config[CONFIG_MAPWIDTH],
+ want_config[CONFIG_MAPHEIGHT]);
fprintf(fp,"cacheimages: %s\n", want_config[CONFIG_CACHE]?"True":"False");
fprintf(fp,"split: %s\n", want_config[CONFIG_SPLITWIN]?"True":"False");
fprintf(fp,"showicon: %s\n", inv_list.show_icon?"True":"False");
- fprintf(fp,"scrolllines: %d\n", infodata.maxlines);
- fprintf(fp,"scrollinfo: %s\n", infodata.scroll_info_window?"True":"False");
+ fprintf(fp,"showicon.look: %s\n", look_list.show_icon?"True":"False");
+ fprintf(fp,"showweight: %s\n", inv_list.show_weight?"True":"False");
+ fprintf(fp,"showweight.look: %s\n", look_list.show_weight?"True":"False");
+ fprintf(fp,"scrolllines: %d\n", info.lines);
fprintf(fp,"sound: %s\n", want_config[CONFIG_SOUND]?"True":"False");
fprintf(fp,"command_window: %d\n", use_config[CONFIG_CWINDOW]);
fprintf(fp,"foodbeep: %s\n", use_config[CONFIG_FOODBEEP]?"True":"False");
@@ -3510,8 +3288,9 @@ void save_defaults()
void command_show (const char *params)
{
- if(!params) {
- if (inv_list.show_what==show_all) inv_list.show_what = show_applied;
+ if (!params) {
+ if (inv_list.show_what==show_all)
+ inv_list.show_what = show_applied;
else { /* rotate the bit. If no valid bits are set, start over */
inv_list.show_what = inv_list.show_what << 1;
if (!(inv_list.show_what & show_mask))
@@ -3552,26 +3331,26 @@ void command_show (const char *params)
int main(int argc, char *argv[])
{
int sound,got_one=0;
- int i;
-#ifdef HAS_COMMON_RCSID
- INIT_COMMON_RCSID;
-#endif
-#ifdef HAS_X11_RCSID
- INIT_X11_RCSID;
-#endif
/*
* output some version informations on LOG.
* usefull when reporting a bug.
*/
-
#ifdef HAS_COMMON_RCSID
- for (i=0;common_rcsid[i];i++)
- LOG(LOG_INFO,"Version::common","%s",common_rcsid[i]);
+ {
+ INIT_COMMON_RCSID;
+ int i;
+ for (i=0;common_rcsid[i];i++)
+ LOG(LOG_INFO,"Version::common","%s",common_rcsid[i]);
+ }
#endif
#ifdef HAS_X11_RCSID
- for (i=0;x11_rcsid[i];i++)
- LOG(LOG_INFO,"Version::x11 ","%s",x11_rcsid[i]);
+ {
+ INIT_X11_RCSID;
+ int i;
+ for (i=0;x11_rcsid[i];i++)
+ LOG(LOG_INFO,"Version::x11 ","%s",x11_rcsid[i]);
+ }
#endif
/* This needs to be done first. In addition to being quite quick,
@@ -3592,13 +3371,7 @@ int main(int argc, char *argv[])
fprintf(stderr,"Failure to init windows.\n");
exit(1);
}
- csocket.inbuf.buf=malloc(MAXSOCKBUF);
-
-#ifdef HAVE_SYSCONF
- maxfd = sysconf(_SC_OPEN_MAX);
-#else
- maxfd = getdtablesize();
-#endif
+ csocket.inbuf.buf = xmalloc(MAXSOCKBUF);
sound = init_sounds();
More information about the crossfire
mailing list