summaryrefslogtreecommitdiff
path: root/src/main-sdl.c
diff options
context:
space:
mode:
authorBardur Arantsson <bardur@scientician.net>2010-01-08 20:28:34 +0100
committerBardur Arantsson <bardur@scientician.net>2010-01-08 23:46:06 +0100
commit6aa48afdd57d03314fdf4be6c9da911c32277c84 (patch)
tree2dc401f9aae2dc6736d2fc3811c8f8099d3eabe6 /src/main-sdl.c
Import tome-2.3.5.
Diffstat (limited to 'src/main-sdl.c')
-rw-r--r--src/main-sdl.c2865
1 files changed, 2865 insertions, 0 deletions
diff --git a/src/main-sdl.c b/src/main-sdl.c
new file mode 100644
index 00000000..42c76958
--- /dev/null
+++ b/src/main-sdl.c
@@ -0,0 +1,2865 @@
+/* Copyright (C) 2003-2004 Neil Stevens <neil@hakubi.us>
+ // Copyright (C) 2004 Ethan Stump <estump@seas.upenn.edu>
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
+ // of this software and associated documentation files (the "Software"), to deal
+ // in the Software without restriction, including without limitation the rights
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ // copies of the Software, and to permit persons to whom the Software is
+ // furnished to do so, subject to the following conditions:
+ //
+ // The above copyright notice and this permission notice shall be included in
+ // all copies or substantial portions of the Software.
+ //
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ // THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ // AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ //
+ // Except as contained in this notice, the name(s) of the author(s) shall not be
+ // used in advertising or otherwise to promote the sale, use or other dealings
+ // in this Software without prior written authorization from the author(s).
+ */
+
+#ifdef USE_SDL
+
+#include "angband.h"
+#include <SDL.h>
+#include <SDL_image.h>
+#include <SDL_ttf.h>
+
+#include <math.h>
+
+#ifdef USE_ISO
+/*
+ * Simugraph system (Hj. Malthaner)
+ */
+#include "iso/simsys.h"
+#include "iso/simgraph.h"
+#include "iso/world_adaptor.h"
+#include "iso/world_view.h"
+/*
+ * Simugraph specific routines
+ * by Hj. Malthaner
+ */
+#include "iso/hackdef.h"
+
+/*
+ * Text place marker function protype (Hj. Malthaner)
+ */
+static void set_spots(int x, int y, int n, bool v);
+
+/**
+ * we need to track spots with text to avoid overdrawing text with images
+ * @author Hj. Malthaner (hansjoerg.malthaner@gmx.de)
+ */
+bool spots[80][24];
+
+/**
+ * mouse coordinates for Simugraph engine
+ * @author Hj. Malthaner (hansjoerg.malthaner@gmx.de)
+ */
+int mx, my;
+
+/*
+ * Hajo: this flags need to be set when opening windows
+ */
+
+static int tex_width;
+static int tex_height;
+static int tex_xoff;
+static int tex_yoff;
+
+static unsigned int tab16[1 << 16];
+
+/**
+ * this is used if we need to fake an 8 bit array
+ * @author Hj. Malthaner
+ */
+static unsigned short * data8;
+
+// buffers to store char code/attr for graphics
+unsigned char **iso_ap;
+unsigned char **iso_cp;
+unsigned char **iso_atp;
+unsigned char **iso_ctp;
+unsigned char **iso_aep;
+unsigned char **iso_cep;
+
+#endif /* USE_ISO */
+
+/*************************************************
+ GLOBAL SDL-ToME PROPERTIES
+ *************************************************/
+
+/* Default window properties - used if none are available
+from other places*/
+#define DEF_SCREEN_WIDTH 800
+#define DEF_SCREEN_HEIGHT 600
+#define DEF_SCREEN_BPP 16
+
+/*Main window properties that may be loaded at runtime from
+a preference file or environmental variables. However,
+default values (defined above) can be used. */
+static int arg_width = DEF_SCREEN_WIDTH;
+static int arg_height = DEF_SCREEN_HEIGHT;
+static int arg_bpp = DEF_SCREEN_BPP;
+
+/**************/
+
+/* Default font properties - used unless otherwise changed.
+These properties are the size and also default font to load. */
+#define DEF_FONT_SIZE 14
+#define DEF_FONT_FILE "VeraMono.ttf"
+
+/* The font properties that may perhaps be changed at runtime,
+due to environmental variables, preference files, or in-program
+commands.*/
+static int arg_font_size = DEF_FONT_SIZE;
+static char arg_font_name[64] = DEF_FONT_FILE;
+
+/**************/
+
+/* Graphics setting - signifies what graphics to use. Valid ints
+are available with given defines */
+
+/* No graphics - use only colored text */
+#define NO_GRAPHICS 0
+/* "Old" graphics - use 8x8.bmp to extract graphics tiles */
+#define GRAPHICS_8x8 8
+/* "New" graphics - use 16x16.bmp as tiles and apply mask.bmp for transparency*/
+#define GRAPHICS_16x16 16
+
+static int arg_graphics_type = NO_GRAPHICS;
+
+
+/**************/
+
+/* The number of term_data structures to set aside mem for */
+#define MAX_CONSOLE_COUNT 8
+
+/* The number of consoles that are actually being used.
+This number could be changed via preference files, environmental
+variables, command-line arguments, or possibly even in-game
+keypresses or menu-selections. */
+static int arg_console_count = 1;
+
+/* When rendering multiple terminals, each is drawn with a
+surrounding border. This value controls the width of this
+border */
+#define BORDER_THICKNESS 1
+
+/**************/
+
+/* some miscellaneous settings which have not been dealt
+with yet */
+static bool arg_double_width = FALSE;
+
+/* flag signifying whether the game is in full screen */
+static bool arg_full_screen = FALSE;
+
+/* a flag to show whether window properties have been
+set or not... if so, the properties can be dumped
+upon quit*/
+static bool window_properties_set = FALSE;
+
+/*************************************************
+ GLOBAL SDL-ToME VARIABLES
+ *************************************************/
+
+/* the main screen to draw to */
+static SDL_Surface *screen;
+
+/* the video settings for the system */
+static SDL_VideoInfo *videoInfo;
+
+/* a flag to suspend updating of the screen;
+this is in place so that when a large area is being
+redrawn -- like when doing a Term_redraw() or when
+redoing the entire screen -- all of the changes
+can be stored up before doing an update. This
+should cut down on screen flicker */
+static bool suspendUpdate = FALSE;
+
+/* some helper surfaces that are used for rendering
+characters */
+static SDL_Surface *worksurf;
+static SDL_Surface *crayon;
+
+/* the cursor surface */
+static SDL_Surface *cursor = NULL;
+
+/* the array of pre-rendered characters
+(see loadAndRenderFont() below) */
+SDL_Surface *text[128];
+
+/* the actual TTF_Font used (XXX should get rid of this)*/
+TTF_Font *font=0;
+
+/* the width and height of the uniformly-sized pre-rendered
+characters */
+int t_width = 0, t_height = 0;
+
+
+/*************************************************
+ COLOR SETUP
+ *************************************************/
+
+/* Simple black, mapped using the format of the main screen */
+int screen_black;
+
+/* The color to use for the cursor */
+static int cursor_color = 0;
+/* default cursor color is a semi-transparent yellow */
+#define DEF_CURSOR_COLOR 255,255,0,128
+
+/* The array of colors, mapped to the format of the crayon surface,
+since this is ultimately the surface that color is begin applied to */
+static int color_data[16];
+
+/* The following macro is for color defining...
+ Note that the color is fully opaque... */
+#define COLOR(r,g,b) \
+ SDL_MapRGBA(crayon->format,r,g,b,SDL_ALPHA_OPAQUE)
+
+/*These color macros will setup the colors to use, but must be called after
+ the SDL video has been set. That way SDL can correct for any funky video
+ setttings. */
+
+#define BLACK COLOR( 0, 0, 0) /* 0*/
+#define WHITE COLOR(255,255,255) /* 1*/
+#define MID_GREY COLOR(128,128,128) /* 2*/
+#define BRIGHT_ORANGE COLOR(255,128, 0) /* 3*/
+#define RED COLOR(192, 0, 0) /* 4*/
+#define GREEN COLOR( 0,128, 64) /* 5*/
+#define BRIGHT_BLUE COLOR( 0, 0,255) /* 6*/
+#define DARK_ORANGE COLOR(128, 64, 0) /* 7*/
+#define DARK_GREY COLOR( 64, 64, 64) /* 8*/
+#define BRIGHT_GREY COLOR(192,192,192) /* 9*/
+#define PURPLE COLOR(255, 0,255) /*10*/
+#define YELLOW COLOR(255,255, 0) /*11*/
+#define BRIGHT_RED COLOR(255, 0, 0) /*12*/
+#define BRIGHT_GREEN COLOR( 0,255, 0) /*13*/
+#define AQUAMARINE COLOR( 0,255,255) /*14*/
+#define BROWN COLOR(192,128, 64) /*15*/
+
+/*************************************************
+ TERMINAL DATA STRUCTURE SETUP
+ *************************************************/
+
+/* Forward declare */
+typedef struct _term_data term_data;
+
+/* A structure for each "term" */
+struct _term_data
+{
+ term t; /* the term structure, defined in z-term.h */
+ cptr name; /* name of this term sub-window */
+
+ uint rows, cols; /* row/column count */
+ SDL_Rect rect; /* the bounding rectangle for the entire box;
+ includes border and empty space as well */
+ /* this rectangle is in screen coordinates */
+
+ int border_thick; /* thickness of border to draw around window */
+ int border_color; /* current color of the border */
+ uint cushion_x_top, cushion_x_bot, cushion_y_top, cushion_y_bot;
+ /* empty space cushion between border and tiles */
+
+ uint tile_width; /* the width of each tile (graphic or otherwise)*/
+ uint tile_height; /* the height of each tile (graphic or otherwise)*/
+
+ SDL_Surface *surf; /* the surface that graphics for this screen are
+ rendered to before blitting to main screen */
+ int black,white,purple; /* basic colors keyed to this terminal's surface */
+
+#ifdef USE_GRAPHICS
+#ifdef USE_TRANSPARENCY
+#endif
+#endif
+};
+
+/* The array of term data structures */
+static term_data data[MAX_CONSOLE_COUNT];
+
+/* Ordered array of pointers to term data structures, placed in order of
+priority: lowest is on top of all others, the higher the index, the further
+back into the screen that it is drawn */
+static term_data *term_order[MAX_CONSOLE_COUNT];
+
+/*************************************************
+ FILE-SPECIFIC MACROS
+ *************************************************/
+
+/* Debug macros! */
+#define DB(str) \
+ printf("main-sdl: %s\n",str);
+
+/* Prints out the RGBA values of a given color */
+#define TYPECOLOR32(color) printf(" R:%d\tG:%d\tB:%d\tA:%d\t\n",\
+ color>>24,(color&0x00ff0000)>>16,\
+ (color&0x0000ff00)>>8,(color&0x000000ff))
+
+#define TYPECOLOR16(color) printf(" R:%d\tG:%d\tB:%d\tA:%d\t\n",\
+ (color&0xf000)>>12,(color&0x0f00)>>8,\
+ (color&0x00f0)>>4,(color&0x000f))
+
+/* SDL Surface locking and unlocking */
+#define SDL_LOCK(surf) \
+ if (SDL_MUSTLOCK(surf) ){ \
+ if (SDL_LockSurface(surf) < 0) { \
+ printf("Can't lock the screen: %s\n", SDL_GetError()); \
+ exit(1); \
+ } \
+ }
+
+#define SDL_UNLOCK(surf) \
+ if (SDL_MUSTLOCK(surf) ){ \
+ SDL_UnlockSurface(surf); \
+ }
+
+/* Wrapped SDL_UpdateRects function, to take into
+account the fact that updates may be suspended by
+the suspendUpdate flag... this macro should be used
+whenever a rect needs updated */
+#define SDL_UPDATE(rect) \
+ if (!suspendUpdate) \
+ SDL_UpdateRects(screen,1,&rect)
+
+/* A complete screen redraw macro */
+#define SDL_REDRAW_SCREEN \
+ SDL_UpdateRect(screen,0,0,arg_width,arg_height)
+
+/*************************************************
+ QUITTING
+ *************************************************/
+
+/* function prototype */
+void dumpWindowSettings(void);
+
+/* SDL Quitting function... declare a few functions first.*/
+void killFontAndAlphabet(void);
+static void sdl_quit(cptr string)
+{
+ printf("sdl_quit called.\n");
+ printf("message: %s\n",string);
+ /* Need to take care of font and rendered characters */
+ killFontAndAlphabet();
+ if (TTF_WasInit())
+ TTF_Quit();
+ /* Then exit SDL */
+ SDL_Quit();
+
+ /* Dump the window properties, if available */
+ if (window_properties_set)
+ dumpWindowSettings();
+
+ /* And now for the default quit behavior */
+ quit_aux = 0;
+ quit(string);
+}
+
+/*************************************************
+ FONT SUPPORT FUNCTIONS
+ *************************************************/
+
+/* function prototype for creating surfaces */
+SDL_Surface *createSurface(int width, int height);
+
+/* killFontAndAlphabet will effectively de-initialize the font system;
+it does this by closing the font and destroying any pre-rendered
+text in memory */
+void killFontAndAlphabet(void)
+{
+ int i;
+ /* need to close a font and free all of its corresponding pre-rendered
+ surfaces */
+ if (font)
+ {
+ TTF_CloseFont(font);
+ font = 0;
+ }
+ for (i=0;i<128;i++)
+ {
+ if(text[i])
+ {
+ SDL_FreeSurface(text[i]);
+ text[i] = NULL;
+ }
+ }
+}
+
+/* loadAndRenderFont is responsible for loading and initializing
+a font. First, SDL_ttf calls are made to load and set the style
+for the desired font. Next, a character alphabet is rendered and
+each character is placed onto a uniformly-sized surface within
+the text[] array. Whenever text is needed for displaying on-screen,
+this array is referenced and the desired character picture is used. */
+void loadAndRenderFont(char *fname, int size)
+{
+ int minx,maxx,miny,maxy,advance,i,midline = 0;
+ char filename[PATH_MAX + 1];
+ char fontdir[PATH_MAX + 1];
+ SDL_Color base_color = {255,255,255,255};
+ SDL_Surface *temp_surf;
+ SDL_Rect tgt = {0,0,0,0};
+
+
+ /* Assuming that the filename is valid,open the font */
+ path_build(fontdir, PATH_MAX, ANGBAND_DIR_XTRA, "font");
+ path_build(filename, PATH_MAX, fontdir, fname);
+ font = TTF_OpenFont(filename,size);
+ if (font == NULL)
+ sdl_quit("Error loading that font!");
+ /* Set the font style to normal */
+ TTF_SetFontStyle(font,TTF_STYLE_NORMAL);
+
+ /* Collect some measurements on this font -
+ arbitrarily choose the letter 'a' to get width*/
+ TTF_GlyphMetrics(font,'a',&minx,&maxx,&miny,&maxy,&advance);
+ /* the width of each character tile */
+ t_width = advance;
+ /* the height of each character tile */
+ t_height = TTF_FontHeight(font);
+ /* position of the y=0 line in each tile */
+ midline = TTF_FontAscent(font);
+
+ /* now... render each of the individual characters */
+ for (i=0;i<128;i++)
+ {
+ /* make a pretty blended glyph */
+ temp_surf=TTF_RenderGlyph_Blended(font,i,base_color);
+ /* and make sure that we got it right! */
+ if (temp_surf == NULL)
+ sdl_quit("Glyph failed to render!");
+ /* get the metrics of this particular glyph so we can position it */
+ TTF_GlyphMetrics(font,i,&minx,&maxx,&miny,&maxy,&advance);
+ /* copy rendered glyph into text queue, at the right position*/
+ tgt.x = minx;
+ tgt.y = midline-maxy;
+ /* but first... we'll need a surface in the text queue to blit to! */
+ text[i] = createSurface(t_width,t_height);
+ /* turn OFF src-alpha... results in brute
+ copy of the RGBA contents of surf */
+ SDL_SetAlpha(temp_surf,0,0);
+ SDL_BlitSurface(temp_surf,NULL,text[i],&tgt);
+ /* turn OFF src-alpha since we'll be using worksurf for blitting */
+ SDL_SetAlpha(text[i],0,0);
+ /* kill the surface to patch up memory leaks */
+ SDL_FreeSurface(temp_surf);
+ }
+}
+
+#ifdef USE_ISO
+/*************************************************
+ ISO SUPPORT FUNCTIONS
+ *************************************************/
+/**
+ * inits operating system stuff
+ * @author Hj. Malthaner (hansjoerg.malthaner@gmx.de)
+ */
+int dr_os_init(int n, int *parameter)
+{
+ // Hajo:
+ // unused in isov-x11
+ return TRUE;
+}
+
+
+/**
+ * opens graphics device/context/window of size w*h
+ * @param w width
+ * @param h height
+ * @author Hj. Malthaner (hansjoerg.malthaner@gmx.de)
+ */
+int dr_os_open(int w, int h)
+{
+ const int left = 13;
+
+/* tex_width = (data[0].fd->dw * (data[0].t.wid - left + 2) + 3) & 0xFFFC;
+ tex_height = data[0].fd->dh * (data[0].t.hgt - 2);
+
+ tex_xoff = data[0].fd->dw * left;
+ tex_yoff = data[0].fd->dh * 1 + 1;
+*/
+
+ //tex_width = (data[0].size_w - (left - 2) * (data[0].size_w / data[0].cols) + 3) & 0xFFFC;
+ // this is too big (but works :-))
+ tex_width = data[0].size_w & 0xfffc;
+ tex_height = (data[0].size_h / data[0].rows) * (data[0].rows-2);
+
+ tex_xoff = (tex_width / data[0].cols) * left;
+ tex_yoff = (tex_height / data[0].rows) * 1 + 1;
+
+ return TRUE;
+}
+
+
+/**
+ * closes operating system stuff
+ * @author Hj. Malthaner (hansjoerg.malthaner@gmx.de)
+ */
+int dr_os_close()
+{
+ // Hajo:
+ // unused in isov-x11
+ return TRUE;
+}
+
+
+/**
+ * retrieve display width
+ * @author Hj. Malthaner (hansjoerg.malthaner@gmx.de)
+ */
+int dr_get_width()
+{
+ return data[0].size_w;
+}
+
+
+/**
+ * retrieve display height
+ * @author Hj. Malthaner (hansjoerg.malthaner@gmx.de)
+ */
+int dr_get_height()
+{
+ return data[0].size_h;
+}
+
+
+/**
+ * this is used if we need to fake an 8 bit array
+ * @author Hj. Malthaner
+ */
+static unsigned short * data8;
+
+
+/**
+ * creates a (maybe virtual) array of graphics data
+ * @author Hj. Malthaner
+ */
+unsigned short * dr_textur_init()
+{
+ int i;
+
+ printf("isov-sdl::dr_textur_init()\n");
+ printf(" width = %d\n", data[0].size_w);
+ printf(" height = %d\n", data[0].size_h);
+
+ for (i = 0; i < (1 << 16); i++)
+ {
+ // FIXME!!!
+ // must consider color bits, or breaks in anything else but RGB 555
+ unsigned int R;
+ unsigned int G;
+ unsigned int B;
+
+ // RGB 555
+ R = (i & 0x7C00) >> 10;
+ G = (i & 0x03E0) >> 5;
+ B = (i & 0x001F) >> 0;
+
+
+ tab16[i] = SDL_MapRGB(screen->format, R << 3, G << 3, B << 3);
+ }
+
+
+
+ data8 = malloc((data[0].size_w) * (data[0].size_h) * 2);
+
+ printf(" textur = %p\n", data8);
+
+ // fake an 16 bit array and convert data before displaying
+ return data8;
+}
+
+static void flush_area(int dest_x, int dest_y,
+ int x, int y, int w, int h)
+{
+ SDL_Surface *face = screen;
+
+ if (SDL_LockSurface(face) == 0)
+ {
+ int i, j;
+ const int bpp = screen->format->BytesPerPixel;
+
+ for (j = 0; j < h; j++)
+ {
+ unsigned short * p = data8 + (y + j) * tex_width + x;
+ unsigned char * row = face->pixels + (dest_y + j) * face->pitch + dest_x * bpp;
+
+
+ for (i = 0; i < w; i++)
+ {
+ *((unsigned short*)row) = tab16[ *p++ ];
+ row += bpp;
+ }
+ }
+ SDL_UnlockSurface(face);
+ }
+}
+
+/**
+ * displays the array of graphics data
+ * @author Hj. Malthaner
+ */
+void dr_textur(int xp, int yp, int w, int h)
+{
+ int y;
+
+ // clipping unten
+ if (yp + h > tex_height)
+ {
+ h = tex_height - yp;
+ }
+
+ /* debug spots
+ for(y=0; y<24; y++) {
+ int x;
+
+ for(x=0; x<80; x++) {
+ if(spots[x][y]) {
+ printf("X");
+ } else {
+ printf(".");
+ }
+}
+ printf("\n");
+}
+ */
+
+ for (y = 0; y < SCREEN_HGT; y++)
+ {
+ const int left = 13;
+ const int y1 = y + 1;
+ int x = 0;
+
+ yp = data[0].size_h / data[0].rows * y;
+
+ spots[79][y1] = FALSE;
+
+ do
+ {
+ int n = 0;
+ while (x + n + left < 80 && !spots[x + n + left][y1])
+ {
+ n++;
+ }
+
+ xp = data[0].size_w / data[0].cols * x;
+
+
+ flush_area(tex_xoff + xp, tex_yoff + yp,
+ xp, yp,
+ data[0].size_w / data[0].cols*(n),
+ data[0].size_h / data[0].rows);
+
+ x += n;
+
+ while (x + left < 80 && spots[x + left][y1])
+ {
+ x++;
+ }
+ }
+ while (x + left < 80);
+ }
+}
+
+
+/**
+ * use this method to flush graphics pipeline (undrawn stuff) onscreen.
+ * @author Hj. Malthaner
+ */
+void dr_flush()
+{
+ // Iso-view for angband needs no sync.
+ // XSync(md,FALSE);
+}
+
+
+/**
+ * set colormap entries
+ * @author Hj. Malthaner
+ */
+void dr_setRGB8multi(int first, int count, unsigned char * data)
+{
+ // Hajo:
+ // unused in isov-x11
+}
+
+
+/**
+ * display/hide mouse pointer
+ * @author Hj. Malthaner (hansjoerg.malthaner@gmx.de)
+ */
+void show_pointer(int yesno)
+{
+ // Hajo:
+ // unused in isov-x11
+}
+
+
+/**
+ * move mouse pointer
+ * @author Hj. Malthaner (hansjoerg.malthaner@gmx.de)
+ */
+void move_pointer(int x, int y)
+{
+ // Hajo:
+ // unused in isov-x11
+}
+
+
+/**
+ * update softpointer position
+ * @author Hj. Malthaner (hansjoerg.malthaner@gmx.de)
+ */
+void ex_ord_update_mx_my()
+{
+ // Hajo:
+ // unused in isov-x11
+}
+
+
+/**
+ * get events from the system
+ * @author Hj. Malthaner (hansjoerg.malthaner@gmx.de)
+ */
+void GetEvents()
+{
+ // Hajo:
+ // unused in isov-x11
+}
+
+
+/**
+ * get events from the system without waiting
+ * @author Hj. Malthaner (hansjoerg.malthaner@gmx.de)
+ */
+void GetEventsNoWait()
+{
+ // Hajo:
+ // unused in isov-x11
+}
+
+
+/**
+ * @returns time since progrma start in milliseconds
+ * @author Hj. Malthaner
+ */
+long long dr_time(void)
+{
+ // Hajo:
+ // unused in isov-x11
+ return 0;
+}
+
+
+/**
+ * sleeps some microseconds
+ * @author Hj. Malthaner
+ */
+void dr_sleep(unsigned long usec)
+{
+ // Hajo:
+ // unused in isov-x11
+}
+
+
+/**
+ * loads a sample
+ * @return a handle for that sample or -1 on failure
+ * @author Hj. Malthaner
+ */
+int dr_load_sample(const char *filename)
+{
+ // Hajo:
+ // unused in isov-x11
+ return TRUE;
+}
+
+
+/**
+ * plays a sample
+ * @param key the key for the sample to be played
+ * @author Hj. Malthaner
+ */
+void dr_play_sample(int key, int volume)
+{
+ // Hajo:
+ // unused in isov-x11
+}
+
+static unsigned char ** halloc(int w, int h)
+{
+ unsigned char **field = (unsigned char **)malloc(sizeof(unsigned char *) * h);
+ int i;
+
+ for (i = 0; i < h; i++)
+ {
+ field[i] = (unsigned char *)malloc(sizeof(unsigned char) * w);
+ memset(field[i], 32 , w);
+ }
+
+ return field;
+}
+
+/**
+ * spot array access procedure. Mark text output spots
+ * @author Hj. Malthaner (hansjoerg.malthaner@gmx.de)
+ */
+static void set_spots(const int x, const int y, const int n, const bool v)
+{
+ int i;
+
+ for (i = x; i < x + n; i++)
+ {
+ spots[i][y] = v;
+ }
+}
+
+
+/***********************************************/
+#endif /* USE_ISO */
+
+/***********************************************/
+
+/*** Function hooks needed by "Term" ***/
+
+static void Term_init_sdl(term *t)
+{
+ term_data *td = (term_data*)(t->data);
+ DB("Term_init_sdl");
+ /* XXX XXX XXX */
+}
+
+static void Term_nuke_sdl(term *t)
+{
+ term_data *td = (term_data*)(t->data);
+ DB("Term_nuke_sdl");
+ /* XXX XXX XXX */
+}
+
+static errr Term_user_sdl(int n)
+{
+ term_data *td = (term_data*)(Term->data);
+ DB("Term_user_sdl");
+ /* XXX XXX XXX */
+
+ /* Unknown */
+ return (1);
+}
+
+/* KEYPRESS_STRING repeatedly sends characters to the terminal
+XXX - should implement routine from maim-sdl.c, it's sooo much
+cleaner */
+#define KEYPRESS_STRING(str) \
+strcpy(buf,str); \
+n = buf; \
+while (*n != '\0') { \
+ Term_keypress((int)(*(n++))); \
+}
+
+/* function prototype */
+void manipulationMode(void);
+void redrawAllTerminals(void);
+/* This is the main event handling routine that will be called
+whenever an event is pulled off of the queue (in Term_xtra_sdl())*/
+void handleEvent(SDL_Event *event)
+{
+ static char buf[24]; /* a buffer used when passing key names */
+ char *n; /* and a pointer to manipulate this buffer */
+
+ switch( event->type )
+ {
+ case SDL_KEYDOWN:
+ {
+ /* handle key presses */
+
+ /* I'm reading that as long as the upper 9 bits of the unicode
+ * value are zero, then the lower 7 bits are direct ASCII characters.
+ * Furthermore, it seems that all basic keys return non-zero values
+ * for the lower 7 bits, but function keys and other various things
+ * return 0000000 for the lower 7 bits.
+ * Basically, if the lower 7 bits are zero, do something special
+ * (like start a macro), but otherwise just pass along the ASCII
+ * code!
+ */
+ byte ascii_part = event->key.keysym.unicode & 0x00ff;
+
+ /* gimme the key name */
+ printf("Key is: %s\n",SDL_GetKeyName(event->key.keysym.sym));
+
+ /* allow for full screen toggling! */
+ if ((event->key.keysym.sym == SDLK_RETURN) && \
+ (SDL_GetModState() & KMOD_ALT))
+ {
+ SDL_WM_ToggleFullScreen(screen);
+ /* toggle the internal full screen flag */
+ arg_full_screen = (arg_full_screen ? FALSE : TRUE);
+ }
+
+ /* entry into window manipulation mode */
+ if ((event->key.keysym.sym == SDLK_RETURN) && \
+ (SDL_GetModState() & KMOD_CTRL))
+ {
+ DB("Manipulation mode!");
+ manipulationMode();
+ }
+
+#ifdef USE_ISO
+ /* toggle tile size */
+ if (event->key.keysym.sym == SDLK_SCROLLOCK)
+ {
+ switch (display_get_tile_size())
+ {
+ case 32:
+ display_select_tile_size(0);
+ break;
+ case 64:
+ display_select_tile_size(1);
+ break;
+ default:
+ display_select_tile_size(0);
+ break;
+ }
+ reset_visuals();
+ strcpy(buf, "graf-iso.prf");
+ process_pref_file(buf);
+ refresh_display();
+ SDL_UpdateRect(screen, 0, 0, data[0].size_w, data[0].size_h);
+ }
+
+ /* cycle grid type none/objects+monsters only/full */
+ if ((event->key.keysym.sym == '#') && \
+ (SDL_GetModState() & KMOD_ALT))
+ {
+ set_grid(get_grid()+1);
+ refresh_display();
+ }
+
+#endif
+
+ /*printf("ascii_part: %d\n",ascii_part);*/
+ if (ascii_part)
+ {
+ /* We have now determined that the ASCII part is not '0', so
+ we can safely pass along the ASCII value! */
+ Term_keypress(ascii_part);
+ }
+ else
+ {
+ /* We want to ignore keypresses that are simply the modifier
+ keys*/
+ if (!( (event->key.keysym.sym == SDLK_RSHIFT) |
+ (event->key.keysym.sym == SDLK_LSHIFT) |
+ (event->key.keysym.sym == SDLK_RALT) |
+ (event->key.keysym.sym == SDLK_LALT) |
+ (event->key.keysym.sym == SDLK_RCTRL) |
+ (event->key.keysym.sym == SDLK_LCTRL) ))
+ {
+
+ /* now build a macro string using the modifiers together
+ with the key that was just pressed*/
+
+ /* As for the formatting...
+ * We pass the key press and modifiers as follows:
+ * \[ctrl-alt-shift-"key name"]
+ * following the previously established convention...
+ *
+ * All of the things that happen are defined in pref-sdl.prf
+ */
+
+ KEYPRESS_STRING("\["); /*Output the first part... */
+ /* See if a control key is down */
+ if (event->key.keysym.mod & KMOD_CTRL)
+ {
+ KEYPRESS_STRING("ctrl-");
+ }
+ /* See if an alt key is down */
+ if (event->key.keysym.mod & KMOD_ALT)
+ {
+ KEYPRESS_STRING("alt-");
+ }
+ /* See if a shift key is down */
+ if (event->key.keysym.mod & KMOD_SHIFT)
+ {
+ KEYPRESS_STRING("shift-");
+ }
+
+ /* Add in the name of whatever key was pressed */
+ KEYPRESS_STRING(SDL_GetKeyName(event->key.keysym.sym));
+
+ /* and end it... */
+ KEYPRESS_STRING("]");
+ }
+ }
+ break;
+ }
+ case SDL_QUIT:
+ {
+ /* handle quit requests */
+ DB("Emergency Blit");
+ redrawAllTerminals();
+ /*sdl_quit("Quitting!\n");*/
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+/* declare the screen clearing function used below */
+void eraseTerminal();
+void drawTermStuff(term_data *td, SDL_Rect *rect);
+static errr Term_xtra_sdl(int n, int v)
+{
+ static SDL_Event event;
+ term_data *td;
+
+
+ /* Analyze */
+ switch (n)
+ {
+ case TERM_XTRA_EVENT:
+ {
+ if (v)
+ {
+ /* Perform event checking with blocking */
+ SDL_WaitEvent( &event );
+ handleEvent( &event );
+ } else {
+ /* Perform event checking without blocking */
+ if (SDL_PollEvent(&event)){
+ /* We found an event! */
+ handleEvent(&event);
+ }
+ }
+ return(0);
+ }
+
+ case TERM_XTRA_FLUSH:
+ {
+ /* Keep doing events until the queue is empty! */
+ while (SDL_PollEvent(&event))
+ {
+ handleEvent(&event);
+ }
+ return (0);
+ }
+
+ case TERM_XTRA_CLEAR:
+ {
+ /* Clear the terminal */
+ DB("TERM_XTRA_CLEAR");
+ suspendUpdate = TRUE;
+ eraseTerminal();
+ return (0);
+ }
+
+ case TERM_XTRA_SHAPE:
+ {
+ /*
+ * Set the cursor visibility XXX XXX XXX
+ *
+ * This action should change the visibility of the cursor,
+ * if possible, to the requested value (0=off, 1=on)
+ *
+ * This action is optional, but can improve both the
+ * efficiency (and attractiveness) of the program.
+ */
+
+ return (0);
+ }
+
+ case TERM_XTRA_FROSH:
+ {
+ /*
+ * Flush a row of output XXX XXX XXX
+ *
+ * This action should make sure that row "v" of the "output"
+ * to the window will actually appear on the window.
+ *
+ * This action is optional, assuming that "Term_text_xxx()"
+ * (and similar functions) draw directly to the screen, or
+ * that the "TERM_XTRA_FRESH" entry below takes care of any
+ * necessary flushing issues.
+ */
+
+ return (1);
+ }
+
+ case TERM_XTRA_FRESH:
+ {
+ /*
+ * Flush output XXX XXX XXX
+ *
+ * This action should make sure that all "output" to the
+ * window will actually appear on the window.
+ *
+ * This action is optional, assuming that "Term_text_xxx()"
+ * (and similar functions) draw directly to the screen, or
+ * that the "TERM_XTRA_FROSH" entry above takes care of any
+ * necessary flushing issues.
+ */
+
+#ifdef USE_ISO
+ // Hajo:
+ // refresh the graphical view
+
+ refresh_display();
+ SDL_UpdateRect(screen, 0, 0, data[0].size_w, data[0].size_h);
+// SDL_UpdateRect(td->face, 0, 0, 80*td->w, 24*td->h);
+#else /* regular SDL */
+ /* If terminal display has been held for any reason,
+ then update the whole thing now!*/
+ DB("TERM_XTRA_FRESH");
+ if (suspendUpdate)
+ {
+ DB(" update WAS suspended... updating now");
+ td = (term_data*)(Term->data);
+ suspendUpdate = FALSE;
+ drawTermStuff(td,NULL);
+ }
+#endif /* USE_ISO */
+ return (0);
+ }
+
+ case TERM_XTRA_NOISE:
+ {
+ /*
+ * Make a noise XXX XXX XXX
+ *
+ * This action should produce a "beep" noise.
+ *
+ * This action is optional, but convenient.
+ */
+
+ return (1);
+ }
+
+ case TERM_XTRA_SOUND:
+ {
+ /*
+ * Make a sound XXX XXX XXX
+ *
+ * This action should produce sound number "v", where the
+ * "name" of that sound is "sound_names[v]". This method
+ * is still under construction.
+ *
+ * This action is optional, and not very important.
+ */
+
+ return (1);
+ }
+
+ case TERM_XTRA_BORED:
+ {
+ /* Perform event checking without blocking */
+ if (SDL_PollEvent(&event)){
+ /* We found an event! */
+ handleEvent(&event);
+ }
+ return(0);
+ }
+
+ case TERM_XTRA_REACT:
+ {
+ /*
+ * React to global changes XXX XXX XXX
+ *
+ * For example, this action can be used to react to
+ * changes in the global "color_table[256][4]" array.
+ *
+ * This action is optional, but can be very useful for
+ * handling "color changes" and the "arg_sound" and/or
+ * "arg_graphics" options.
+ */
+#ifdef USE_ISO
+ strcpy(buf, "graf-iso.prf");
+ process_pref_file(buf);
+#endif /* USE_ISO */
+ return (1);
+ }
+
+ case TERM_XTRA_ALIVE:
+ {
+ /*
+ * Change the "hard" level XXX XXX XXX
+ *
+ * This action is used if the program changes "aliveness"
+ * by being either "suspended" (v=0) or "resumed" (v=1)
+ * This action is optional, unless the computer uses the
+ * same "physical screen" for multiple programs, in which
+ * case this action should clean up to let other programs
+ * use the screen, or resume from such a cleaned up state.
+ *
+ * This action is currently only used by "main-gcu.c",
+ * on UNIX machines, to allow proper "suspending".
+ */
+
+ return (1);
+ }
+
+ case TERM_XTRA_LEVEL:
+ {
+ /*
+ * Change the "soft" level XXX XXX XXX
+ *
+ * This action is used when the term window changes "activation"
+ * either by becoming "inactive" (v=0) or "active" (v=1)
+ *
+ * This action can be used to do things like activate the proper
+ * font / drawing mode for the newly active term window. This
+ * action should NOT change which window has the "focus", which
+ * window is "raised", or anything like that.
+ *
+ * This action is optional if all the other things which depend
+ * on what term is active handle activation themself, or if only
+ * one "term_data" structure is supported by this file.
+ */
+
+ return (1);
+ }
+
+ case TERM_XTRA_DELAY:
+ {
+ /*
+ * Delay for some milliseconds XXX XXX XXX
+ *
+ * This action is useful for proper "timing" of certain
+ * visual effects, such as breath attacks.
+ *
+ * This action is optional, but may be required by this file,
+ * especially if special "macro sequences" must be supported.
+ */
+
+ /* I think that this command is system independent... */
+ /*sleep(v/1000);*/
+ /* main-x11 uses usleep(1000*v); */
+ /* main-win uses Sleep(v); */
+ return (1);
+ }
+
+ case TERM_XTRA_GET_DELAY:
+ {
+ /*
+ * Get Delay of some milliseconds XXX XXX XXX
+ * place the result in Term_xtra_long
+ *
+ * This action is useful for proper "timing" of certain
+ * visual effects, such as recording cmovies.
+ *
+ * This action is optional, but cmovies wont perform
+ * good without it
+ */
+
+ return (1);
+ }
+ }
+
+ /* Unknown or Unhandled action */
+ return (1);
+}
+
+/*************************************************
+ GRAPHICS ROUTINES
+ *************************************************/
+
+/* wrapper routine for creating an RGB surface with given height and
+ width that corresponds to desired color depth and respects the system
+ pixel format */
+SDL_Surface *createSurface(int width, int height)
+{
+ SDL_Surface *surf;
+ int surface_type;
+
+ if (videoInfo->hw_available)
+ surface_type = SDL_HWSURFACE;
+ else
+ surface_type = SDL_SWSURFACE;
+
+ /* XXX need to make RGBA masks correspond to system pixel format! */
+ switch (arg_bpp)
+ {
+ case 8:
+ {
+ /* I really don't know if 8 bpp is even possible, but here it is */
+ surf = SDL_CreateRGBSurface(surface_type,width,\
+ height,8,0xc0,0x30,0x0c,0x03);
+ break;
+ }
+ case 16:
+ {
+ surf = SDL_CreateRGBSurface(surface_type,width,\
+ height,16,0xf000,0x0f00,0x00f0,0x000f);
+ break;
+ }
+ case 24:
+ {
+ surf = SDL_CreateRGBSurface(surface_type,width,\
+ height,24,0xfc0000,0x03f000,0x000fc0,0x000030);
+ break;
+ }
+ case 32:
+ {
+ surf = SDL_CreateRGBSurface(surface_type,width,\
+ height,32,0xff000000,0x00ff0000,0x0000ff00,0x000000ff);
+ break;
+ }
+ default:
+ {
+ surf = NULL;
+ break;
+ }
+ }
+
+ if (surf == NULL)
+ sdl_quit("Bad Surface Creation!");
+
+ return surf;
+}
+
+/* Take a rectangle in terminal coordinates and then transform it into
+screen coordinates; td is the term_data that this rect belongs to */
+void term_to_screen(SDL_Rect *termrect, term_data *td)
+{
+ termrect->x += td->rect.x;
+ termrect->y += td->rect.y;
+}
+
+/* Do the opposite, take a rectangle in screen coordinates and transform
+it into the terminal coordinates of the given term_data */
+void screen_to_term(SDL_Rect *scrrect, term_data *td)
+{
+ scrrect->x -= td->rect.x;
+ scrrect->y -= td->rect.y;
+}
+
+/* A macro that determines if the 'top' rectangle completely occludes the
+'bottom' rectangle */
+#define BLOCKS(top,bottom) \
+( (top.x <= bottom.x) & ((top.x+top.w)>=(bottom.x+bottom.w)) & \
+ (top.y <= bottom.y) & ((top.y+top.h)>=(bottom.y+bottom.h)) )
+
+#define INTERSECT(r1,r2) \
+!( ( (r1.x > (r2.x+r2.w)) | (r2.x > (r1.x+r1.w)) ) & \
+ ( (r1.y > (r2.y+r2.h)) | (r2.y > (r1.y+r1.h)) ) )
+
+/* A function to calculate the intersection of two rectangles. Takes base
+rectangle and then updates it to include only the rectangles that intersect
+with the test rectangle. If there is an intersection, the function returns
+TRUE and base now contains the intersecting rectangle. If there is no
+intersection, then the function returns FALSE */
+bool intersectRects(SDL_Rect *base, SDL_Rect *test)
+{
+ if (INTERSECT((*base),(*test)))
+ {
+ /* Scoot the x-coordinates for the left side*/
+ if ( test->x > base->x )
+ {
+ base->w -= test->x - base->x;
+ base->x = test->x;
+ }
+ /* Scoot the x-coordinates for the right side*/
+ if ( (test->x + test->w) < (base->x + base->w) )
+ {
+ base->w = test->x + test->w - base->x;
+ }
+ /* Scoot the upper y-coordinates */
+ if ( test->y > base->y )
+ {
+ base->h -= test->y - base->y;
+ base->y = test->y;
+ }
+ /* Scoot the lower y-coordinates */
+ if ( (test->y + test->h) < (base->y + base->h) )
+ {
+ base->h = test->y + test->h - base->y;
+ }
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+/* A function to calculate the join of two rectangles; the first argument is
+changed to the joined rectangle */
+SDL_Rect joinRects(SDL_Rect *r1, SDL_Rect *r2)
+{
+ SDL_Rect out = {0,0,0,0};
+
+ if ( (r1 != NULL) & (r2 != NULL) )
+ {
+ /* Lower x-coordinate */
+ if ( r2->x < r1->x )
+ out.x = r2->x;
+ else
+ out.x = r1->x;
+ /* Upper x-coordinate */
+ if ( (r2->x+r2->w) > (r1->x+r1->w) )
+ out.w = (r2->x+r2->w) - out.x;
+ else
+ out.w = (r1->x+r1->w) - out.x;
+ /* Lower y-coordinate */
+ if ( r2->y < r1->y )
+ out.y = r2->y;
+ else
+ out.y = r1->y;
+ if ( (r2->y+r2->h) > (r1->y+r1->h) )
+ out.h = (r2->y+r2->h) - out.y;
+ else
+ out.h = (r1->y+r1->h) - out.y;
+ }
+ return out;
+}
+
+/* Given a term_data (and its associated screen) and a rectangle in terminal
+coordinates (with NULL signifying to take the whole terminal surface), blit
+graphics from the term_data surface to the screen, using the term_data's rect
+to indicate how terminal coordinates transform into screen coordinates.
+This is complicated, however, by the possibility that the indicated area may be
+occluded by overlaying terminals. In this case, if the target area is
+completely occluded, nothing will be done. If partially occluded, it will be
+drawn, but occluding terminals will then re-blit to re-cover the area. */
+void drawTermStuff(term_data *td, SDL_Rect *rect)
+{
+ int n = 0, i;
+ bool block = FALSE, cover = FALSE;
+ SDL_Rect spot, isect_term, isect_scr;
+
+ /* first of all, if updating is suspended, do nothing! */
+ if (!suspendUpdate)
+ {
+ /* find out which number in the ordered stack of screens that this
+ terminal is */
+ while ((term_order[n] != td) & (n < MAX_CONSOLE_COUNT))
+ {
+ n++;
+ }
+ if (n == MAX_CONSOLE_COUNT)
+ printf("Could not find terminal in display list...\n");
+ /* now loop through and see if any terminals completely occlude
+ the desired spot; if num=0, note that this will be skipped */
+ if (rect == NULL)
+ {
+ /* Grab the whole terminal screen */
+ spot.x = 0; spot.y = 0;
+ spot.w = td->surf->w; spot.h = td->surf->h;
+ }
+ else
+ {
+ /* Just copy the given area */
+ spot.x = rect->x; spot.y = rect->y;
+ spot.w = rect->w; spot.h = rect->h;
+ }
+ term_to_screen(&spot,td);
+ i = n;
+ while (i--)
+ {
+ if (BLOCKS(term_order[i]->rect,spot))
+ {
+ /* Higher terminal completely occludes this spot */
+ block = TRUE;
+ DB(" Blocks!");
+ }
+ else if (INTERSECT(term_order[i]->rect,spot))
+ {
+ /* Partial occlusion */
+ cover = TRUE;
+ DB(" Covers!");
+ }
+ }
+ /* If any of the higher terminals blocked, then don't do
+ anything */
+ if (!block)
+ {
+ /*printf("Blitting to %d %d %d %d\n",spot.x,spot.y,spot.w,spot.h);*/
+ /* First of all, draw the graphics */
+ SDL_BlitSurface(td->surf,rect,screen,&spot);
+ if (cover)
+ {
+ printf("covering...");
+ /* There are covering terminals, so go through and blit all
+ partially occluding ones */
+ while (n--)
+ {
+ /* copy spot to find the intersect */
+ isect_scr.x = spot.x; isect_scr.y = spot.y;
+ isect_scr.w = spot.w; isect_scr.h = spot.h;
+ if (intersectRects(&isect_scr,&(term_order[n]->rect)))
+ {
+ /* this terminal intersects... re-blit */
+ /* first, convert to term coordinates */
+ isect_term.x = isect_scr.x; isect_term.y = isect_scr.y;
+ isect_term.w = isect_scr.w; isect_term.h = isect_scr.h;
+ screen_to_term(&isect_term,term_order[n]);
+ /* blit from term coordinates to screen coordinates */
+ SDL_BlitSurface(term_order[n]->surf,&isect_term,\
+ screen,&isect_scr);
+ }
+ }
+ }
+ /* Now update what was drawn */
+ DB("Update");
+ SDL_UpdateRects(screen,1,&spot);
+ }
+ }
+}
+
+/* utility routine for creating and setting the color of the cursor;
+it could be useful for setting a new cursor color if desired.
+Could later be expanded to do other stuff with the cursor,
+like a hollow rectangle a la main-win.c or even a graphic */
+void createCursor(byte r, byte g, byte b, byte a)
+{
+ /* free the cursor if it exists */
+ if (cursor != NULL)
+ SDL_FreeSurface(cursor);
+
+ /* and create it anew! (or the first time) */
+ cursor = createSurface(t_width,t_height);
+
+ /* be sure to use alpha channel when blitting! */
+ SDL_SetAlpha(cursor,SDL_SRCALPHA,0);
+
+ /* just set the color for now - drawing rectangles
+ needs surface locking for some setups */
+ cursor_color = SDL_MapRGBA(cursor->format,r,g,b,a);
+ SDL_LOCK(cursor);
+ SDL_FillRect(cursor,NULL,cursor_color);
+ SDL_UNLOCK(cursor);
+}
+
+/* Cursor Display routine - just blits the global cursor
+surface onto the correct location */
+static errr Term_curs_sdl(int x, int y)
+{
+#ifdef USE_ISO
+ highlite_spot(x, y);
+#else /* regular SDL */
+ term_data *td = (term_data*)(Term->data);
+ static SDL_Rect base;
+
+ /* calculate the position to place the cursor */
+ base.x = td->surf->clip_rect.x + x*t_width;
+ base.y = td->surf->clip_rect.y + y*t_height;
+ base.w = t_width;
+ base.h = t_height;
+
+ /* blit the cursor over top of the given spot;
+ note that surface should not be locked
+ (see note in Term_text_sdl() below) */
+ SDL_BlitSurface(cursor,NULL,td->surf,&base);
+
+ /* Now draw to the main screen */
+ drawTermStuff(td,&base);
+#endif /* USE_ISO */
+ /* Success */
+ return (0);
+}
+
+/* routine for wiping terminal locations - simply draws
+a black rectangle over the offending spots! */
+static errr Term_wipe_sdl(int x, int y, int n)
+{
+ static SDL_Rect base;
+ term_data *td = (term_data*)(Term->data);
+
+ /* calculate boundaries of the area to clear */
+ base.x = td->surf->clip_rect.x + x*t_width;
+ base.y = td->surf->clip_rect.y + y*t_height;
+ base.w = n*t_width;
+ base.h = t_height;
+
+ SDL_LOCK(td->surf);
+
+ /* blank the screen area */
+ SDL_FillRect(td->surf, &base, td->black);
+
+ SDL_UNLOCK(td->surf);
+
+ /* And... UPDATE the rectangle we just wrote to! */
+ drawTermStuff(td,&base);
+
+ /* Success */
+ return (0);
+}
+
+/* Perform a full clear of active terminal; redraw the borders.*/
+void eraseTerminal(void)
+{
+ static SDL_Rect base;
+ term_data *td = (term_data*)(Term->data);
+
+ /* temporarily remove clipping rectangle */
+ SDL_SetClipRect(td->surf,NULL);
+
+ SDL_LOCK(td->surf);
+ /* flood terminal with border color */
+ SDL_FillRect(td->surf,NULL,td->border_color);
+
+ /* get smaller rectangle to hollow out window */
+ base.x = td->border_thick;
+ base.y = td->border_thick;
+ base.w = td->rect.w - 2*td->border_thick;
+ base.h = td->rect.h - 2*td->border_thick;
+
+ /* hollow out terminal */
+ SDL_FillRect(td->surf,&base,td->black);
+
+ SDL_UNLOCK(screen);
+
+ /* reset clipping rectangle */
+ base.x += td->cushion_x_top;
+ base.y += td->cushion_y_top;
+ base.w -= td->cushion_x_top + td->cushion_x_bot;
+ base.h -= td->cushion_y_top + td->cushion_y_bot;
+ SDL_SetClipRect(td->surf,&base);
+ printf("Clip rect: %d %d %d %d\n",base.x,base.y,base.w,base.h);
+ /* And... UPDATE the whole thing */
+ drawTermStuff(td,NULL);
+
+}
+
+/*
+ * Draw some text on the screen
+ *
+ * This function should actually display an array of characters
+ * starting at the given location, using the given "attribute",
+ * and using the given string of characters, which contains
+ * exactly "n" characters and which is NOT null-terminated.
+ *
+ * You may assume "valid" input if the window is properly sized.
+ *
+ * You must be sure that the string, when written, erases anything
+ * (including any visual cursor) that used to be where the text is
+ * drawn. On many machines this happens automatically, on others,
+ * you must first call "Term_wipe_xxx()" to clear the area.
+ *
+ * In color environments, you should activate the color contained
+ * in "color_data[a & 0x0F]", if needed, before drawing anything.
+ *
+ * You may ignore the "attribute" if you are only supporting a
+ * monochrome environment, since this routine is normally never
+ * called to display "black" (invisible) text, including the
+ * default "spaces", and all other colors should be drawn in
+ * the "normal" color in a monochrome environment.
+ *
+ * Note that if you have changed the "attr_blank" to something
+ * which is not black, then this function must be able to draw
+ * the resulting "blank" correctly.
+ *
+ * Note that this function must correctly handle "black" text if
+ * the "always_text" flag is set, if this flag is not set, all the
+ * "black" text will be handled by the "Term_wipe_xxx()" hook.
+ */
+static errr Term_text_sdl(int x, int y, int n, byte a, const char *cp)
+{
+#ifdef USE_ISO
+ if (a < 16)
+ {
+ set_spots(x, y, n, TRUE);
+ }
+ else
+ {
+ set_spots(x, y, n, FALSE);
+ }
+#else
+ term_data *td = (term_data*)(Term->data);
+ static SDL_Rect base;
+ SDL_Rect base_back;
+ int i = n;
+ char old = 0;
+
+ /* calculate place to clear off and draw to */
+ base.x = td->surf->clip_rect.x + x*td->tile_width;
+ base.y = td->surf->clip_rect.y + y*td->tile_height;
+ base.w = n*td->tile_width;
+ base.h = td->tile_height;
+
+ base_back = base;
+
+ SDL_LOCK(screen);
+
+ /* blank the drawing area */
+ SDL_FillRect(td->surf, &base, td->black);
+
+ SDL_UNLOCK(screen);
+
+ /* Note that SDL docs specify that SDL_BlitSurface should not be called
+ on locked surfaces... since the character printing routine below revolves
+ around blitting, the surface has been unlocked first*/
+
+ /* loop through the input string, drawing characters */
+ i = n;
+ old = 0;
+ while (i--)
+ {
+ /* Output the character... */
+ /* If character has not changed, then just blit the old surface into
+ the new location to save effort*/
+ if (*cp == old)
+ {
+ /* the desired character/color combo is already on the work surf */
+ /* just blit it! */
+ SDL_BlitSurface(worksurf,NULL,td->surf,&base);
+ } else {
+ /* copy the desired character onto working surface */
+ SDL_BlitSurface(text[*cp],NULL,worksurf,NULL);
+ /* color our crayon surface with the desired color */
+ SDL_FillRect(crayon,NULL,color_data[a&0x0f]);
+ /* apply the color to the character on the working surface */
+ SDL_BlitSurface(crayon,NULL,worksurf,NULL);
+ /* and blit it onto our screen! */
+ SDL_BlitSurface(worksurf,NULL,td->surf,&base);
+ }
+ /* Move to the next position */
+ base.x += t_width;
+ /* Store the old character */
+ old = *cp;
+ /* Increment the character pointer */
+ cp++;
+ }
+
+ /* And update */
+ drawTermStuff(td,&base_back);
+
+#endif /* USE_ISO */
+ /* Success */
+ return (0);
+}
+
+/*
+ * Draw some attr/char pairs on the screen
+ *
+ * This routine should display the given "n" attr/char pairs at
+ * the given location (x,y). This function is only used if one
+ * of the flags "always_pict" or "higher_pict" is defined.
+ *
+ * You must be sure that the attr/char pairs, when displayed, will
+ * erase anything (including any visual cursor) that used to be at
+ * the given location. On many machines this is automatic, but on
+ * others, you must first call "Term_wipe_xxx(x, y, 1)".
+ *
+ * With the "higher_pict" flag, this function can be used to allow
+ * the display of "pseudo-graphic" pictures, for example, by using
+ * the attr/char pair as an encoded index into a pixmap of special
+ * "pictures".
+ *
+ * With the "always_pict" flag, this function can be used to force
+ * every attr/char pair to be drawn by this function, which can be
+ * very useful if this file can optimize its own display calls.
+ *
+ * This function is often associated with the "arg_graphics" flag.
+ *
+ * This function is only used if one of the "higher_pict" and/or
+ * "always_pict" flags are set.
+ */
+#ifndef USE_ISO
+static errr Term_pict_sdl(int x, int y, int n, const byte *ap, const char *cp)
+{
+ term_data *td = (term_data*)(Term->data);
+ DB("Term_pict_sdl");
+ /* XXX XXX XXX */
+
+#else
+// for ISO-view we need USE_TRANSPARENCY and USE_EGO_GRAPHICS defined
+static errr Term_pict_sdl(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp, const byte *eap, const char *ecp)
+{
+ /* Hajo: memorize output */
+ memcpy(&iso_ap[y][x], ap, n);
+ memcpy(&iso_cp[y][x], cp, n);
+ memcpy(&iso_atp[y][x], tap, n);
+ memcpy(&iso_ctp[y][x], tcp, n);
+ memcpy(&iso_aep[y][x], eap, n);
+ memcpy(&iso_cep[y][x], ecp, n);
+
+ // here is no text
+ set_spots(x, y, n, FALSE);
+
+#endif /* USE_ISO */
+ /* Success */
+ return (0);
+}
+
+/*************************************************
+ SPECIAL TERMINAL WINDOW MANIPULATION ROUTINES
+ *************************************************/
+
+/* macro for bounding a value between two given values */
+#define BOUND(val,low,high) \
+if (val < low) \
+{ \
+ val = low; \
+} \
+else if (val > high) \
+{ \
+ val = high; \
+}
+
+/* two macros to get the adjusted maximums for window
+positions... eg the screen width minus the width of the
+window is the maximum x-position that the window can
+be set at. */
+#define MAX_X(td) \
+( arg_width - td->rect.w )
+
+#define MAX_Y(td) \
+( arg_height - td->rect.h )
+
+/* another two macros that give maximum window widths
+based on screen size and current window position together
+width tile widths/heights */
+#define MAX_WIDTH(td) \
+( (int)floorf((arg_width - td->rect.x - 2*td->border_thick - \
+ td->cushion_x_bot - td->cushion_x_top )/td->tile_width))
+
+#define MAX_HEIGHT(td) \
+( (int)floorf((arg_height - td->rect.y - 2*td->border_thick - \
+ td->cushion_y_bot - td->cushion_y_top )/td->tile_height))
+
+/* update the width and height of given term's rectangle by simply
+multiplying the tile count by tile size and adding in cushions and
+borders */
+#define UPDATE_SIZE(td) \
+ td->rect.w = (td->cols)*td->tile_width + td->cushion_x_top \
+ + td->cushion_x_bot + 2*td->border_thick; \
+ td->rect.h = (td->rows)*td->tile_height + td->cushion_y_top \
+ + td->cushion_y_bot + 2*td->border_thick
+
+void recompose(void);
+
+/* Resize the active terminal with new width and height.
+Note that his involves a complicated sequence of events...
+Details to follow below! */
+void resizeTerminal(int width, int height)
+{
+ term_data *td = (term_data*)(Term->data);
+
+ /* First of all, bound the input width and height to satisfy
+ these conditions:
+ - The main ToME window should be at least 80 cols, 24 rows
+ - no part of each window should be drawn off screen....
+ I'm including borders in this restriction!
+ But no bounds checking needs to take place if the input width
+ and height are unchanged....
+ */
+
+ if (td == &data[0])
+ {
+ /* The active terminal is the main ToME window...
+ don't let the width get below 80, don't let the heights below
+ 24, and don't let it leak off of the edge! */
+ if (width != td->cols)
+ {
+ BOUND(width,80,MAX_WIDTH(td));
+ }
+ if (height != td->rows)
+ {
+ BOUND(height,24,MAX_HEIGHT(td));
+ }
+ }
+ else
+ {
+ /* This is not the main window... just make sure it
+ doesn't shrink to nothing or go past the edge */
+ if (width != td->cols)
+ {
+ BOUND(width,1,MAX_WIDTH(td));
+ }
+ if (height != td->rows)
+ {
+ BOUND(height,1,MAX_HEIGHT(td));
+ }
+ }
+
+ /* Okay, now make sure that something has ACTUALLY changed
+ before doing anything */
+ if ((width != td->cols) || (height != td->rows))
+ {
+
+ /* Now, ask zterm to please resize the term structure! */
+ Term_resize(width,height);
+
+ /* Reactivate, since Term_resize seems to activate the
+ main window again...*/
+ Term_activate(&td->t);
+
+ /* It might not have resized completely to the new
+ size we wanted (some windows have size limits it seems,
+ like the message window). So, update our structure with
+ the size that were actually obtained.*/
+ td->cols = Term->wid;
+ td->rows = Term->hgt;
+
+ /* And recalculate the sizes */
+ UPDATE_SIZE(td);
+
+ /* Create a new surface that can hold the updated size */
+ SDL_FreeSurface(td->surf);
+ td->surf = createSurface(td->rect.w,td->rect.h);
+
+ /* Now we should be in business for a complete redraw! */
+ Term_redraw();
+
+ /* Re-blit everything so it looks good */
+ recompose();
+
+ /* That's it! */
+ }
+}
+
+/* Move the terminal around... a much simpler action that involves
+just changing the pos_x/pos_y values and redrawing!*/
+void moveTerminal(int x, int y)
+{
+ term_data *td = (term_data*)(Term->data);
+
+ /* Now, the window is being shifted about... much simpler
+ situation to handle! But of course, the window must not
+ drift too far or else parts will be hanging off the screen
+ and may lead to errors - bound the input positions to
+ prevent this unfortunate situation... do nothing if the
+ input is no different than the current */
+ if (x != td->rect.x)
+ {
+ BOUND(x,0,MAX_X(td));
+ }
+ if (y != td->rect.y)
+ {
+ BOUND(y,0,MAX_Y(td));
+ }
+
+ /* Okay, now make sure that something changed before doing
+ anything */
+ if ((x != td->rect.x) || (y != td->rect.y))
+ {
+ /* Now update OUR structure */
+ td->rect.x = x;
+ td->rect.y = y;
+
+ /* Then do a reblit to see the results */
+ recompose();
+
+ /* That's it! */
+ }
+}
+
+/* Routine to bring a given term_data to the top of the drawing stack */
+void bringToTop(int current)
+{
+ term_data *td;
+ term_data *tc;
+ int n = 0;
+ int i;
+
+ /* Get the pointer to the desired term_data from the data structure */
+ td = &data[current];
+
+ printf("Current stack: \n");
+ for (i=0;i<arg_console_count;i++)
+ {
+ printf(" %d: %p\n",i,term_order[i]);
+ }
+ printf("\n");
+
+ /* Find the number in the term_order stack */
+ while ((term_order[n] != td) & (n < MAX_CONSOLE_COUNT))
+ {
+ n++;
+ }
+ if (n == MAX_CONSOLE_COUNT)
+ printf("Could not find terminal in display list...\n");
+
+ printf("Order is %d\n",n);
+
+ /* Now move all lower-indexed pointers up one index */
+ while (n)
+ {
+ printf(" move %d to %d\n",n-1,n);
+ printf(" %p\n",term_order[n-1]);
+ printf(" %p\n",term_order[n]);
+ term_order[n] = term_order[n-1];
+ n--;
+ }
+ /* And stick this term_data pointer on top */
+ term_order[0] = td;
+
+ printf("Final stack: \n");
+ for (i=0;i<arg_console_count;i++)
+ {
+ printf(" %d: %p\n",i,term_order[i]);
+ }
+ printf("\n");
+
+}
+
+/* This utility routine will cycle the active term to the
+next available in the data[] array. It will then do a
+redraw of this term so that it is ready to be manipulated.
+The input is the current active terminal, and the output is
+the new active terminal */
+int cycleTerminal(int current)
+{
+ /* redraw the current term to get rid of its purple
+ border */
+ data[current].border_color = data[current].white;
+ Term_redraw();
+
+ /* increment the terminal number*/
+ current++;
+ /* now do a little modulo cycle action and
+ activate the next term! */
+ current %= arg_console_count;
+ Term_activate(&(data[current].t));
+
+ /* before redrawing, set the border color to purple to
+ indicate that this terminal is being manipulated*/
+ data[current].border_color = data[current].purple;
+
+ /* then bring this terminal to the top of the order, so it is drawn on
+ top during manipulation mode */
+ bringToTop(current);
+
+ /* and do a complete redraw */
+ Term_redraw();
+
+ /* return the current terminal... */
+ return current;
+}
+
+/* This routine will simply re-blit all of the surfaces onto the main screen,
+respecting the current term_order */
+void recompose(void)
+{
+ int i = arg_console_count;
+ /* do a complete screen wipe */
+ SDL_LOCK(screen);
+ SDL_FillRect(screen,NULL,screen_black);
+ SDL_UNLOCK(screen);
+
+ /* cycle through the term_order */
+ while (i--)
+ {
+ SDL_BlitSurface(term_order[i]->surf,NULL,screen,&(term_order[i]->rect));
+ }
+
+ /* Update everything */
+ SDL_REDRAW_SCREEN;
+}
+
+/* This utility routine will completely blank the screen and
+then cycle through all terminals, performing a Term_redraw()
+on each and every term that is being used (according to
+arg_term_count that is). The terminals will be redrawn
+last-to-first, so that the main is over top of everything */
+void redrawAllTerminals(void)
+{
+ int i = arg_console_count;
+ DB("Total redraw");
+ /* do a complete screen wipe */
+ SDL_LOCK(screen);
+ SDL_FillRect(screen,NULL,screen_black);
+ SDL_UNLOCK(screen);
+
+ while (i--)
+ {
+ /* Re-order the terminals */
+ term_order[i] = &data[i];
+ }
+
+ i = arg_console_count;
+ /* cycle down through each terminal */
+ while (i--)
+ {
+ /* Activate this terminal */
+ Term_activate(&(data[i].t));
+
+ /* Make its border white since manipulation mode is over */
+ data[i].border_color = data[i].white;
+
+ /* And redraw it */
+ Term_redraw();
+ }
+ /* Loop will end on i=0 ! */
+
+ printf("Current stack: \n");
+ for (i=0;i<arg_console_count;i++)
+ {
+ printf(" %d: %p\n",i,term_order[i]);
+ }
+ printf("\n");
+
+ /* now update the screen completely, just in case*/
+ SDL_REDRAW_SCREEN;
+}
+
+/* This is the special event handling function for doing
+terminal window manipulation! When special manipulation
+mode is activated, execution goes here. This special mode
+has its own keypresses. To begin with, the main terminal
+border is highlighted (in purple) to indicate that it is
+being manipulated. The following keypresses are accepted:
+-Space: switches between editing modes. The system begins
+ in position editing mode, and Enter will toggle size
+ (row/col) editing mode.
+-Arrows: increments/decrements the position/size in an
+ intuitive way! ;) Some modifiers are accepted in order
+ to speed things up on very high resolution screens:
+ . with shift down, increment is five
+ . with ctrl down, increment is ten
+ . with both, increment is fifty!
+ Of course, no movement or resize can cause the window
+ to leave the confines of the screen, so using the big
+ jump is safe.
+-Enter: cycles to the next available terminal to edit.
+-Escape: quits manipulation mode, performing one final
+ redraw to take into account all changes.
+*/
+void manipulationMode(void)
+{
+ term_data *td;
+ SDL_Event event;
+ bool done = FALSE, moveMode = TRUE;
+ int mouse_x, mouse_y;
+ int value = 0, delta_x = 0, delta_y = 0;
+ int current_term;
+ SDL_Surface backup;
+
+ /* Begin by redrawing the main terminal with its
+ purple border to signify that it is being edited*/
+
+ /* start with the main terminal */
+ current_term = 0;
+
+ /* get the pointer */
+ td = &data[0];
+
+ /* before redrawing, set the border color to purple to
+ indicate that this terminal is being manipulated*/
+ td->border_color = td->purple;
+
+ /* and do a complete redraw */
+ DB("Term_redraw");
+ Term_redraw();
+
+ /* Now keep looping until Esc has been pressed. */
+ while (!done)
+ {
+ /* Get the keypress event */
+ SDL_WaitEvent(&event);
+ /* Make sure that it is a keypress */
+ if (event.type == SDL_KEYDOWN)
+ {
+ /* Act on the keypress! */
+ switch (event.key.keysym.sym)
+ {
+ case SDLK_ESCAPE:
+ {
+ /* Escape has been pressed, so we're done!*/
+ done = TRUE;
+ break;
+ }
+ case SDLK_SPACE:
+ {
+ /* Space has been pressed: toggle move mode */
+ moveMode = ( moveMode ? FALSE : TRUE );
+ break;
+ }
+ case SDLK_RETURN:
+ {
+ /* Return... cycle the terminals!
+ update the current_term appropriately*/
+ current_term = cycleTerminal(current_term);
+
+ /* Get the new term_data */
+ td = &data[current_term];
+
+ break;
+ }
+ case SDLK_RIGHT:
+ case SDLK_LEFT:
+ case SDLK_DOWN:
+ case SDLK_UP:
+ {
+ /* Increase either the x-position or column
+ width - multiply according to modifiers */
+ value = 1;
+ if (SDL_GetModState() & KMOD_SHIFT)
+ {
+ /* shift is down... a muliplier of 5 */
+ value *= 5;
+ }
+ if (SDL_GetModState() & KMOD_CTRL)
+ {
+ /* control is down... multiply by 10 */
+ value *= 10;
+ }
+
+ /* Now, behavior depends on which key was pressed
+ and whether we are in moveMode resize mode... */
+
+ /* First, set the delta_x/y based on key */
+ if (event.key.keysym.sym == SDLK_RIGHT)
+ {
+ delta_x = 1;
+ delta_y = 0;
+ }
+ if (event.key.keysym.sym == SDLK_LEFT)
+ {
+ delta_x = -1;
+ delta_y = 0;
+ }
+ if (event.key.keysym.sym == SDLK_DOWN)
+ {
+ delta_x = 0;
+ delta_y = 1;
+ }
+ if (event.key.keysym.sym == SDLK_UP)
+ {
+ delta_x = 0;
+ delta_y = -1;
+ }
+
+ /* Now either moveTerminal() or
+ resizeTerminal() based on value of
+ moveMode! */
+ if (moveMode)
+ {
+ moveTerminal(td->rect.x + value*delta_x,\
+ td->rect.y + value*delta_y);
+ }
+ else
+ {
+ resizeTerminal(td->cols + value*delta_x,\
+ td->rows + value*delta_y);
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+ else if (event.type == SDL_MOUSEBUTTONDOWN)
+ {
+ /* Store the coordinates where the button was pressed */
+ mouse_x = event.button.x;
+ mouse_y = event.button.y;
+ }
+ else if (event.type == SDL_MOUSEMOTION)
+ {
+ /* Mouse is moving... maybe move or resize the window, based
+ on the state of the mouse buttons */
+
+ /* To keep the motion quick, temporarily ignore all mouse motion
+ events until window moving is complete */
+ SDL_EventState(SDL_MOUSEMOTION,SDL_IGNORE);
+
+ if(event.motion.state & SDL_BUTTON(1))
+ {
+ /* the left mouse button is down, move the window,
+ do a differential based on where the button was pressed */
+ moveTerminal(td->rect.x + (event.motion.x - mouse_x), \
+ td->rect.y + (event.motion.y - mouse_y));
+ /* save the most current mouse location */
+ SDL_GetMouseState(&mouse_x,&mouse_y);
+ }
+
+ if(event.motion.state & SDL_BUTTON(3))
+ {
+ /* the right mouse button is down, so resize the window;
+ do a differential, but divide the number by the tile sizes */
+
+ /* see if at least one whole tile width/height has been
+ reached */
+ int delta_cols, delta_rows;
+ delta_cols = (int)floorf(\
+ (float)(event.motion.x - mouse_x)/td->tile_width);
+ delta_rows = (int)floorf(\
+ (float)(event.motion.y - mouse_y)/td->tile_height);
+ if ( delta_cols || delta_rows )
+ {
+ /* something changed, so update */
+ resizeTerminal(td->cols + delta_cols, \
+ td->rows + delta_rows);
+ /* save the most current mouse location */
+ SDL_GetMouseState(&mouse_x,&mouse_y);
+ }
+ }
+
+ /* Deal with mouse motion again */
+ SDL_EventState(SDL_MOUSEMOTION,SDL_ENABLE);
+
+ }
+ }
+ /* Perform the last redraw to take all changes
+ into account */
+ redrawAllTerminals();
+}
+
+/*************************************************
+ INITIALIZATION ROUTINES
+ *************************************************/
+
+static errr term_data_init(term_data *td, int i)
+{
+ term *t = &(td->t);
+ char env_var[80];
+ cptr val;
+
+
+ /***** load position, size information */
+
+ int cols, rows, x, y;
+
+ /* grab the column and row counts from
+ environmental variables for now */
+ sprintf(env_var,"TOME_NUM_COLS_%d",i);
+ val = getenv(env_var);
+ /* make sure it is valid */
+ if (val != NULL)
+ {
+ cols = atoi(val);
+ /* now make sure that the main window will
+ have at least 80x24 */
+ if (td == &data[0])
+ {
+ /* can't really pick an upper bound without
+ knowing what the position is... oh well. */
+ BOUND(cols,80,255);
+ }
+ }
+ else
+ {
+ /* no environmental variable... have to guess
+ something. If it's the main window, choose
+ the minimum. */
+ if (td == &data[0])
+ cols = 80;
+ else
+ cols = 5;
+ }
+ /* do the rows */
+ sprintf(env_var,"TOME_NUM_ROWS_%d",i);
+ val = getenv(env_var);
+ /* make sure it is valid */
+ if (val != NULL)
+ {
+ rows = atoi(val);
+ /* now make sure that the main window will
+ have at least 80x24 */
+ if (td == &data[0])
+ {
+ /* can't really pick an upper bound without
+ knowing what the position is... oh well. */
+ BOUND(rows,24,128);
+ }
+ }
+ else
+ {
+ /* no environmental variable... have to guess
+ something. If it's the main window, choose
+ the minimum. */
+ if (td == &data[0])
+ rows = 24;
+ else
+ rows = 3;
+ }
+ /* store these values in the term_data structure */
+ td->rows = rows;
+ td->cols = cols;
+
+ /* the position will be loaded from environmental
+ variables as well - for the time being*/
+ /* x-location */
+ sprintf(env_var,"TOME_X_POS_%d",i);
+ val = getenv(env_var);
+ /* make sure it is valid */
+ if (val != NULL)
+ {
+ x = atoi(val);
+ /* now do intelligent position checking */
+ BOUND(x,0,MAX_X(td));
+ }
+ else
+ {
+ /* no variable, choose something */
+ x = 20*i;
+ }
+ /* y-location */
+ sprintf(env_var,"TOME_Y_POS_%d",i);
+ val = getenv(env_var);
+ /* make sure it is valid */
+ if (val != NULL)
+ {
+ y = atoi(val);
+ /* position checking again */
+ BOUND(y,0,MAX_Y(td));
+ }
+ else
+ {
+ /* no variable */
+ y = 20*i;
+ }
+ /* and store these values into the structure */
+ td->rect.x = x;
+ td->rect.y = y;
+
+ /*********** term structure initializing */
+
+ /* Initialize the term
+ gets: pointer to address, number of columns, number of rows, number
+ of keypresses to queue up (guess 24?)*/
+ term_init(t, cols, rows, 24);
+
+ /* Use a "soft" cursor */
+ t->soft_cursor = TRUE;
+
+ /* Picture routine flags */
+ t->always_pict = FALSE;
+ t->higher_pict = FALSE;
+ t->always_text = FALSE;
+
+ /* Erase with "white space" */
+ t->attr_blank = TERM_WHITE;
+ t->char_blank = ' ';
+
+ /* Hooks */
+ t->xtra_hook = Term_xtra_sdl;
+ t->curs_hook = Term_curs_sdl;
+ t->wipe_hook = Term_wipe_sdl;
+ t->text_hook = Term_text_sdl;
+#ifdef USE_ISO
+ t->pict_hook = Term_pict_sdl;
+#endif /* USE_ISO */
+
+ /* Save the data */
+ t->data = td;
+
+ /* Activate (important) */
+ Term_activate(t);
+
+ /************* finish term_data intializing */
+
+ /* name of this term window */
+ td->name = angband_term_name[i];
+
+ /* For now, all font is the same size... use global t_width/height */
+ td->tile_width = t_width;
+ td->tile_height = t_height;
+
+ td->cushion_x_top = 1;
+ td->cushion_x_bot = 1;
+ td->cushion_y_top = 1;
+ td->cushion_y_bot = 1;
+
+ /* Now calculate the total width and height*/
+ UPDATE_SIZE(td);
+
+ /* Create a surface to draw to */
+ td->surf = createSurface(td->rect.w,td->rect.h);
+ SDL_SetAlpha(td->surf,0,0);
+
+ /* Key some colors to this surface */
+ td->black = SDL_MapRGB(td->surf->format, 0, 0, 0);
+ td->white = SDL_MapRGB(td->surf->format,255,255,255);
+ td->purple = SDL_MapRGB(td->surf->format,255, 0,255);
+
+ /* Turn on a border, thickness specified by BORDER_THICKNESS */
+ td->border_thick = BORDER_THICKNESS;
+
+ /* make the default terminal border color to be white */
+ td->border_color = td->white;
+
+
+ printf("Init-int term: %d\n",i);
+#ifdef USE_GRAPHICS
+#ifdef USE_TRANSPARENCY
+#endif
+#endif
+
+ /* Success */
+ return (0);
+}
+
+/* dumpWindowSettings is responsible for exporting all current
+values of the window positions, etc. to the screen, so that
+the user can see what the final values were after tweaking */
+void dumpWindowSettings(void)
+{
+ char name[80];
+ char value[8];
+ int i;
+
+ DB("Dumping settings");
+ printf("---------------------------\n");
+ /* cycle through each available terminal */
+ for (i=0; i<arg_console_count; i++)
+ {
+ printf("Terminal %d:\n",i);
+ /* get the name, and value of each value to dump */
+ sprintf(name,"TOME_X_POS_%d",i);
+ sprintf(value,"%d",data[i].rect.x);
+ printf("%s=%s\n",name,value);
+
+ sprintf(name,"TOME_Y_POS_%d",i);
+ sprintf(value,"%d",data[i].rect.y);
+ printf("%s=%s\n",name,value);
+
+ sprintf(name,"TOME_NUM_COLS_%d",i);
+ sprintf(value,"%d",data[i].cols);
+ printf("%s=%s\n",name,value);
+
+ sprintf(name,"TOME_NUM_ROWS_%d",i);
+ sprintf(value,"%d",data[i].rows);
+ printf("%s=%s\n",name,value);
+
+ /* Simple! */
+ printf("\n");
+ }
+}
+
+/* The main-sdl initialization routine!
+This routine processes arguments, opens the SDL
+window, loads fonts, etc. */
+errr init_sdl(int argc, char **argv)
+{
+ int i, surface_type;
+ char filename[PATH_MAX + 1];
+ const char file_sep = '.';
+ /* Flags to pass to SDL_SetVideoMode */
+ int videoFlags;
+
+ /* Before sdl_quit could possible be called, need to make sure that the text
+ array is zeroed, so that sdl_quit->killFontAndAlphabet() doesn't try to free
+ SDL_Surfaces that don't exist ! */
+ memset(text,0,sizeof(text));
+
+ /* Also, clear out the term order array */
+ memset(term_order,0,sizeof(term_order));
+
+ /* initialize SDL */
+ if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
+ {
+ sdl_quit("Video initialization failed!");
+ }
+ DB("SDL Initialized!");
+
+ /* get video info, to be used for determining if hardware acceleration is
+ available, pixel format, etc.... */
+ videoInfo = SDL_GetVideoInfo();
+
+ /* Environment calls to retrieve specific settings...
+ Note that these can be overridden by the command-line
+ arguments that are handled below */
+ if(getenv("TOME_CONSOLE_COUNT"))
+ arg_console_count = atoi(getenv("TOME_CONSOLE_COUNT"));
+ if(getenv("TOME_SCREEN_WIDTH"))
+ arg_width = atoi(getenv("TOME_SCREEN_WIDTH"));
+ if(getenv("TOME_SCREEN_HEIGHT"))
+ arg_height = atoi(getenv("TOME_SCREEN_HEIGHT"));
+ if(getenv("TOME_SCREEN_BPP"))
+ arg_bpp = atoi(getenv("TOME_SCREEN_BPP"));
+ if(getenv("TOME_FONT_SIZE"))
+ arg_font_size = atoi(getenv("TOME_FONT_SIZE"));
+
+ /* Argument handling routine;
+ the argv pointer is already pointing at the '--'
+ argument, so just start from there, parsing each
+ option as it comes along */
+ for (i=1; i < argc ; i++)
+ {
+ /* Set the number of consoles to handle
+ (ie the number of windows) */
+ if (0 == strcmp(argv[i], "-n"))
+ {
+ if (++i == argc)
+ {
+ printf("Argument missing for option -n\n");
+ return -1;
+ }
+
+ arg_console_count = atoi(argv[i]);
+ if (arg_console_count <= 0 || \
+ arg_console_count > MAX_CONSOLE_COUNT)
+ {
+ printf("Invalid console count given.\n");
+ arg_console_count = 1;
+ }
+ }
+ /* Set the SDL window/screen width in pixels */
+ else if (0 == strcmp(argv[i], "-w"))
+ {
+ if (++i == argc)
+ {
+ printf("Argument missing for option -w\n");
+ return -1;
+ }
+
+ arg_width = atoi(argv[i]);
+ }
+ /* Set the SDL window/screen height in pixels */
+ else if (0 == strcmp(argv[i], "-h"))
+ {
+ if (++i == argc)
+ {
+ printf("Argument missing for option -h\n");
+ return -1;
+ }
+
+ arg_height = atoi(argv[i]);
+ }
+ /* Set the SDL window/screen color depth
+ (in bits per pixel -- only 8,16,32 are okay) */
+ else if (0 == strcmp(argv[i], "-bpp"))
+ {
+ if (++i == argc)
+ {
+ printf("Argument missing for option -bpp\n");
+ return -1;
+ }
+
+ arg_bpp = atoi(argv[i]);
+ if ( (arg_bpp != 8) && (arg_bpp != 16) \
+ && (arg_bpp != 24) && (arg_bpp != 32) )
+ {
+ printf("Invalid color depth. Must be either 8, 16, or 32 bpp!\n");
+ return -1;
+ }
+ }
+ /* see if new graphics are requested...*/
+ else if (0 == strcmp(argv[i], "-g"))
+ {
+ printf("New graphics (16x16) enabled!\n");
+ arg_graphics_type = GRAPHICS_16x16;
+ }
+ /* see if old graphics are requested...*/
+ else if (0 == strcmp(argv[i], "-o"))
+ {
+ printf("Old graphics (8x8) enabled!\n");
+ arg_graphics_type = GRAPHICS_8x8;
+ }
+
+ /* see if double width tiles are requested */
+ else if (0 == strcmp(argv[i], "-b"))
+ {
+ /* do nothing for now */
+ /* arg_double_width = TRUE; */
+ }
+ /* switch into full-screen at startup */
+ else if (0 == strcmp(argv[i], "-fs"))
+ {
+ DB("Full-screen enabled!");
+ arg_full_screen = TRUE;
+ }
+ /* change the font size */
+ else if (0 == strcmp(argv[i], "-s"))
+ {
+ if (++i == argc)
+ {
+ printf("Argument missing for option -s\n");
+ printf("Please specify font size!\n");
+ return -1;
+ }
+
+ arg_font_size = atoi(argv[i]);
+ }
+ /* change the font to use */
+ else if (0 == strcmp(argv[i], "-f"))
+ {
+ /* Can we please not be so MS Windows-specific? One of the main goals
+ of SDL in ToME was to be more portable. These file name hacks are
+ only the idiom of that one OS, though. -- Neil */
+ DB("Getting font name");
+ if (++i == argc)
+ {
+ printf("Argument missing for option -f\n");
+ printf("Please specify a true-type font found in /lib/xtra/font!\n");
+ return -1;
+ }
+
+ /* tokenize the font name so that no .ttf extension
+ is required */
+ strcpy(arg_font_name,\
+ strtok(argv[i],&file_sep));
+
+ /* and append the extension */
+ strcat(arg_font_name,".ttf");
+
+ /* print a little debug message, so
+ user sees what font was actually selected */
+ printf("\tUsing font: %s\n",arg_font_name);
+
+ /* maybe check to see if file is even
+ existant in /lib/xtra/font */
+ }
+
+ } /* end argument handling */
+
+ /* Make sure that the engine will shutdown SDL properly*/
+ quit_aux = sdl_quit;
+
+ /* Use the ToME logo and set the window name */
+ filename[PATH_MAX] = 0;
+ path_build(filename, PATH_MAX, ANGBAND_DIR_XTRA, "graf/icon.png");
+ SDL_WM_SetIcon(IMG_Load(filename), 0);
+ SDL_WM_SetCaption("ToME", "tome");
+
+ /* SDL video settings, dependent on whether hardware is available */
+ if (videoInfo->hw_available)
+ videoFlags = SDL_HWSURFACE;
+ else
+ videoFlags = SDL_SWSURFACE;
+
+ /* now set the video mode that has been configured */
+ screen = SDL_SetVideoMode( arg_width, arg_height, arg_bpp, videoFlags );
+
+ /* Verify there is a surface */
+ if ( !screen )
+ {
+ DB("No screen!");
+ sdl_quit("Failed to set SDL Surface.");
+ }
+
+ DB("Video Mode Set!");
+
+ /* now switch into full screen if asked for */
+ if (arg_full_screen)
+ SDL_WM_ToggleFullScreen(screen);
+
+ DB("SDL Window Created!");
+
+ /* Now ready the fonts! */
+
+ DB("initializing SDL_ttf");
+ if(TTF_Init()==-1) {
+ printf("TTF_Init: %s\n", TTF_GetError());
+ sdl_quit("Bah");
+ }
+
+ DB("loading font...");
+
+ /* load and render the font */
+ loadAndRenderFont(arg_font_name,arg_font_size);
+
+ /* Graphics! ----
+ If graphics are selected, then load graphical tiles! */
+ if (arg_graphics_type != NO_GRAPHICS)
+ {
+ /* load graphics tiles */
+ }
+
+ /* Initialize the working surface and crayon surface used for rendering
+ text in different colors. */
+
+ worksurf = createSurface(t_width,t_height);
+ crayon = createSurface(t_width,t_height);
+
+ /* The working surface will blit using alpha values... */
+ SDL_SetAlpha(worksurf,SDL_SRCALPHA,0);
+
+ /* Set up the colors using the great little color macros! */
+ color_data[0] = BLACK;
+ color_data[1] = WHITE;
+ color_data[2] = MID_GREY;
+ color_data[3] = BRIGHT_ORANGE;
+ color_data[4] = RED;
+ color_data[5] = GREEN;
+ color_data[6] = BRIGHT_BLUE;
+ color_data[7] = DARK_ORANGE;
+ color_data[8] = DARK_GREY;
+ color_data[9] = BRIGHT_GREY;
+ color_data[10] = PURPLE;
+ color_data[11] = YELLOW;
+ color_data[12] = BRIGHT_RED;
+ color_data[13] = BRIGHT_GREEN;
+ color_data[14] = AQUAMARINE;
+ color_data[15] = BROWN;
+
+ /* And setup the cursor, using the default color...
+ XXX - in the future, this should (and will) be loaded from prefs */
+ createCursor(DEF_CURSOR_COLOR);
+
+ /* Initialize the windows, or whatever that means in this case.
+ Do this in reverse order so that the main window is on top.*/
+ suspendUpdate = TRUE; /* draw everything at the end */
+ i = arg_console_count;
+ while (i--)
+ {
+ term_data *td = &data[i];
+
+ /* Initialize the term_data */
+ term_data_init(td, i);
+
+ /* Save global entry */
+ angband_term[i] = Term;
+
+ /* Add into term_order */
+ term_order[i] = td;
+
+ }
+
+ /* And setup the basic screen colors -- these are keyed to the format of
+ the main terminal surface */
+ screen_black = SDL_MapRGB(screen->format, 0, 0, 0);
+
+ suspendUpdate = FALSE; /* now draw everything */
+ redrawAllTerminals();
+ /*SDL_REDRAW_SCREEN;*/
+
+ /* now that the windows have been set, their settings can
+ be dumped upon quit! */
+ window_properties_set = TRUE;
+
+ /* Enable UNICODE keysyms - needed for current eventHandling routine */
+ SDL_EnableUNICODE(1);
+
+ /* Enable key repeat! */
+ SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL);
+
+ #ifdef USE_ISO
+ DB("Isometric view uses always graphics mode.\n");
+ use_graphics = TRUE;
+
+
+ /* Hajo: allocate memory for output data */
+ /* These arrays are read by the iso-view and written from this file */
+ iso_cp = halloc(data[0].t.wid, data[0].t.hgt);
+ iso_ap = halloc(data[0].t.wid, data[0].t.hgt);
+ iso_ctp = halloc(data[0].t.wid, data[0].t.hgt);
+ iso_atp = halloc(data[0].t.wid, data[0].t.hgt);
+ iso_cep = halloc(data[0].t.wid, data[0].t.hgt);
+ iso_aep = halloc(data[0].t.wid, data[0].t.hgt);
+
+ // Hmm, no ANGBAND_SYS in old iso-code
+ // if I change this I don't have to load the *.prf manually?
+ //
+ // seems not to work for the following:
+ /* Hajo: set mode */
+ ANGBAND_GRAF = "iso";
+
+ /* Hajo: init view */
+ init_adaptor();
+
+ center_player = TRUE;
+#endif /* USE_ISO */
+
+#ifdef USE_ISO
+ // Juergen: HACK, but this all is just for testing ...
+ data[0].t.higher_pict = TRUE;
+#endif
+
+ /* main-sdl initialized! */
+ return 0;
+}
+
+#endif