summaryrefslogtreecommitdiff
path: root/djgpp
diff options
context:
space:
mode:
Diffstat (limited to 'djgpp')
-rw-r--r--djgpp/file.c118
-rw-r--r--djgpp/gfx.c559
-rw-r--r--djgpp/install31
-rw-r--r--djgpp/install.c119
-rw-r--r--djgpp/main.c34
-rw-r--r--djgpp/mem.c262
-rw-r--r--djgpp/platgui.c4235
-rw-r--r--djgpp/runcmd.c143
-rw-r--r--djgpp/vstring.c48
9 files changed, 5549 insertions, 0 deletions
diff --git a/djgpp/file.c b/djgpp/file.c
new file mode 100644
index 0000000..5f5d49f
--- /dev/null
+++ b/djgpp/file.c
@@ -0,0 +1,118 @@
+/*
+
+ viDOOM - level editor for DOOM
+
+ Copyright (C) 2000 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ File system interfaces
+
+*/
+static const char rcs_id[]="$Id$";
+
+#include "config.h"
+#include <unistd.h>
+#include <string.h>
+
+
+/* ---------------------------------------- PRIVATE FUNCS
+*/
+static void ChangeDirsep(char *p)
+{
+ while(*p)
+ {
+ if (*p=='\\')
+ *p='/';
+
+ p++;
+ }
+}
+
+
+/* ---------------------------------------- EXPORTED FUNCS
+*/
+char *Pwd(void)
+{
+ static char s[PATH_MAX];
+
+ getcwd(s,PATH_MAX);
+
+ return(s);
+}
+
+void Cd(char *path)
+{
+ chdir(path);
+}
+
+char *Dirname(char *path)
+{
+ static char s[PATH_MAX];
+ char *p;
+
+ strcpy(s,path);
+
+ p=s+strlen(s)-1;
+
+ while((*p)&&(p>s))
+ if ((*p=='/')||(*p=='\\'))
+ *(p+1)=0;
+ else
+ p--;
+
+ return(s);
+}
+
+char *Basename(char *path)
+{
+ static char s[PATH_MAX];
+ char *p;
+
+ strcpy(s,path);
+
+ p=s+strlen(s)-1;
+
+ while(p>s)
+ if ((*p=='/')||(*p=='\\'))
+ return(p+1);
+ else
+ p--;
+
+ return(s);
+}
+
+int FileExists(char *path)
+{
+ return(__file_exists(path));
+}
+
+int FilenamesEqual(char *path1, char *path2)
+{
+ char p1[PATH_MAX],p2[PATH_MAX];
+
+ strcpy(p1,path1);
+ strcpy(p2,path2);
+
+ ChangeDirsep(p1);
+ ChangeDirsep(p2);
+
+ return(!strcasecmp(p1,p2));
+}
+
+
+/* END OF FILE */
diff --git a/djgpp/gfx.c b/djgpp/gfx.c
new file mode 100644
index 0000000..b93f6ea
--- /dev/null
+++ b/djgpp/gfx.c
@@ -0,0 +1,559 @@
+/*
+
+ viDOOM - level editor for DOOM
+
+ Copyright (C) 2000 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ Graphics functions
+
+*/
+static const char rcs_id[]="$Id$";
+
+#include "config.h"
+
+#include <stdio.h>
+#include <allegro.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <time.h>
+#include "gfx.h"
+#include "gui.h"
+#include "debug.h"
+
+
+/* ---------------------------------------- VARS
+*/
+#define COLDEP 16
+#define ACOL(c) (makecol_depth(COLDEP,((c)&0xff0000)>>16, \
+ ((c)&0xff00)>>8, \
+ ((c)&0xff)))
+
+static int init=FALSE;
+
+static BITMAP *bm;
+static int width;
+static int height;
+
+static int mbuttons;
+
+static int dirty_min_x;
+static int dirty_max_x;
+static int dirty_min_y;
+static int dirty_max_y;
+
+#define DIRTY(x,y) do { \
+ dirty_min_x=MIN(x,dirty_min_x); \
+ dirty_min_y=MIN(y,dirty_min_y); \
+ dirty_max_x=MAX((x)+1,dirty_max_x); \
+ dirty_max_y=MAX((y)+1,dirty_max_y); \
+ } while(0)
+
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+
+static void GetKey(GFXKey *key)
+{
+ static struct
+ {
+ int alleg;
+ int code;
+ } keym[]= {
+ {KEY_F1,GFX_F1},
+ {KEY_F2,GFX_F2},
+ {KEY_F3,GFX_F3},
+ {KEY_F4,GFX_F4},
+ {KEY_F5,GFX_F5},
+ {KEY_F6,GFX_F6},
+ {KEY_F7,GFX_F7},
+ {KEY_F8,GFX_F8},
+ {KEY_F9,GFX_F9},
+ {KEY_F10,GFX_F10},
+ {KEY_F11,GFX_F11},
+ {KEY_F12,GFX_F12},
+ {KEY_ESC,GFX_ESC},
+ {KEY_INSERT,GFX_INSERT},
+ {KEY_HOME,GFX_HOME},
+ {KEY_PGUP,GFX_PGUP},
+ {KEY_DEL,GFX_DELETE},
+ {KEY_END,GFX_END},
+ {KEY_PGDN,GFX_PGDN},
+ {KEY_UP,GFX_UP},
+ {KEY_DOWN,GFX_DOWN},
+ {KEY_LEFT,GFX_LEFT},
+ {KEY_RIGHT,GFX_RIGHT},
+ {KEY_ENTER,GFX_ENTER},
+ {KEY_BACKSPACE,GFX_BACKSPACE},
+ {KEY_TAB,GFX_TAB},
+ {-1,-1},
+ };
+ int f;
+ int k;
+
+ while(TRUE)
+ {
+ k=readkey();
+
+ key->shift=key_shifts&KB_SHIFT_FLAG;
+ key->ctrl=key_shifts&KB_CTRL_FLAG;
+ key->alt=key_shifts&KB_ALT_FLAG;
+
+ f=0;
+ while(keym[f].code!=-1)
+ {
+ if (keym[f].alleg==k>>8)
+ {
+ key->ascii=0;
+ key->code=keym[f].code;
+ return;
+ }
+
+ f++;
+ }
+
+ if (isprint(k&0xff))
+ {
+ key->ascii=(k&0xff);
+ key->code=GFX_ASCII;
+ return;
+ }
+ }
+}
+
+/* ---------------------------------------- EXPORTED FUNCTIONS
+*/
+void GFX_init(void)
+{
+ if (!init)
+ {
+ init=TRUE;
+ allegro_init();
+
+ install_keyboard();
+
+ install_timer();
+
+ if ((mbuttons=install_mouse())==-1)
+ GFX_exit(EXIT_FAILURE,"Failed to install mouse handler\n");
+
+ set_color_depth(COLDEP);
+ }
+}
+
+
+void GFX_close(void)
+{
+ if (init)
+ {
+ allegro_exit();
+ init=FALSE;
+ }
+}
+
+
+void GFX_open(int w,int h)
+{
+ height=h;
+ width=w;
+
+ if (set_gfx_mode(GFX_AUTODETECT,w,h,0,0)<0)
+ GFX_exit(EXIT_FAILURE,"Couldn't open screen of %dx%d\n",w,h);
+
+ if (!(bm=create_bitmap(w,h)))
+ GFX_exit(EXIT_FAILURE,"Couldn't create bitmap of %dx%d\n",w,h);
+
+ show_mouse(screen);
+}
+
+
+void GFX_SETTEXT(void)
+{
+ if (set_gfx_mode(GFX_TEXT,80,25,0,0)<0)
+ GFX_exit(EXIT_FAILURE,"Couldn't open text screen\n");
+
+ show_mouse(NULL);
+ remove_mouse();
+ remove_timer();
+ remove_keyboard();
+}
+
+
+void GFX_SETGRAPHICS(void)
+{
+ if (set_gfx_mode(GFX_AUTODETECT,width,height,0,0)<0)
+ GFX_exit(EXIT_FAILURE,"Couldn't re-open graphics screen\n");
+
+ install_keyboard();
+ install_timer();
+ install_mouse();
+ show_mouse(screen);
+}
+
+
+void GFX_clear(int col)
+{
+ clear_to_color(bm,ACOL(col));
+ dirty_min_x=0;
+ dirty_max_x=width;
+ dirty_min_y=0;
+ dirty_max_y=width;
+}
+
+
+void GFX_redraw(void)
+{
+ if (dirty_max_x<dirty_min_x)
+ return;
+
+ dirty_min_x=MAX(0,dirty_min_x);
+ dirty_min_y=MAX(0,dirty_min_y);
+ dirty_max_x=MIN(width,dirty_max_x);
+ dirty_max_y=MIN(height,dirty_max_y);
+
+ show_mouse(NULL);
+
+ blit(bm,screen,dirty_min_x,dirty_min_y,
+ dirty_min_x,dirty_min_y,
+ dirty_max_x-dirty_min_x+1,dirty_max_y-dirty_min_y+1);
+
+ show_mouse(screen);
+
+ dirty_max_x=0;
+ dirty_min_x=width-1;
+ dirty_max_y=0;
+ dirty_min_y=width-1;
+}
+
+
+void GFX_FORCE_REDRAW(void)
+{
+ show_mouse(NULL);
+ blit(bm,screen,0,0,0,0,width,height);
+ show_mouse(screen);
+ dirty_max_x=0;
+ dirty_min_x=width-1;
+ dirty_max_y=0;
+ dirty_min_y=width-1;
+}
+
+
+void GFX_line(int x1,int y1,int x2,int y2,int col)
+{
+ DIRTY(x1,y1);
+ DIRTY(x2,y2);
+ line(bm,x1,y1,x2,y2,ACOL(col));
+}
+
+
+void GFX_plot(int x,int y,int col)
+{
+ DIRTY(x,y);
+ putpixel(bm,x,y,ACOL(col));
+}
+
+
+void GFX_circle(int x,int y,int r,int col)
+{
+ DIRTY(x-r-1,y-r-1);
+ DIRTY(x+r+1,y+r+1);
+ circle(bm,x,y,r,ACOL(col));
+}
+
+
+void GFX_fcircle(int x,int y,int r,int col)
+{
+ DIRTY(x-r-1,y-r-1);
+ DIRTY(x+r+1,y+r+1);
+ circlefill(bm,x,y,r,ACOL(col));
+}
+
+
+void GFX_rect(int x,int y,int w,int h,int col)
+{
+ DIRTY(x,y);
+ DIRTY(x+w,y+h);
+
+ w-=SGN(w);
+ h-=SGN(h);
+
+ rect(bm,x,y,x+w,y+h,ACOL(col));
+}
+
+
+void GFX_frect(int x,int y,int w,int h,int col)
+{
+ DIRTY(x,y);
+ DIRTY(x+w,y+h);
+
+ w-=SGN(w);
+ h-=SGN(h);
+
+ rectfill(bm,x,y,x+w,y+h,ACOL(col));
+}
+
+
+void GFX_set_XOR_mode(void)
+{
+ drawing_mode(DRAW_MODE_XOR,NULL,0,0);
+}
+
+
+void GFX_clear_XOR_mode(void)
+{
+ drawing_mode(DRAW_MODE_SOLID,NULL,0,0);
+}
+
+
+void GFX_print(int x,int y,int col,char *fmt,...)
+{
+ char s[512];
+ va_list va;
+
+ va_start(va,fmt);
+ vsprintf(s,fmt,va);
+ va_end(va);
+
+ DIRTY(x,y);
+ DIRTY(x+text_length(font,s),y+text_height(font));
+
+ text_mode(-1);
+ textout(bm,font,s,x,y,ACOL(col));
+}
+
+
+int GFX_fh(void)
+{
+ return(text_height(font));
+}
+
+
+int GFX_fw(void)
+{
+ return(text_length(font," "));
+}
+
+
+int GFX_mouse_buttons(void)
+{
+ return(mbuttons);
+}
+
+
+int GFX_mouse(int *x,int *y)
+{
+ if (x)
+ *x=mouse_x;
+
+ if (y)
+ *y=mouse_y;
+
+ return(mouse_b);
+}
+
+
+void GFX_waitkey(GFXKey *key)
+{
+ GFXKey dummy;
+
+ while(!keypressed());
+ if (key)
+ GetKey(key);
+ else
+ GetKey(&dummy);
+}
+
+
+int GFX_key(GFXKey *key)
+{
+ if(!keypressed())
+ return(FALSE);
+ else
+ {
+ GetKey(key);
+ return(TRUE);
+ }
+}
+
+
+void GFX_bounce(void)
+{
+ while((keypressed())||(mouse_b))
+ if (keypressed())
+ readkey();
+}
+
+
+void GFX_await_input(GFXEvent *ev)
+{
+ static time_t last_time=0;
+ static int mb;
+
+ /* Assume that a gap of 1-2 seconds means that this is a new await
+ input loop
+ */
+ if (time(NULL)-last_time>1)
+ mb=0;
+
+ while (TRUE)
+ {
+ if (keypressed())
+ {
+ ev->type=GFX_KEY_EVENT;
+ GetKey(&ev->key);
+ return;
+ }
+
+ if (mouse_b!=mb)
+ {
+ ev->mouse.shift=key_shifts&KB_SHIFT_FLAG;
+ ev->mouse.ctrl=key_shifts&KB_CTRL_FLAG;
+ ev->mouse.alt=key_shifts&KB_ALT_FLAG;
+ ev->mouse.x=mouse_x;
+ ev->mouse.y=mouse_y;
+ ev->mouse.b=mb=mouse_b;
+ ev->type=GFX_MOUSE_EVENT;
+ return;
+ }
+ }
+}
+
+
+void GFX_await_input_full(GFXEvent *ev)
+{
+ static time_t last_time=0;
+ static int mx,my,mb;
+
+ /* Assume that a gap of 1-2 seconds means that this is a new await
+ input loop
+ */
+ if (time(NULL)-last_time>1)
+ {
+ mx=-1;
+ my=-1;
+ mb=0;
+ }
+
+ while (TRUE)
+ {
+ if (keypressed())
+ {
+ ev->type=GFX_KEY_EVENT;
+ GetKey(&ev->key);
+ last_time=time(NULL);
+ return;
+ }
+
+ if ((mouse_b!=mb)||(mouse_x!=mx)||(mouse_y!=my))
+ {
+ ev->mouse.shift=key_shifts&KB_SHIFT_FLAG;
+ ev->mouse.ctrl=key_shifts&KB_CTRL_FLAG;
+ ev->mouse.alt=key_shifts&KB_ALT_FLAG;
+ ev->mouse.x=mx=mouse_x;
+ ev->mouse.y=my=mouse_y;
+ ev->mouse.b=mb=mouse_b;
+ ev->type=GFX_MOUSE_EVENT;
+ last_time=time(NULL);
+ return;
+ }
+ }
+}
+
+
+void GFX_exit(int code,char *fmt,...)
+{
+ va_list va;
+
+ if (init)
+ allegro_exit();
+
+ va_start(va,fmt);
+ vfprintf(stderr,fmt,va);
+ va_end(va);
+
+ exit(code);
+}
+
+
+GFX_IMAGE GFX_create_image(GFX_BITMAP *bm)
+{
+ BITMAP *b;
+ RLE_SPRITE *ret;
+ int x,y;
+
+ if (!(b=create_bitmap(bm->w,bm->h)))
+ return(NULL);
+
+ clear(b);
+
+ for(x=0;x<bm->w;x++)
+ for(y=0;y<bm->h;y++)
+ putpixel(b,x,y,ACOL(bm->pal[*(bm->data+(y*bm->w)+(x))]));
+
+ ret=get_rle_sprite(b);
+ destroy_bitmap(b);
+
+ return((GFX_IMAGE)ret);
+}
+
+
+void GFX_destroy_image(GFX_IMAGE img)
+{
+ destroy_rle_sprite(img);
+}
+
+
+void GFX_draw_image(GFX_IMAGE i, int x, int y)
+{
+ RLE_SPRITE *s;
+
+ s=i;
+ draw_rle_sprite(bm,s,x,y);
+ DIRTY(x,y);
+ DIRTY(x+s->w,y+s->h);
+}
+
+
+void GFX_fill_screen(GFX_IMAGE i)
+{
+ BITMAP *b;
+ RLE_SPRITE *s;
+
+ s=i;
+ b=create_bitmap(s->w,s->h);
+ draw_rle_sprite(b,s,0,0);
+
+ stretch_blit(b,bm,0,0,s->w,s->h,0,0,width,height);
+ destroy_bitmap(b);
+
+ DIRTY(0,0);
+ DIRTY(width,height);
+}
+
+
+void GFX_save_screen(char *path)
+{
+ BITMAP *sub;
+
+ sub=create_sub_bitmap(screen,0,0,width,height);
+ save_bmp(path,sub,NULL);
+ destroy_bitmap(sub);
+}
+
+
+/* END OF FILE */
diff --git a/djgpp/install b/djgpp/install
new file mode 100644
index 0000000..754914f
--- /dev/null
+++ b/djgpp/install
@@ -0,0 +1,31 @@
+# viDOOM - level editor for DOOM
+#
+# Copyright (C) 2000 Ian Cowburn (ianc@noddybox.demon.co.uk)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# -------------------------------------------------------------------------
+#
+# Install Makefile for DJGPP
+#
+# $Id: install,v 1.1 2000/07/19 14:05:45 dosuser Exp dosuser $
+#
+
+install: FORCE
+ $(CC) -o install.exe install.c
+ install.exe $(INSTALLDIR)
+ del install.exe
+
+FORCE:
diff --git a/djgpp/install.c b/djgpp/install.c
new file mode 100644
index 0000000..2639319
--- /dev/null
+++ b/djgpp/install.c
@@ -0,0 +1,119 @@
+/*
+
+ viDOOM - level editor for DOOM
+
+ Copyright (C) 2000 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ Install program for DOS/DJGPP version
+
+*/
+static const char rcs_id[]="$Id$";
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+/* This is done as an executable just because we can then ensure that the
+ slashes are the right way around
+*/
+void Cmd(char *fmt, ...)
+{
+ char cmd[1024];
+ va_list va;
+
+ va_start(va,fmt);
+ vsprintf(cmd,fmt,va);
+ va_end(va);
+
+ printf("*** %s\n",cmd);
+ strcat(cmd," > temp.$$$");
+ system(cmd);
+ system("del temp.$$$");
+}
+
+
+int main(int argc, char *argv[])
+{
+ char path[1024];
+ char *p,*pwd;
+
+ if (argc!=2)
+ {
+ fprintf(stderr,"usage: install dir\n");
+ exit(1);
+ }
+
+ pwd=getcwd(NULL,1024);
+
+ strcpy(path,argv[1]);
+
+ if (path[strlen(path)-1]=='\\')
+ path[strlen(path)-1]=0;
+
+ p=path;
+
+ while(*p)
+ {
+ if (*p=='/')
+ *p='\\';
+
+ p++;
+ }
+
+ if (chdir(".."))
+ exit(1);
+
+ /* Do viDOOM
+ */
+ mkdir(path);
+
+ printf("===== Installing viDOOM to %s =====\n",path);
+
+ Cmd("del %s\\vidoom.exe",path);
+ Cmd("del %s\\*.cfg",path);
+ Cmd("del %s\\vidoom.ini",path);
+ Cmd("copy vidoom.exe %s",path);
+ Cmd("copy LICENSE %s",path);
+ Cmd("copy *.cfg %s",path);
+ Cmd("copy base.ini %s",path);
+ Cmd("ren %s\\base.ini vidoom.ini",path);
+
+ /* Do docs
+ */
+ strcat(path,"\\doc");
+ mkdir(path);
+
+ Cmd("del %s\\*.htm",path);
+ Cmd("del %s\\*.png",path);
+ Cmd("copy doc\\*.htm %s",path);
+ Cmd("copy doc\\*.png %s",path);
+
+
+ /* Finish
+ */
+ if (chdir(pwd))
+ exit(1);
+
+ free(pwd);
+
+ return(0);
+}
+
+
+/* END OF FILE */
diff --git a/djgpp/main.c b/djgpp/main.c
new file mode 100644
index 0000000..28a1e04
--- /dev/null
+++ b/djgpp/main.c
@@ -0,0 +1,34 @@
+/*
+
+ viDOOM - level editor for DOOM
+
+ Copyright (C) 2000 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ Startup code
+
+*/
+static const char rcs_id[]="$Id$";
+
+#include "vidoom.h"
+
+
+int main(int argc,char *argv[])
+{
+ return(viDOOM(argc,argv));
+}
diff --git a/djgpp/mem.c b/djgpp/mem.c
new file mode 100644
index 0000000..fd7774a
--- /dev/null
+++ b/djgpp/mem.c
@@ -0,0 +1,262 @@
+/*
+
+ viDOOM - level editor for DOOM
+
+ Copyright (C) 2000 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ Memory allocation code
+
+*/
+static const char rcs_id[]="$Id$";
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "mem.h"
+#include "gfx.h"
+#include "file.h"
+
+#include "debug.h"
+
+/* Set MEMSTAT to the following levels :
+
+ 0 - Nodebug information
+ 1 - Fatal debug information (still allocated block on failure,
+ general release errors)
+ 2 - All debug information
+
+ Regardless of the above no debug is generated if DEBUG is not set
+*/
+#ifndef DEBUG
+#define MEMSTAT 0
+#else
+#define MEMSTAT 1
+#endif
+
+typedef struct memmap
+ {
+ char file[64];
+ int line;
+ void *addr;
+ struct memmap *next;
+ struct memmap *prev;
+ } MemMap;
+
+static MemMap *mmap=NULL;
+
+
+static void DumpMemList(char *p)
+{
+ MemMap *m;
+
+# if MEMSTAT == 0
+ return;
+# endif
+
+ Debug(("**** %s ****\n",p));
+ Debug(("Still waiting to be freed:\n"));
+
+ if ((m=mmap))
+ while(m)
+ {
+ Debug(("\t%p allocated to %s:%d\n",m->addr,m->file,m->line));
+ m=m->next;
+ }
+ else
+ Debug(("\tNONE\n"));
+
+}
+
+
+static void AddMM(char *mode,char *file, int line, void *addr)
+{
+ MemMap *n;
+
+# if MEMSTAT == 0
+ return;
+# endif
+
+ n=malloc(sizeof(MemMap));
+ strcpy(n->file,Basename(file));
+ n->line=line;
+ n->addr=addr;
+
+ if (!mmap)
+ {
+ mmap=n;
+ n->next=NULL;
+ n->prev=NULL;
+ }
+ else
+ {
+ mmap->prev=n;
+ n->next=mmap;
+ n->prev=NULL;
+ mmap=n;
+ }
+
+# if MEMSTAT == 2
+ Debug(("%s: Memory %p allocated to %s:%d\n",mode,addr,file,line));
+# endif
+}
+
+
+static void RmMM(char *mode, char *file, int line, void *addr)
+{
+ MemMap *n;
+ int del;
+
+# if MEMSTAT == 0
+ return;
+# endif
+
+ del=0;
+ n=mmap;
+
+ while(n)
+ if (n->addr==addr)
+ {
+# if MEMSTAT == 2
+ Debug(("%s: Address %p freed by %s:%d\n",mode,addr,file,line));
+# endif
+
+ if (n->prev)
+ n->prev->next=n->next;
+ else
+ mmap=n->next;
+
+ if (n->next)
+ n->next->prev=n->prev;
+
+ free(n);
+ n=NULL;
+ del=1;
+ }
+ else
+ n=n->next;
+
+ if (!del)
+ Debug(("%s: ***** Address %p not found - freed by %s:%d\n",
+ mode,addr,file,line));
+}
+
+
+void *FGrab(char *fn, int line, int len)
+{
+ char *ptr;
+
+ if (len==0)
+ len=1;
+
+ if (!(ptr=malloc(len)))
+ {
+ DumpMemList("GRAB FAILED");
+ GFX_exit(EXIT_FAILURE,"Memory allocation failed!\n"
+ "%s:%d Grab(%d)\n",fn,line,len);
+ }
+
+ memset(ptr,0,len);
+
+ AddMM("Grab",fn,line,ptr);
+
+ return(ptr);
+}
+
+
+void *FReGrab(char *fn, int line, void *ptr, int len)
+{
+ if (len==0)
+ len=1;
+
+ if (ptr)
+ RmMM("ReGrab(RELEASE)",fn,line,ptr);
+
+ if (!(ptr=realloc(ptr,len)))
+ {
+ DumpMemList("REGRAB FAILED");
+ GFX_exit(EXIT_FAILURE,"Memory allocation failed!\n"
+ "%s:%d ReGrab(%d)\n",fn,line,len);
+ }
+
+ AddMM("ReGrab(ACQUIRE)",fn,line,ptr);
+
+ return(ptr);
+}
+
+
+void FRelease(char *fn, int line, void *p)
+{
+ RmMM("Release",fn,line,p);
+ free(p);
+}
+
+
+void *FCopy(char *fn, int line, void *p,int len)
+{
+ void *ptr;
+
+ if (len==0)
+ ptr=malloc(1);
+ else
+ ptr=malloc(len);
+
+ if (!ptr)
+ {
+ DumpMemList("COPY FAILED");
+ GFX_exit(EXIT_FAILURE,"Memory allocation failed!\n"
+ "%s:%d Copy(%p,%d)\n",fn,line,p,len);
+ }
+
+ if (len)
+ memcpy(ptr,p,len);
+
+ AddMM("Copy",fn,line,ptr);
+
+ return(ptr);
+}
+
+
+char *FStrdup(char *fn, int line, char *p)
+{
+ char n_fn[PATH_MAX];
+ char *ptr;
+
+ strcpy(n_fn,fn);
+ strcat(n_fn," [STRDUP]");
+
+ if (p)
+ {
+ if (!(ptr=malloc(strlen(p)+1)))
+ {
+ DumpMemList("STRDUP FAILED");
+ GFX_exit(EXIT_FAILURE,"Memory allocation failed!\n"
+ "%s:%d Stdup(%s)\n",fn,line,p);
+ }
+
+ strcpy(ptr,p);
+ AddMM("Strdup",fn,line,ptr);
+ return(ptr);
+ }
+ else
+ return(NULL);
+}
+
+/* END OF FILE */
diff --git a/djgpp/platgui.c b/djgpp/platgui.c
new file mode 100644
index 0000000..3f50964
--- /dev/null
+++ b/djgpp/platgui.c
@@ -0,0 +1,4235 @@
+/*
+
+ viDOOM - level editor for DOOM
+
+ Copyright (C) 2000 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ Platform specific GUI type routines
+
+*/
+static const char rcs_id[]="$Id$";
+
+#include "config.h"
+
+#include <stdio.h>
+#include <allegro.h>
+#include <string.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <dir.h>
+#include <limits.h>
+#include <ctype.h>
+#include <fcntl.h>
+
+#include "platgui.h"
+#include "gfx.h"
+#include "gui.h"
+#include "mem.h"
+#include "file.h"
+#include "util.h"
+
+#include "debug.h"
+
+#define COLDEP 16
+#define ACOL(c) (makecol_depth(COLDEP,((c)&0xff0000)>>16, \
+ ((c)&0xff00)>>8, \
+ ((c)&0xff)))
+
+#define DIALOG_STRLEN 16
+
+#define SMALL_BEVEL 1 /* Bevels on radio and flag boxes */
+#define BEVEL 2 /* All other bevels */
+#define TICK 2
+
+#define PL_COL 0xb0b0ff /* Col for active picklist */
+
+#define BUFF_LEN 1024
+
+/* ---------------------------------------- VARS
+*/
+static int SCRW,SCRH;
+static int FW,FH;
+
+/* Vars for GUI_yesno_all()
+*/
+static int all_pressed=FALSE;
+static int all_result=FALSE;
+
+/* Global picklist data and the picklist dialog
+*/
+#define PL_BORDER 0
+#define PL_TITLE 1
+#define PL_PICKLIST 2
+#define PL_OK 3
+#define PL_CANCEL 4
+#define PL_END 5
+
+static DIALOG picklist[PL_END+1];
+static int pick_no;
+static char **pick_data;
+
+
+/* Global image picklist data and the image picklist dialog
+*/
+#define IPL_BORDER 0
+#define IPL_TITLE 1
+#define IPL_PICKLIST 2
+#define IPL_IMG_BORDER 3
+#define IPL_IMAGE 4
+#define IPL_OK 5
+#define IPL_CANCEL 6
+#define IPL_END 7
+
+static DIALOG img_picklist[IPL_END+1];
+static int img_pick_no;
+static PLAT_IMG_PICKLIST
+ *img_pick_data;
+
+
+/* Global data and the file viewer dialog
+*/
+#define FV_BORDER 0
+#define FV_TITLE 1
+#define FV_TEXTBOX 2
+#define FV_TEXT 3
+#define FV_VERT_SCROLL 4
+#define FV_HORIZ_SCROLL 5
+#define FV_OK 6
+#define FV_END 7
+
+#define FV_SCROLLWIDTH 10
+#define FV_WIDTH 75
+#define FV_HEIGHT 40
+
+static DIALOG fv_dialog[FV_END+1];
+
+typedef struct
+ {
+ double one;
+ int size;
+ int pos;
+ } ScrollbarData;
+
+
+/* Global data for the text editor dialog
+*/
+#define TE_BORDER 0
+#define TE_TITLE 1
+#define TE_TEXTBOX 2
+#define TE_TEXT 3
+#define TE_OK 4
+#define TE_CANCEL 5
+#define TE_END 6
+
+#define TE_WIDTH 75
+#define TE_CHUNK 256
+#define TE_HEIGHT 40
+
+static DIALOG te_dialog[TE_END+1];
+
+typedef struct
+ {
+ char t[TE_HEIGHT][TE_WIDTH+1];
+ int top;
+ int x,y;
+ int col;
+ int lines;
+ int start;
+ } TextEditData;
+
+typedef struct
+ {
+ int len;
+ char *p;
+ } TextEditLine;
+
+
+/* Types for the menu
+*/
+typedef struct
+ {
+ int x;
+ int y;
+ int w;
+ int h;
+ } BoundBox;
+
+#define MENU_OK 0
+#define MENU_CANCEL_ESC 1
+#define MENU_CANCEL_CLICK 2
+#define MENU_CHILD_RETURN 3
+
+typedef struct
+ {
+ int ret;
+ int mode;
+ } MenuControl;
+
+
+static int MouseInBox(BoundBox *box,int no);
+
+/* 'Hidden' interfaces to gfx.c
+*/
+extern void GFX_FORCE_REDRAW(void);
+extern void GFX_SETTEXT(void);
+extern void GFX_SETGRAPHICS(void);
+
+
+/* ---------------------------------------- FILE VEIWER SUPPORT FUNCS
+*/
+static char *ConvertFileText(char *p)
+{
+ static char s[BUFF_LEN+1];
+ int f;
+
+ f=0;
+
+ while((*p)&&(f<BUFF_LEN))
+ {
+ if (isprint(*p))
+ s[f++]=*p++;
+ else if (*p == '\t')
+ {
+ if ((f%8)==0)
+ s[f++]=' ';
+
+ while(((f%8)!=0)&&(f<BUFF_LEN))
+ s[f++]=' ';
+
+ p++;
+ }
+ else
+ p++;
+ }
+
+ s[f]=0;
+
+ return(s);
+}
+
+
+/* ---------------------------------------- GUI OBJECT PROCS SUPPORT FUNCS
+*/
+static void Rect3D(int x,int y,int w,int h, int invert,int bevel)
+{
+ int f;
+ int mid,lo,hi;
+
+ mid=ACOL(GUI_MID);
+
+ if (invert)
+ {
+ lo=ACOL(GUI_HI);
+ hi=ACOL(GUI_LO);
+ }
+ else
+ {
+ hi=ACOL(GUI_HI);
+ lo=ACOL(GUI_LO);
+ }
+
+ rectfill(screen,x,y,x+w-1,y+h-1,mid);
+
+ for(f=0;f<bevel;f++)
+ {
+ vline(screen,x+f,y+f,y+h-1-f,hi);
+ vline(screen,x+w-1-f,y+f,y+h-1-f,lo);
+
+ hline(screen,x+f,y+f,x+w-1-f,hi);
+ hline(screen,x+f,y+h-1-f,x+w-1-f,lo);
+ }
+}
+
+
+static void DrawTick(int x,int y,int w,int h)
+{
+ int ox,oy,x2,y2,x3,y3;
+ int f;
+
+ x2=x+(w/4);
+ y2=y+h-1;
+
+ x3=x2;
+ y3=y2;
+
+ while(x3<(x+w-1))
+ {
+ x3++;
+ y3--;
+ }
+
+ ox=x;
+ oy=y;
+
+ x=x2;
+ y=y2;
+
+ while(x>ox)
+ {
+ x--;
+ y--;
+ }
+
+ for(f=0;f<TICK;f++)
+ {
+ line(screen,x,y,x2,y2,ACOL(BLACK));
+ line(screen,x2,y2,x3,y3,ACOL(BLACK));
+
+ y--;
+ y2--;
+ y3--;
+ }
+}
+
+
+/* This code is based on _draw_scrollable_frame() from guiproc.c in Allegro
+*/
+static void DrawScrollableFrame(DIALOG *d, int listsize, int offset,
+ int height, int fg_color, int bg)
+{
+ BITMAP *pattern;
+ int i, len;
+ int xx, yy;
+
+ /* draw frame
+ */
+ rect(screen, d->x, d->y, d->x+d->w, d->y+d->h, fg_color);
+
+ /* possibly draw scrollbar
+ */
+ if (listsize > height)
+ {
+ vline(screen, d->x+d->w-12, d->y+1, d->y+d->h-1, fg_color);
+
+ /* create and draw the scrollbar
+ */
+ pattern=create_bitmap(2,2);
+
+ /*
+ putpixel(pattern,0,0,d->fg);
+ putpixel(pattern,1,1,d->fg);
+ putpixel(pattern,1,0,d->bg);
+ putpixel(pattern,0,1,d->bg);
+ */
+ putpixel(pattern,0,0,ACOL(GUI_MID));
+ putpixel(pattern,1,1,ACOL(GUI_MID));
+ putpixel(pattern,1,0,ACOL(GUI_LO));
+ putpixel(pattern,0,1,ACOL(GUI_LO));
+
+ i = ((d->h-4) * height + listsize/2) / listsize;
+ xx = d->x+d->w-11;
+ yy = d->y+2;
+
+ if (offset > 0)
+ {
+ len = (((d->h-4) * offset) + listsize/2) / listsize;
+ drawing_mode(DRAW_MODE_COPY_PATTERN, pattern, 0, 0);
+ rectfill(screen, xx, yy, xx+10, yy+len-1, ACOL(GUI_MID));
+ solid_mode();
+ yy += len;
+ }
+
+ if (yy+i < d->y+d->h-2)
+ {
+ Rect3D(xx, yy, 11, i, FALSE, BEVEL);
+ yy += i;
+ drawing_mode(DRAW_MODE_COPY_PATTERN, pattern, 0, 0);
+ rectfill(screen, xx, yy, xx+10, d->y+d->h-2, ACOL(GUI_MID));
+ solid_mode();
+ }
+ else
+ Rect3D(xx, yy, 11, i, FALSE, BEVEL);
+
+ destroy_bitmap(pattern);
+ }
+}
+
+
+/* This code is copied from _draw_listbox() from guiproc.c in Allegro, so we
+ can force it to call DrawScrollableFrame()
+*/
+static void DrawListbox(DIALOG *d)
+{
+ typedef char *(*getfuncptr)(int, int *);
+ int height, listsize, i, len, bar, x, y, w;
+ int fg_color, fg, bg;
+ char *sel = d->dp2;
+ char *s;
+ char store;
+
+ (*(getfuncptr)d->dp)(-1, &listsize);
+ height = (d->h-3) / text_height(font);
+ bar = (listsize > height);
+ w = (bar ? d->w-14 : d->w-2);
+
+ fg_color = (d->flags & D_DISABLED) ? gui_mg_color : d->fg;
+
+ /* draw box contents
+ */
+ for (i=0; i<height; i++)
+ {
+ if (d->d2+i < listsize)
+ {
+ if (d->d2+i == d->d1)
+ {
+ fg = d->bg;
+ bg = fg_color;
+ }
+ else if ((sel) && (sel[d->d2+i]))
+ {
+ fg = d->bg;
+ bg = gui_mg_color;
+ }
+ else
+ {
+ fg = fg_color;
+ bg = d->bg;
+ }
+
+ s = (*(getfuncptr)d->dp)(i+d->d2, NULL);
+ x = d->x + 2;
+ y = d->y + 2 + i*text_height(font);
+ text_mode(bg);
+ rectfill(screen, x, y, x+7, y+text_height(font)-1, bg);
+ x += 8;
+ len = strlen(s);
+ store = 0;
+ while (text_length(font, s) >= d->w - (bar ? 22 : 10))
+ {
+ s[len] = store;
+ len--;
+ store = s[len];
+ s[len] = 0;
+ }
+ textout(screen, font, s, x, y, fg);
+ x += text_length(font, s);
+ s[len] = store;
+ if (x <= d->x+w)
+ rectfill(screen, x, y, d->x+w, y+text_height(font)-1, bg);
+ }
+ else
+ rectfill(screen, d->x+2, d->y+2+i*text_height(font),
+ d->x+w, d->y+1+(i+1)*text_height(font), d->bg);
+ }
+
+ if (d->y+2+i*text_height(font) <= d->y+d->h-2)
+ rectfill(screen, d->x+2, d->y+2+i*text_height(font),
+ d->x+w, d->y+d->h-2, d->bg);
+
+ /* draw frame, maybe with scrollbar
+ */
+ DrawScrollableFrame(d, listsize, d->d2, height, fg_color, d->bg);
+}
+
+
+/* ---------------------------------------- GUI OBJECT PROCS
+
+ Note that many of the functions are based on the source available
+ in guiproc.c in Allegro
+*/
+static int d_3d_box(int msg, DIALOG *d, int c)
+{
+ if (msg==MSG_DRAW)
+ Rect3D(d->x,d->y,d->w,d->h,FALSE,BEVEL);
+
+ return(D_O_K);
+}
+
+
+static int d_inv_3d_box(int msg, DIALOG *d, int c)
+{
+ if (msg==MSG_DRAW)
+ Rect3D(d->x,d->y,d->w,d->h,TRUE,BEVEL);
+
+ return(D_O_K);
+}
+
+
+static int d_img_bmap_proc(int msg, DIALOG *d, int c)
+{
+ RLE_SPRITE *bm;
+
+ if (msg==MSG_DRAW)
+ {
+ rectfill(screen,d->x,d->y,d->x+d->w-1,d->y+d->h-1,ACOL(BLACK));
+
+ if ((bm=d->dp))
+ draw_rle_sprite(screen,bm,d->x,d->y);
+ }
+
+ return(D_O_K);
+}
+
+
+static int d_img_list_proc(int msg, DIALOG *d, int c)
+{
+ static int my_d_list_proc(int msg, DIALOG *d, int c);
+ int d1;
+ int ret;
+
+ d1=img_picklist[IPL_PICKLIST].d1;
+
+ ret=my_d_list_proc(msg,d,c);
+
+ if (d1!=img_picklist[IPL_PICKLIST].d1)
+ {
+ img_picklist[IPL_IMAGE].dp=
+ img_pick_data[img_picklist[IPL_PICKLIST].d1].img;
+
+ d_img_bmap_proc(MSG_DRAW,&img_picklist[IPL_IMAGE],0);
+ }
+
+ return(ret);
+}
+
+
+int my_d_check_proc(int msg, DIALOG *d, int c)
+{
+ int x;
+ int fg;
+
+ if (msg==MSG_DRAW)
+ {
+ fg=ACOL(WHITE);
+ text_mode(d->bg);
+
+ gui_textout(screen, d->dp, d->x,
+ d->y+(d->h-(text_height(font)-gui_font_baseline))/2,
+ fg, FALSE);
+
+ x=d->x+d->w-d->h;
+
+ Rect3D(x,d->y,d->h,d->h,TRUE,SMALL_BEVEL);
+ rectfill(screen,x+SMALL_BEVEL,d->y+SMALL_BEVEL,
+ x+d->h-SMALL_BEVEL*2,d->y+d->h-SMALL_BEVEL*2,
+ ACOL(WHITE));
+
+ if (d->flags & D_SELECTED)
+ if (d->d1)
+ rectfill(screen,x+SMALL_BEVEL+2,d->y+SMALL_BEVEL+2,
+ x+d->h-SMALL_BEVEL*2-2,
+ d->y+d->h-SMALL_BEVEL*2-2,
+ ACOL(BLACK));
+ else
+ DrawTick(x+SMALL_BEVEL,d->y+SMALL_BEVEL,
+ d->h-SMALL_BEVEL*2,d->h-SMALL_BEVEL*2);
+
+ return D_O_K;
+ }
+
+ /* Group zero is done as a check box, not a radio box
+ */
+ if (d->d1)
+ return d_radio_proc(msg, d, c);
+ else
+ return d_button_proc(msg, d, c);
+}
+
+
+int my_d_radio_proc(int msg, DIALOG *d, int c)
+{
+ int x,fg;
+
+ switch(msg)
+ {
+ case MSG_DRAW:
+ fg=(d->flags & D_DISABLED) ? gui_mg_color : d->fg;
+ text_mode(d->bg);
+ gui_textout
+ (screen,
+ d->dp,d->x+d->h+text_height(font),
+ d->y+(d->h-(text_height(font)-gui_font_baseline))/2,fg,FALSE);
+
+ x = d->x;
+
+ Rect3D(x,d->y,d->h,d->h,TRUE,SMALL_BEVEL);
+ rectfill(screen,x+SMALL_BEVEL,d->y+SMALL_BEVEL,
+ x+d->h-SMALL_BEVEL*2,d->y+d->h-SMALL_BEVEL*2,
+ ACOL(WHITE));
+
+ if (d->flags & D_SELECTED)
+ rectfill(screen,x+SMALL_BEVEL+2,d->y+SMALL_BEVEL+2,
+ x+d->h-SMALL_BEVEL*2-2,
+ d->y+d->h-SMALL_BEVEL*2-2,
+ ACOL(BLACK));
+
+ break;
+
+ default:
+ return(d_radio_proc(msg,d,c));
+ break;
+ }
+
+ return(D_O_K);
+}
+
+
+static int my_d_list_proc(int msg, DIALOG *d, int c)
+{
+ switch(msg)
+ {
+ case MSG_DRAW:
+ DrawListbox(d);
+ break;
+
+ default:
+ return(d_list_proc(msg,d,c));
+ break;
+ }
+
+ return (D_O_K);
+}
+
+
+static int my_d_button_proc(int msg, DIALOG *d, int c)
+{
+ int inv;
+
+ switch(msg)
+ {
+ case MSG_DRAW:
+ if (d->flags&D_GOTFOCUS)
+ rect(screen,d->x-1,d->y-1,d->x+d->w,d->y+d->h,ACOL(BLACK));
+ else
+ rect(screen,d->x-1,d->y-1,d->x+d->w,d->y+d->h,ACOL(GUI_MID));
+
+ if (d->flags&D_SELECTED)
+ inv=TRUE;
+ else
+ inv=FALSE;
+
+ Rect3D(d->x,d->y,d->w,d->h,inv,BEVEL);
+ text_mode(-1);
+ gui_textout(screen,d->dp,d->x+(d->w/2),d->y+d->h/2-FH/2,d->fg,TRUE);
+
+ break;
+
+ default:
+ return(d_button_proc(msg,d,c));
+ break;
+ }
+
+ return (D_O_K);
+}
+
+
+static int d_ro_textbox(int msg, DIALOG *d, int c)
+{
+ char **p;
+ int x,y;
+ int f;
+
+ p=d->dp;
+
+ if(msg==MSG_DRAW)
+ {
+ text_mode(-1);
+
+ y=d->d2;
+ x=d->d1;
+
+ vsync();
+
+ rectfill(screen,d->x,d->y,d->x+d->w-1,d->y+d->h-1,ACOL(WHITE));
+
+ for(f=0;(f<FV_HEIGHT)&&(p[y]);f++,y++)
+ if (strlen(p[y])>x)
+ textprintf(screen,font,d->x,d->y+(f*FH),ACOL(BLACK),
+ "%-.*s",FV_WIDTH,p[y]+x);
+
+ }
+
+ return (D_O_K);
+}
+
+
+static int d_vert_scrollbar(int msg, DIALOG *d, int c)
+{
+ ScrollbarData *sd;
+ int *ip;
+ DIALOG *dp;
+ int last_y;
+
+ /* Special case for 'zero' length scrollbars - just ignore interactions
+ and draw a full length scrollbar
+ */
+ if (d->d2==0)
+ {
+ if (msg==MSG_DRAW)
+ {
+ rect(screen,d->x,d->y,d->x+d->w,d->y+d->h,ACOL(BLACK));
+ Rect3D(d->x+1,d->y+1,d->w-1,d->h-1,FALSE,BEVEL);
+ }
+
+ return(D_O_K);
+ }
+
+ switch(msg)
+ {
+ case MSG_START:
+ /* Calc box size, etc
+ */
+ sd=Grab(sizeof(*sd));
+ d->dp3=sd;
+
+ sd->one=(double)d->h/(double)(d->d2+d->d1);
+ sd->size=(int)(sd->one*d->d1);
+ sd->pos=0;
+ ip=d->dp;
+ *ip=0;
+
+ break;
+
+ case MSG_END:
+ Release(d->dp3);
+ break;
+
+ case MSG_DRAW:
+ {
+ BITMAP *pattern;
+
+ sd=d->dp3;
+
+ /* draw frame
+ */
+ rect(screen,d->x,d->y,d->x+d->w,d->y+d->h,ACOL(BLACK));
+
+ /* create and draw the scrollbar
+ */
+ pattern=create_bitmap(2,2);
+
+ putpixel(pattern,0,0,ACOL(GUI_MID));
+ putpixel(pattern,1,1,ACOL(GUI_MID));
+ putpixel(pattern,1,0,ACOL(GUI_LO));
+ putpixel(pattern,0,1,ACOL(GUI_LO));
+
+ drawing_mode(DRAW_MODE_COPY_PATTERN, pattern, 0, 0);
+ rectfill(screen,d->x+1,d->y+1,d->x+d->w-1,d->y+d->h-2,0);
+ solid_mode();
+ Rect3D(d->x+1,d->y+1+sd->pos,d->w-1,sd->size,FALSE,BEVEL);
+
+ destroy_bitmap(pattern);
+
+ break;
+ }
+
+ case MSG_WANTFOCUS:
+ return(D_WANTFOCUS);
+ break;
+
+ case MSG_CLICK:
+ sd=d->dp3;
+ ip=d->dp;
+ dp=d->dp2;
+
+ if (mouse_y<(d->y+sd->pos))
+ {
+ while((mouse_b)&&(mouse_y<(d->y+sd->pos)))
+ if (*ip)
+ {
+ (*ip)--;
+
+ sd->pos=(int)((*ip)*sd->one);
+
+ show_mouse(NULL);
+ SEND_MESSAGE(d,MSG_DRAW,0);
+ SEND_MESSAGE(dp,MSG_DRAW,0);
+ show_mouse(screen);
+ }
+ }
+ else if (mouse_y>(d->y+sd->pos+sd->size))
+ {
+ while((mouse_b)&&(mouse_y>(d->y+sd->pos+sd->size)))
+ if ((*ip)<d->d2)
+ {
+ (*ip)++;
+
+ sd->pos=(int)((*ip)*sd->one);
+
+ show_mouse(NULL);
+ SEND_MESSAGE(d,MSG_DRAW,0);
+ SEND_MESSAGE(dp,MSG_DRAW,0);
+ show_mouse(screen);
+ }
+ }
+ else
+ {
+ last_y=mouse_y;
+
+ /* I'm sure there's a better way of doing this, but I couldn't
+ get the sums to work out...
+ */
+ while(mouse_b)
+ {
+ int my;
+ int diff;
+ int np;
+
+ my=mouse_y;
+ diff=my-last_y;
+ np=sd->pos+diff;
+
+ if ((diff<0)&&((*ip)>0))
+ {
+ while((sd->pos>np)&&(*ip))
+ {
+ (*ip)--;
+ sd->pos=(int)((*ip)*sd->one);
+ }
+
+ show_mouse(NULL);
+ SEND_MESSAGE(d,MSG_DRAW,0);
+ SEND_MESSAGE(dp,MSG_DRAW,0);
+ show_mouse(screen);
+ }
+ else if ((diff>0)&&((*ip)<d->d2))
+ {
+ while((sd->pos<np)&&((*ip)<d->d2))
+ {
+ (*ip)++;
+ sd->pos=(int)((*ip)*sd->one);
+ }
+
+ if (sd->pos==(d->h-sd->size))
+ *ip=d->d2;
+
+ show_mouse(NULL);
+ SEND_MESSAGE(d,MSG_DRAW,0);
+ SEND_MESSAGE(dp,MSG_DRAW,0);
+ show_mouse(screen);
+ }
+
+ last_y=my;
+ }
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ return(D_O_K);
+}
+
+
+static int d_horiz_scrollbar(int msg, DIALOG *d, int c)
+{
+ ScrollbarData *sd;
+ int *ip;
+ DIALOG *dp;
+ int last_x;
+
+ /* Special case for 'zero' length scrollbars - just ignore interactions
+ and draw a full length scrollbar
+ */
+ if (d->d2==0)
+ {
+ if (msg==MSG_DRAW)
+ {
+ rect(screen,d->x,d->y,d->x+d->w,d->y+d->h,ACOL(BLACK));
+ Rect3D(d->x+1,d->y+1,d->w-1,d->h-1,FALSE,BEVEL);
+ }
+
+ return(D_O_K);
+ }
+
+ switch(msg)
+ {
+ case MSG_START:
+ /* Calc box size, etc
+ */
+ sd=Grab(sizeof(*sd));
+ d->dp3=sd;
+
+ sd->one=(double)d->w/(double)(d->d2+d->d1);
+ sd->size=(int)(sd->one*d->d1);
+ sd->pos=0;
+ ip=d->dp;
+ *ip=0;
+
+ break;
+
+ case MSG_END:
+ Release(d->dp3);
+ break;
+
+ case MSG_DRAW:
+ {
+ BITMAP *pattern;
+
+ sd=d->dp3;
+
+ /* draw frame
+ */
+ rect(screen,d->x,d->y,d->x+d->w,d->y+d->h,ACOL(BLACK));
+
+ /* create and draw the scrollbar
+ */
+ pattern=create_bitmap(2,2);
+
+ putpixel(pattern,0,0,ACOL(GUI_MID));
+ putpixel(pattern,1,1,ACOL(GUI_MID));
+ putpixel(pattern,1,0,ACOL(GUI_LO));
+ putpixel(pattern,0,1,ACOL(GUI_LO));
+
+ drawing_mode(DRAW_MODE_COPY_PATTERN, pattern, 0, 0);
+ rectfill(screen,d->x+1,d->y+1,d->x+d->w-1,d->y+d->h-2,0);
+ solid_mode();
+ Rect3D(d->x+1+sd->pos,d->y+1,sd->size,d->h-1,FALSE,BEVEL);
+
+ destroy_bitmap(pattern);
+
+ break;
+ }
+
+ case MSG_WANTFOCUS:
+ return(D_WANTFOCUS);
+ break;
+
+ case MSG_CLICK:
+ sd=d->dp3;
+ ip=d->dp;
+ dp=d->dp2;
+
+ if (mouse_x<(d->x+sd->pos))
+ {
+ while((mouse_b)&&(mouse_x<(d->x+sd->pos)))
+ if (*ip)
+ {
+ (*ip)--;
+
+ sd->pos=(int)((*ip)*sd->one);
+
+ show_mouse(NULL);
+ SEND_MESSAGE(d,MSG_DRAW,0);
+ SEND_MESSAGE(dp,MSG_DRAW,0);
+ show_mouse(screen);
+ }
+ }
+ else if (mouse_x>(d->x+sd->pos+sd->size))
+ {
+ while((mouse_b)&&(mouse_x>(d->x+sd->pos+sd->size)))
+ if ((*ip)<d->d2)
+ {
+ (*ip)++;
+
+ sd->pos=(int)((*ip)*sd->one);
+
+ show_mouse(NULL);
+ SEND_MESSAGE(d,MSG_DRAW,0);
+ SEND_MESSAGE(dp,MSG_DRAW,0);
+ show_mouse(screen);
+ }
+ }
+ else
+ {
+ last_x=mouse_x;
+
+ /* I'm sure there's a better way of doing this, but I couldn't
+ get the sums to work out...
+ */
+ while(mouse_b)
+ {
+ int mx;
+ int diff;
+ int np;
+
+ mx=mouse_x;
+ diff=mx-last_x;
+ np=sd->pos+diff;
+
+ if ((diff<0)&&((*ip)>0))
+ {
+ while((sd->pos>np)&&(*ip))
+ {
+ (*ip)--;
+ sd->pos=(int)((*ip)*sd->one);
+ }
+
+ show_mouse(NULL);
+ SEND_MESSAGE(d,MSG_DRAW,0);
+ SEND_MESSAGE(dp,MSG_DRAW,0);
+ show_mouse(screen);
+ }
+ else if ((diff>0)&&((*ip)<d->d2))
+ {
+ while((sd->pos<np)&&((*ip)<d->d2))
+ {
+ (*ip)++;
+ sd->pos=(int)((*ip)*sd->one);
+ }
+
+ if (sd->pos==(d->h-sd->size))
+ *ip=d->d2;
+
+ show_mouse(NULL);
+ SEND_MESSAGE(d,MSG_DRAW,0);
+ SEND_MESSAGE(dp,MSG_DRAW,0);
+ show_mouse(screen);
+ }
+
+ last_x=mx;
+ }
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ return(D_O_K);
+}
+
+
+static int d_textedit(int msg, DIALOG *d, int c)
+{
+ static char out[2]=" ";
+ char *tmp;
+ TextEditData *te;
+ TextEditLine *p;
+ int y,sx,sy;
+ int f;
+
+ p=d->dp;
+
+ switch(msg)
+ {
+ case MSG_START:
+ /* Memory for text buffer
+ */
+ te=Grab(sizeof(*te));
+ d->dp3=te;
+ te->start=TRUE;
+ te->top=0;
+ te->x=0;
+ te->y=0;
+ te->col=0;
+
+ te->lines=0;
+
+ while(p[te->lines].p)
+ te->lines++;
+
+ for(sx=0;sx<TE_WIDTH+1;sx++)
+ for(sy=0;sy<TE_HEIGHT;sy++)
+ te->t[sy][sx]=0;
+ break;
+
+ case MSG_END:
+ Release(d->dp3);
+ break;
+
+ case MSG_WANTFOCUS:
+ return(D_WANTFOCUS);
+ break;
+
+ case MSG_LOSTFOCUS:
+ return(D_WANTFOCUS);
+ break;
+
+ case MSG_DRAW:
+ te=d->dp3;
+
+ if (te->start)
+ {
+ rectfill(screen,d->x,d->y,d->x+d->w-1,d->y+d->h-1,ACOL(WHITE));
+ te->start=FALSE;
+ }
+
+ text_mode(ACOL(WHITE));
+
+ y=te->top;
+
+ rectfill(screen,d->x+d->w-FW,d->y,
+ d->x+d->w-1,d->y+d->h-1,ACOL(WHITE));
+
+ for(sy=0;sy<TE_HEIGHT;sy++,y++)
+ if (y<te->lines)
+ {
+ for(sx=0;sx<TE_WIDTH;sx++)
+ if ((te->col+sx>=p[y].len)||
+ (te->t[sy][sx]!=p[y].p[te->col+sx]))
+ {
+ if (te->col+sx>=p[y].len)
+ te->t[sy][sx]=0;
+ else
+ te->t[sy][sx]=p[y].p[te->col+sx];
+
+ if (isprint(te->t[sy][sx]))
+ out[0]=te->t[sy][sx];
+ else
+ out[0]=' ';
+
+ textout(screen,font,out,
+ d->x+(sx*FW),d->y+(sy*FH),ACOL(BLACK));
+ }
+ }
+ else
+ {
+ memset(te->t[sy],0,TE_WIDTH+1);
+ rectfill(screen,d->x,d->y+(sy*FH),
+ d->x+d->w-1,d->y+(sy*FH)+FH-1,ACOL(WHITE));
+ }
+
+ text_mode(ACOL(BLACK));
+ out[0]=isprint(te->t[te->y-te->top][te->x-te->col]) ?
+ te->t[te->y-te->top][te->x-te->col] : ' ';
+ textout(screen,font,out,
+ d->x+((te->x-te->col)*FW),
+ d->y+((te->y-te->top)*FH),ACOL(WHITE));
+ te->t[te->y-te->top][te->x-te->col]=-1;
+
+ break;
+
+ case MSG_CLICK:
+ te=d->dp3;
+
+ te->y=(mouse_y-d->y)/FH;
+ te->x=te->col+(mouse_x-d->x)/FW;
+
+ if (te->y>=te->lines)
+ te->y=te->lines-1;
+
+ if (te->x>p[te->y].len)
+ te->x=p[te->y].len;
+
+ show_mouse(NULL);
+ SEND_MESSAGE(d,MSG_DRAW,0);
+ show_mouse(screen);
+ break;
+
+ case MSG_CHAR:
+ te=d->dp3;
+
+ /* Pressing shift and space seems to generate odd values
+ */
+ if ((c>>8)==KEY_SPACE)
+ c=(c&0xff00)|' ';
+
+ switch(c>>8)
+ {
+ case KEY_HOME:
+ te->x=0;
+ te->col=0;
+ break;
+
+ case KEY_END:
+ te->x=p[te->y].len;
+ te->col=MAX(0,te->x-TE_WIDTH);
+ break;
+
+ case KEY_LEFT:
+ {
+ int ctrl;
+
+ ctrl=key_shifts&(KB_CTRL_FLAG|KB_SHIFT_FLAG);
+
+ if (ctrl)
+ while((te->x)&&(isspace(p[te->y].p[te->x])))
+ {
+ if (te->x)
+ te->x--;
+ else
+ ctrl=FALSE;
+
+ if (te->x<te->col)
+ te->col--;
+ }
+
+ do {
+ if (te->x)
+ te->x--;
+ else
+ ctrl=FALSE;
+
+ if (te->x<te->col)
+ te->col--;
+
+ if (isspace(p[te->y].p[te->x]))
+ ctrl=FALSE;
+
+ } while(ctrl);
+
+ break;
+ }
+
+ case KEY_RIGHT:
+ {
+ int ctrl;
+
+ ctrl=key_shifts&(KB_CTRL_FLAG|KB_SHIFT_FLAG);
+
+ if (ctrl)
+ while((te->x<p[te->y].len)&&
+ (isspace(p[te->y].p[te->x])))
+ {
+ te->x++;
+
+ if ((te->x-TE_WIDTH)>te->col)
+ te->col++;
+ }
+
+ do {
+ if (te->x<p[te->y].len)
+ {
+ te->x++;
+
+ if ((te->x-TE_WIDTH)>te->col)
+ te->col++;
+ }
+ else
+ ctrl=FALSE;
+
+ if (isspace(p[te->y].p[te->x]))
+ ctrl=FALSE;
+
+ } while(ctrl);
+
+ break;
+ }
+
+ case KEY_UP:
+ if (te->y)
+ {
+ te->y--;
+
+ if (te->y<te->top)
+ te->top--;
+
+ if (te->x>p[te->y].len)
+ {
+ te->x=p[te->y].len;
+ te->col=MAX(0,te->x-TE_WIDTH);
+ }
+ }
+ break;
+
+ case KEY_PGUP:
+ if (te->y)
+ {
+ te->y-=TE_HEIGHT;
+
+ if (te->y<0)
+ te->y=0;
+
+ if (te->y<te->top)
+ te->top=te->y;
+
+ if (te->x>p[te->y].len)
+ {
+ te->x=p[te->y].len;
+ te->col=MAX(0,te->x-TE_WIDTH);
+ }
+ }
+ break;
+
+ case KEY_DOWN:
+ if (p[te->y+1].p)
+ {
+ te->y++;
+
+ if (te->y>=te->top+TE_HEIGHT)
+ te->top=te->y-TE_HEIGHT+1;
+
+ if (te->x>p[te->y].len)
+ {
+ te->x=p[te->y].len;
+ te->col=MAX(0,te->x-TE_WIDTH);
+ }
+ }
+ break;
+
+ case KEY_PGDN:
+ te->y+=TE_HEIGHT;
+
+ if (te->y>=te->lines)
+ te->y=te->lines-1;
+
+ if (te->y>=te->top+TE_HEIGHT)
+ te->top=te->y-TE_HEIGHT+1;
+
+ if (te->x>p[te->y].len)
+ {
+ te->x=p[te->y].len;
+ te->col=MAX(0,te->x-TE_WIDTH);
+ }
+
+ break;
+
+ case KEY_DEL:
+ if (p[te->y].p[te->x])
+ {
+ for(f=te->x;f<p[te->y].len;f++)
+ p[te->y].p[f]=p[te->y].p[f+1];
+
+ p[te->y].len--;
+ p[te->y].p[p[te->y].len]=0;
+ }
+ else if (p[te->y+1].p)
+ {
+ p[te->y].len+=p[te->y+1].len;
+
+ p[te->y].p=ReGrab(p[te->y].p,
+ (p[te->y].len/TE_CHUNK+1)*TE_CHUNK+1);
+
+ strcat(p[te->y].p,p[te->y+1].p);
+
+ Release(p[te->y+1].p);
+
+ for(f=te->y+1;f<te->lines;f++)
+ p[f]=p[f+1];
+
+ te->lines--;
+
+ p=d->dp=ReGrab(d->dp,
+ sizeof(TextEditLine)*(te->lines+1));
+ p[te->lines].p=NULL;
+ }
+ break;
+
+ case KEY_BACKSPACE:
+ if (te->x)
+ {
+ for(f=te->x;f<p[te->y].len;f++)
+ p[te->y].p[f-1]=p[te->y].p[f];
+
+ p[te->y].len--;
+ te->x--;
+ p[te->y].p[p[te->y].len]=0;
+
+ if (te->x<te->col)
+ te->col--;
+ }
+ else if (te->y)
+ {
+ te->x=p[te->y-1].len;
+ te->col=MAX(0,te->x-TE_WIDTH);
+
+ p[te->y-1].len+=p[te->y].len;
+
+ p[te->y-1].p=ReGrab(p[te->y-1].p,
+ (p[te->y-1].len/TE_CHUNK+1)*TE_CHUNK+1);
+
+ strcat(p[te->y-1].p,p[te->y].p);
+
+ Release(p[te->y].p);
+
+ for(f=te->y;f<te->lines;f++)
+ p[f]=p[f+1];
+
+ if (--te->y<te->top)
+ te->top--;
+
+ te->lines--;
+ p=d->dp=ReGrab(d->dp,
+ sizeof(TextEditLine)*(te->lines+1));
+ p[te->lines].p=NULL;
+ }
+ break;
+
+ case KEY_ENTER:
+ te->lines++;
+ p=d->dp=ReGrab(d->dp,sizeof(TextEditLine)*(te->lines+1));
+
+ for(f=te->lines;f>te->y;f--)
+ p[f]=p[f-1];
+
+ tmp=Strdup(p[te->y].p+te->x);
+ tmp=ReGrab(tmp,(strlen(tmp)/TE_CHUNK+1)*TE_CHUNK+1);
+
+ p[te->y].p[te->x]=0;
+ p[te->y].len=strlen(p[te->y].p);
+
+ te->y++;
+ te->x=0;
+ te->col=0;
+
+ p[te->y].p=tmp;
+ p[te->y].len=strlen(tmp);
+
+ if (te->y>=te->top+TE_HEIGHT)
+ te->top=te->y-TE_HEIGHT+1;
+
+ break;
+
+ case KEY_TAB:
+ for(f=te->x%4+1;f<=4;f++)
+ simulate_keypress(KEY_SPACE<<8|' ');
+ break;
+
+ default:
+ if (isprint(c&0xff))
+ {
+ p[te->y].len++;
+
+ if (!(p[te->y].len%TE_CHUNK))
+ p[te->y].p=ReGrab(p[te->y].p,
+ (p[te->y].len/TE_CHUNK+1)*
+ TE_CHUNK+1);
+
+ for(f=p[te->y].len;f>te->x;f--)
+ p[te->y].p[f]=p[te->y].p[f-1];
+
+ p[te->y].p[te->x]=(c&0xff);
+
+ te->x++;
+
+ if ((te->x-TE_WIDTH)>te->col)
+ te->col++;
+ }
+ break;
+ }
+
+ show_mouse(NULL);
+ SEND_MESSAGE(d,MSG_DRAW,0);
+ show_mouse(screen);
+ return(D_USED_CHAR);
+ break;
+ }
+
+ return (D_O_K);
+}
+
+
+static int d_dial_picklist(int msg, DIALOG *d, int c)
+{
+ char **text;
+ int lx,ly;
+
+ text=d->dp;
+
+ switch(msg)
+ {
+ case MSG_START:
+ break;
+
+ case MSG_END:
+ break;
+
+ case MSG_DRAW:
+ {
+ int bx1,by1,bx2,by2;
+
+ bx1=d->x+d->w-d->h+1;
+ by1=d->y;
+ bx2=d->x+d->w-1;
+ by2=d->y+d->h-1;
+
+ text_mode(-1);
+
+ if (d->flags&D_GOTFOCUS)
+ rectfill(screen,d->x,d->y,d->x+d->w-1,d->y+d->h-1,ACOL(PL_COL));
+ else
+ rectfill(screen,d->x,d->y,d->x+d->w-1,d->y+d->h-1,ACOL(WHITE));
+
+ Rect3D(bx1,by1,d->h,d->h,FALSE,BEVEL);
+
+ textout(screen,font,text[d->d1],d->x,d->y,d->fg);
+ break;
+ }
+
+ case MSG_WANTFOCUS:
+ return(D_WANTFOCUS);
+ break;
+
+ case MSG_CLICK:
+ {
+ BITMAP *under;
+ int done;
+ BoundBox b;
+ int fg,bg;
+ int f;
+ int draw;
+ int cur;
+ int last;
+ int new;
+ int press;
+ int first;
+
+ text_mode(-1);
+ cur=d->d1;
+ press=FALSE;
+ first=TRUE;
+
+ done=FALSE;
+ b.h=d->d2*(FH+1)+1;
+ b.w=d->w;
+ b.x=d->x;
+ b.y=d->y;
+
+ if ((b.x+b.w)>SCRW)
+ b.x=SCRW-b.w;
+
+ if ((b.y+b.h)>SCRH)
+ b.y=SCRH-b.h;
+
+ if (!(under=create_bitmap(b.w+1,b.h+1)))
+ GFX_exit(EXIT_FAILURE,"No more memory to create save under\n");
+
+ show_mouse(NULL);
+ blit(screen,under,b.x,b.y,0,0,b.w+1,b.h+1);
+ show_mouse(screen);
+
+ show_mouse(NULL);
+ rectfill(screen,b.x,b.y,b.x+b.w,b.y+b.h,ACOL(WHITE));
+ rect(screen,b.x,b.y,b.x+b.w,b.y+b.h,ACOL(BLACK));
+
+ for(f=0;f<d->d2;f++)
+ {
+ if (f==cur)
+ {
+ fg=ACOL(WHITE);
+ bg=ACOL(BLACK);
+ }
+ else
+ {
+ fg=ACOL(BLACK);
+ bg=ACOL(WHITE);
+ }
+
+ rectfill(screen,b.x+1,b.y+1+(FH+1)*f,
+ b.x+b.w-1,b.y+b.h-1,bg);
+ textout(screen,font,text[f],b.x+1,b.y+1+(FH+1)*f,fg);
+ }
+
+ show_mouse(screen);
+
+ draw=FALSE;
+ last=-1;
+ lx=-1;
+ ly=-1;
+
+ while(!done)
+ {
+ if (draw)
+ {
+ show_mouse(NULL);
+
+ for(f=0;f<d->d2;f++)
+ {
+ if (f==cur)
+ {
+ fg=ACOL(WHITE);
+ bg=ACOL(BLACK);
+
+ rectfill(screen,b.x+1,b.y+1+(FH+1)*f,
+ b.x+b.w-1,b.y+(FH+1)*(f+1),bg);
+ textout(screen,font,text[f],
+ b.x+1,b.y+1+(FH+1)*f,fg);
+ }
+ else if (f==last)
+ {
+ fg=ACOL(BLACK);
+ bg=ACOL(WHITE);
+
+ rectfill(screen,b.x+1,b.y+1+(FH+1)*f,
+ b.x+b.w-1,b.y+(FH+1)*(f+1),bg);
+ textout(screen,font,text[f],
+ b.x+1,b.y+1+(FH+1)*f,fg);
+ }
+ }
+
+ show_mouse(screen);
+ draw=FALSE;
+ }
+
+ if (first)
+ {
+ while(mouse_b);
+ first=FALSE;
+ }
+
+ if (keypressed())
+ {
+ int k;
+
+ k=readkey();
+
+ switch(k>>8)
+ {
+ case KEY_UP:
+ draw=TRUE;
+
+ if (cur==-1)
+ cur=d->d2-1;
+ else
+ if (--cur<0)
+ cur+=d->d2;
+ break;
+
+ case KEY_DOWN:
+ draw=TRUE;
+
+ if (cur==-1)
+ cur=0;
+ else
+ cur=(cur+1)%d->d2;
+ break;
+
+ case KEY_ESC:
+ cur=-1;
+ done=TRUE;
+ break;
+
+ case KEY_ENTER:
+ done=TRUE;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ if ((mouse_b)&&(!press))
+ press=TRUE;
+
+ if ((!mouse_b)&&(press))
+ {
+ done=TRUE;
+ lx=-1;
+ ly=-1;
+ }
+
+ last=cur;
+
+ if ((lx!=mouse_x)||(ly!=mouse_y))
+ {
+ lx=mouse_x;
+ ly=mouse_y;
+
+ if (MouseInBox(&b,1)!=-1)
+ {
+ new=(mouse_y-b.y)/(FH+1);
+
+ if (new>=d->d2)
+ new=d->d2-1;
+
+ if (new!=cur)
+ {
+ cur=new;
+ draw=TRUE;
+ }
+ }
+ else
+ {
+ if (cur!=-1)
+ draw=TRUE;
+
+ cur=-1;
+ }
+ }
+ }
+ }
+
+ if (cur!=-1)
+ d->d1=cur;
+
+ show_mouse(NULL);
+ blit(under,screen,0,0,b.x,b.y,b.w+1,b.h+1);
+ SEND_MESSAGE(d,MSG_DRAW,0);
+ show_mouse(screen);
+
+ break;
+ }
+
+ case MSG_CHAR:
+ switch(c>>8)
+ {
+ case KEY_ENTER:
+ SEND_MESSAGE(d,MSG_CLICK,0);
+ break;
+
+ default:
+ return(D_O_K);
+ break;
+ }
+
+ show_mouse(NULL);
+ SEND_MESSAGE(d,MSG_DRAW,0);
+ show_mouse(screen);
+ return(D_USED_CHAR);
+ break;
+
+ default:
+ break;
+ }
+
+ return(D_O_K);
+}
+
+
+static int d_title_proc(int msg, DIALOG *d, int c)
+{
+ char *t;
+ int x,y;
+ int l;
+
+ if (msg==MSG_DRAW)
+ {
+ t=d->dp;
+ l=strlen(t);
+
+ x=d->x-l*(FW/2);
+ y=d->y;
+
+ text_mode(d->bg);
+ textout(screen,font,t,x,y,d->fg);
+
+ line(screen,active_dialog[0].x+BEVEL+1,d->y+FH+1,
+ active_dialog[0].x+active_dialog[0].w-BEVEL-1,
+ d->y+FH+1,ACOL(GUI_HI));
+
+ line(screen,active_dialog[0].x+BEVEL+1,d->y+FH+2,
+ active_dialog[0].x+active_dialog[0].w-BEVEL-1,
+ d->y+FH+2,ACOL(GUI_LO));
+ }
+
+ return(D_O_K);
+}
+
+
+static int d_my_ctext_proc(int msg, DIALOG *d, int c)
+{
+ char *t;
+ int x,y;
+ int l;
+
+ if (msg==MSG_DRAW)
+ {
+ t=d->dp;
+ l=strlen(t);
+
+ x=d->x-l*(FW/2);
+ y=d->y;
+
+ text_mode(d->bg);
+ textout(screen,font,t,x,y,d->fg);
+ }
+
+ return(D_O_K);
+}
+
+
+static int d_my_text_proc(int msg, DIALOG *d, int c)
+{
+ if (msg==MSG_DRAW)
+ {
+ text_mode(d->bg);
+ textout(screen,font,d->dp,d->x,d->y,d->fg);
+ }
+
+ return(D_O_K);
+}
+
+
+/* ---------------------------------------- FILE SELECTION CODE
+
+ This code is a copy of the file selector code provided by Shawn Hargreaves
+ in his Allegro library (original filename fsel.c). The only changes are
+ to the file_selector[] DIALOG structure and some of the fs_*_proc()
+ callbacks to use my 3D buttons, etc.
+
+ If this code causes problems, blame *ME*, _not_ Shawn!
+*/
+
+
+#ifndef _USE_LFN
+#define _USE_LFN 0
+#endif
+
+static int fs_edit_proc(int, DIALOG *, int );
+static int fs_flist_proc(int, DIALOG *, int );
+static int fs_dlist_proc(int, DIALOG *, int );
+static char *fs_flist_getter(int, int *);
+static char *fs_dlist_getter(int, int *);
+
+
+#define FLIST_SIZE 2048
+
+typedef struct FLIST
+{
+ char dir[80];
+ int size;
+ char *name[FLIST_SIZE];
+} FLIST;
+
+static FLIST *flist = NULL;
+
+static char *fext = NULL;
+
+
+
+static DIALOG file_selector[] =
+{
+ /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
+ { d_3d_box, 0, 0, 304, 160, 0, 0, 0, 0, 0, 0, NULL },
+ { d_inv_3d_box, 14, 26, 276, 12, 0, 0, 0, 0, 0, 0, NULL },
+ { d_my_ctext_proc, 152, 8, 1, 1, 0, 0, 0, 0, 0, 0, NULL },
+ { my_d_button_proc, 208, 107, 80, 16, 0, 0, 0, D_EXIT, 0, 0, "OK" },
+ { my_d_button_proc, 208, 129, 80, 16, 0, 0, 27, D_EXIT, 0, 0, "Cancel" },
+ { fs_edit_proc, 16, 28, 272, 8, 0, 0, 0, 0, 79, 0, NULL },
+ { fs_flist_proc, 16, 46, 176, 99, 0, 0, 0, D_EXIT, 0, 0, fs_flist_getter },
+ { fs_dlist_proc, 208, 46, 80, 51, 0, 0, 0, D_EXIT, 0, 0, fs_dlist_getter },
+ { NULL }
+};
+
+#define FS_MESSAGE 2
+#define FS_OK 3
+#define FS_CANCEL 4
+#define FS_EDIT 5
+#define FS_FILES 6
+#define FS_DISKS 7
+
+
+
+/* fs_dlist_getter:
+ * Listbox data getter routine for the file selector disk list.
+ */
+static char *fs_dlist_getter(int index, int *list_size)
+{
+ static char d[] = "A:\\";
+
+ if (index < 0) {
+ if (list_size)
+ *list_size = 26;
+ return NULL;
+ }
+
+ d[0] = 'A' + index;
+ return d;
+}
+
+
+
+/* fs_dlist_proc:
+ * Dialog procedure for the file selector disk list.
+ */
+static int fs_dlist_proc(int msg, DIALOG *d, int c)
+{
+ int ret;
+ char *s = file_selector[FS_EDIT].dp;
+
+ if (msg == MSG_START)
+ d->d1 = d->d2 = 0;
+
+ ret = my_d_list_proc(msg, d, c);
+
+ if (ret == D_CLOSE) {
+ *(s++) = 'A' + d->d1;
+ *(s++) = ':';
+ *(s++) = '\\';
+ *s = 0;
+ show_mouse(NULL);
+ SEND_MESSAGE(file_selector+FS_FILES, MSG_START, 0);
+ SEND_MESSAGE(file_selector+FS_FILES, MSG_DRAW, 0);
+ SEND_MESSAGE(file_selector+FS_EDIT, MSG_START, 0);
+ SEND_MESSAGE(file_selector+FS_EDIT, MSG_DRAW, 0);
+ show_mouse(screen);
+ return D_O_K;
+ }
+
+ return ret;
+}
+
+
+
+/* fs_edit_proc:
+ * Dialog procedure for the file selector editable string.
+ */
+static int fs_edit_proc(int msg, DIALOG *d, int c)
+{
+ char *s = d->dp;
+ int ch;
+ int attr;
+ int x;
+ char b[80];
+
+ if (msg == MSG_START) {
+ if (s[0]) {
+ _fixpath(s, b);
+ errno = 0;
+
+ x = s[strlen(s)-1];
+ if ((x=='/') || (x=='\\'))
+ put_backslash(b);
+
+ for (x=0; b[x]; x++) {
+ if (b[x] == '/')
+ s[x] = '\\';
+ else
+ s[x] = toupper(b[x]);
+ }
+ s[x] = 0;
+ }
+ }
+
+ if (msg == MSG_KEY) {
+ if (*s)
+ ch = s[strlen(s)-1];
+ else
+ ch = 0;
+ if (ch == ':')
+ put_backslash(s);
+ else {
+ if ((ch != '/') && (ch != '\\')) {
+ if (file_exists(s, FA_RDONLY | FA_HIDDEN | FA_DIREC, &attr)) {
+ if (attr & FA_DIREC)
+ put_backslash(s);
+ else
+ return D_CLOSE;
+ }
+ else
+ return D_CLOSE;
+ }
+ }
+ show_mouse(NULL);
+ SEND_MESSAGE(file_selector+FS_FILES, MSG_START, 0);
+ SEND_MESSAGE(file_selector+FS_FILES, MSG_DRAW, 0);
+ SEND_MESSAGE(d, MSG_START, 0);
+ SEND_MESSAGE(d, MSG_DRAW, 0);
+ show_mouse(screen);
+ return D_O_K;
+ }
+
+ if (msg==MSG_CHAR) {
+ ch = c & 0xff;
+ if ((ch >= 'a') && (ch <= 'z'))
+ c = (c & 0xffffff00L) | (ch - 'a' + 'A');
+ else if (ch == '/')
+ c = (c & 0xffffff00L) | '\\';
+ else if (_USE_LFN) {
+ if ((ch > 127) || ((ch < 32) && (ch != 8) && (ch != 0)))
+ return D_O_K;
+ }
+ else {
+ if ((ch != '\\') && (ch != '_') && (ch != ':') && (ch != '.') &&
+ ((ch < 'A') || (ch > 'Z')) && ((ch < '0') || (ch > '9')) &&
+ (ch != 8) && (ch != 127) && (ch != 0))
+ return D_O_K;
+ }
+ }
+
+ return d_edit_proc(msg, d, c);
+}
+
+
+
+/* fs_flist_putter:
+ * Callback routine for for_each_file() to fill the file selector listbox.
+ */
+static void fs_flist_putter(char *str, int attrib)
+{
+ int c, c2;
+ char *s, *ext, *tok;
+ char tmp[80];
+ static char ext_tokens[] = " ,;";
+
+ s = get_filename(str);
+ strupr(s);
+
+ if ((fext) && (!(attrib & FA_DIREC))) {
+ strcpy(tmp, fext);
+ ext = get_extension(s);
+ tok = strtok(tmp, ext_tokens);
+ while (tok) {
+ if (stricmp(ext, tok) == 0)
+ break;
+ tok = strtok(NULL, ext_tokens);
+ }
+ if (!tok)
+ return;
+ }
+
+ if ((flist->size < FLIST_SIZE) && (strcmp(s,".") != 0)) {
+ for (c=0; c<flist->size; c++) {
+ if (flist->name[c][strlen(flist->name[c])-1]=='\\') {
+ if (attrib & FA_DIREC)
+ if (strcmp(s, flist->name[c]) < 0)
+ break;
+ }
+ else {
+ if (attrib & FA_DIREC)
+ break;
+ if (strcmp(s, flist->name[c]) < 0)
+ break;
+ }
+ }
+ for (c2=flist->size; c2>c; c2--)
+ flist->name[c2] = flist->name[c2-1];
+
+ flist->name[c] = malloc(strlen(s) + ((attrib & FA_DIREC) ? 2 : 1));
+ strcpy(flist->name[c], s);
+ if (attrib & FA_DIREC)
+ put_backslash(flist->name[c]);
+ flist->size++;
+ }
+}
+
+
+
+/* fs_flist_getter:
+ * Listbox data getter routine for the file selector list.
+ */
+static char *fs_flist_getter(int index, int *list_size)
+{
+ if (index < 0) {
+ if (list_size)
+ *list_size = flist->size;
+ return NULL;
+ }
+ return flist->name[index];
+}
+
+
+
+/* fs_flist_proc:
+ * Dialog procedure for the file selector list.
+ */
+static int fs_flist_proc(int msg, DIALOG *d, int c)
+{
+ int i, ret;
+ int sel = d->d1;
+ char *s = file_selector[FS_EDIT].dp;
+ static int recurse_flag = 0;
+
+ if (msg == MSG_START) {
+ if (!flist)
+ flist = malloc(sizeof(FLIST));
+ else {
+ for (i=0; i<flist->size; i++)
+ if (flist->name[i])
+ free(flist->name[i]);
+ }
+ if (!flist) {
+ errno = ENOMEM;
+ return D_CLOSE;
+ }
+ flist->size = 0;
+ for (i=0; i<flist->size; i++)
+ flist->name[i] = NULL;
+ strcpy(flist->dir, s);
+ *get_filename(flist->dir) = 0;
+ put_backslash(flist->dir);
+ strcat(flist->dir,"*.*");
+ for_each_file(flist->dir, FA_RDONLY | FA_DIREC | FA_ARCH, fs_flist_putter, 0);
+ if (errno)
+ alert(NULL, "Disk error", NULL, "OK", NULL, 13, 0);
+ *get_filename(flist->dir) = 0;
+ d->d1 = d->d2 = 0;
+ sel = 0;
+ }
+
+ if (msg == MSG_END) {
+ if (flist) {
+ for (i=0; i<flist->size; i++)
+ if (flist->name[i])
+ free(flist->name[i]);
+ free(flist);
+ }
+ flist = NULL;
+ }
+
+ recurse_flag++;
+ ret = my_d_list_proc(msg,d,c); /* call the parent procedure */
+ recurse_flag--;
+
+ if (((sel != d->d1) || (ret == D_CLOSE)) && (recurse_flag == 0)) {
+ strcpy(s, flist->dir);
+ *get_filename(s) = 0;
+ put_backslash(s);
+ strcat(s, flist->name[d->d1]);
+ show_mouse(NULL);
+ SEND_MESSAGE(file_selector+FS_EDIT, MSG_START, 0);
+ SEND_MESSAGE(file_selector+FS_EDIT, MSG_DRAW, 0);
+ show_mouse(screen);
+
+ if (ret == D_CLOSE)
+ return SEND_MESSAGE(file_selector+FS_EDIT, MSG_KEY, 0);
+ }
+
+ return ret;
+}
+
+
+
+/* my_file_select:
+ * Displays the Allegro file selector, with the message as caption.
+ * Allows the user to select a file, and stores the selection in path
+ * (which should have room for at least 80 characters). The files are
+ * filtered according to the file extensions in ext. Passing NULL
+ * includes all files, "PCX;BMP" includes only files with .PCX or .BMP
+ * extensions. Returns zero if it was closed with the Cancel button,
+ * non-zero if it was OK'd.
+ */
+int my_file_select(char *message, char *path, char *ext)
+{
+ int ret;
+ char *p;
+ int f;
+
+ f=0;
+ while(file_selector[f].proc)
+ {
+ switch(f)
+ {
+ case FS_EDIT:
+ case FS_FILES:
+ case FS_DISKS:
+ file_selector[f].fg=ACOL(BLACK);
+ file_selector[f].bg=ACOL(WHITE);
+ break;
+
+ default:
+ file_selector[f].fg=gui_fg_color;
+ file_selector[f].bg=gui_bg_color;
+ break;
+ }
+
+ f++;
+ }
+
+ file_selector[FS_MESSAGE].dp = message;
+ file_selector[FS_EDIT].dp = path;
+ fext = ext;
+
+ if (!path[0]) {
+ getcwd(path, 80);
+ for (p=path; *p; p++)
+ if (*p=='/')
+ *p = '\\';
+ else
+ *p = toupper(*p);
+
+ put_backslash(path);
+ }
+
+ clear_keybuf();
+
+ do {
+ } while (mouse_b);
+
+ centre_dialog(file_selector);
+ ret = do_dialog(file_selector, FS_EDIT);
+
+ if ((ret == FS_CANCEL) || (*get_filename(path) == 0))
+ return FALSE;
+
+ p = get_extension(path);
+ if ((*p == 0) && (ext) && (!strpbrk(ext, " ,;"))) {
+ *p = '.';
+ strcpy(p+1, ext);
+ }
+
+ return TRUE;
+}
+
+
+/* ---------------------------------------- GUI MENU SUPPORT FUNCS
+*/
+static void DrawMenuItem(BoundBox *b,char *txt,int sel,PLAT_MENU *child)
+{
+ int h,hy;
+ int fg;
+
+ fg=ACOL(GUI_TEXT);
+
+ if (sel)
+ Rect3D(b->x,b->y,b->w,b->h,FALSE,SMALL_BEVEL);
+ else
+ rectfill(screen,b->x,b->y,b->x+b->w-1,b->y+b->h-1,ACOL(GUI_MID));
+
+ text_mode(-1);
+ textout(screen,font,txt,b->x+SMALL_BEVEL+2,b->y+b->h/2-FH/2,fg);
+
+ if (child)
+ {
+ h=b->h-(SMALL_BEVEL*2)-2;
+ hy=b->y+SMALL_BEVEL+1;
+
+ line(screen,b->x+b->w-SMALL_BEVEL-2-h/2,hy,
+ b->x+b->w-SMALL_BEVEL-2,hy+h/2,ACOL(GUI_HI));
+
+ line(screen,b->x+b->w-SMALL_BEVEL-2-h/2,hy,
+ b->x+b->w-SMALL_BEVEL-2-h/2,hy+h,ACOL(GUI_HI));
+
+ line(screen,b->x+b->w-SMALL_BEVEL-2-h/2,hy+h,
+ b->x+b->w-SMALL_BEVEL-2,hy+h/2,ACOL(GUI_LO));
+ }
+}
+
+
+static int MouseInBox(BoundBox *box,int no)
+{
+ int f;
+
+ for(f=0;f<no;f++)
+ if (((mouse_x>=box[f].x)&&(mouse_x<box[f].x+box[f].w))&&
+ ((mouse_y>=box[f].y)&&(mouse_y<box[f].y+box[f].h)))
+ return(f);
+
+ return(-1);
+}
+
+
+/* ---------------------------------------- CALLBACK AND HANDLER FUNCTIONS
+*/
+static char *picklist_cb(int index,int *size)
+{
+ if (index<0)
+ {
+ *size=pick_no;
+ return(NULL);
+ }
+ else
+ return(pick_data[index]);
+}
+
+
+static char *img_picklist_cb(int index,int *size)
+{
+ if (index<0)
+ {
+ *size=img_pick_no;
+ return(NULL);
+ }
+ else
+ return(img_pick_data[index].text);
+}
+
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+static void init_picklist_dialog(char *title,int width)
+{
+ static int done=FALSE;
+
+ width+=15;
+
+ picklist[PL_BORDER].x=SCRW/2-width/2-20;
+ picklist[PL_BORDER].w=width+40;
+
+ picklist[PL_TITLE].w=width+30;
+ picklist[PL_TITLE].dp=title;
+
+ picklist[PL_PICKLIST].x=SCRW/2-width/2-10;
+ picklist[PL_PICKLIST].w=width+20;
+ picklist[PL_PICKLIST].d1=0;
+ picklist[PL_PICKLIST].d2=0;
+
+ picklist[PL_OK].x=picklist[PL_PICKLIST].x;
+ picklist[PL_OK].w=FW*8;
+ picklist[PL_CANCEL].x=picklist[PL_OK].x+picklist[PL_OK].w+20;
+ picklist[PL_CANCEL].w=picklist[PL_OK].w;
+
+ if (done)
+ return;
+
+ done=TRUE;
+
+ /* Box
+ */
+ picklist[PL_BORDER].proc=d_3d_box;
+ picklist[PL_BORDER].y=10;
+ picklist[PL_BORDER].h=SCRH-20;
+ picklist[PL_BORDER].fg=ACOL(GUI_TEXT);
+ picklist[PL_BORDER].bg=ACOL(GUI_MID);
+ picklist[PL_BORDER].key=0;
+ picklist[PL_BORDER].flags=0;
+ picklist[PL_BORDER].d1=picklist[PL_BORDER].d2=0;
+ picklist[PL_BORDER].dp=picklist[PL_BORDER].dp2=picklist[PL_BORDER].dp3=NULL;
+
+ /* Title
+ */
+ picklist[PL_TITLE].proc=d_my_ctext_proc;
+ picklist[PL_TITLE].x=SCRW/2;
+ picklist[PL_TITLE].y=20;
+ picklist[PL_TITLE].h=10;
+ picklist[PL_TITLE].fg=ACOL(GUI_TEXTBOLD);
+ picklist[PL_TITLE].bg=ACOL(GUI_MID);
+ picklist[PL_TITLE].key=0;
+ picklist[PL_TITLE].flags=0;
+ picklist[PL_TITLE].d1=picklist[PL_TITLE].d2=0;
+ picklist[PL_TITLE].dp2=picklist[PL_TITLE].dp3=NULL;
+
+ /* List
+ */
+ picklist[PL_PICKLIST].proc=my_d_list_proc;
+ picklist[PL_PICKLIST].y=30;
+ picklist[PL_PICKLIST].h=SCRH-60-FH*2;
+ picklist[PL_PICKLIST].fg=ACOL(BLACK);
+ picklist[PL_PICKLIST].bg=ACOL(WHITE);
+ picklist[PL_PICKLIST].key=0;
+ picklist[PL_PICKLIST].flags=D_EXIT;
+ picklist[PL_PICKLIST].dp=picklist_cb;
+ picklist[PL_PICKLIST].dp2=picklist[PL_PICKLIST].dp3=NULL;
+
+ /* OK
+ */
+ picklist[PL_OK].proc=my_d_button_proc;
+ picklist[PL_OK].y=picklist[PL_PICKLIST].y+picklist[PL_PICKLIST].h+7;
+ picklist[PL_OK].h=FH+3+BEVEL;
+ picklist[PL_OK].fg=ACOL(GUI_TEXT);
+ picklist[PL_OK].bg=ACOL(GUI_MID);
+ picklist[PL_OK].key=0;
+ picklist[PL_OK].flags=D_EXIT;
+ picklist[PL_OK].d1=picklist[PL_OK].d2=0;
+ picklist[PL_OK].dp="OK";
+ picklist[PL_OK].dp2=picklist[PL_OK].dp3=NULL;
+
+ /* Cancel
+ */
+ picklist[PL_CANCEL].proc=my_d_button_proc;
+ picklist[PL_CANCEL].y=picklist[PL_OK].y;
+ picklist[PL_CANCEL].h=FH+3+BEVEL;
+ picklist[PL_CANCEL].fg=ACOL(GUI_TEXT);
+ picklist[PL_CANCEL].bg=ACOL(GUI_MID);
+ picklist[PL_CANCEL].key=0;
+ picklist[PL_CANCEL].flags=D_EXIT;
+ picklist[PL_CANCEL].d1=picklist[PL_CANCEL].d2=0;
+ picklist[PL_CANCEL].dp="Cancel";
+ picklist[PL_CANCEL].dp2=picklist[PL_CANCEL].dp3=NULL;
+
+ memset(&picklist[PL_END],0,sizeof(DIALOG));
+ picklist[PL_END].proc=NULL;
+}
+
+
+static void init_img_picklist_dialog(char *title)
+{
+ static int done=FALSE;
+
+ img_picklist[IPL_TITLE].dp=title;
+
+ img_picklist[IPL_PICKLIST].d1=0;
+ img_picklist[IPL_PICKLIST].d2=0;
+
+ img_picklist[IPL_IMAGE].dp=img_pick_data[0].img;
+
+ if (done)
+ return;
+
+ done=TRUE;
+
+ /* Box
+ */
+ img_picklist[IPL_BORDER].proc=d_3d_box;
+ img_picklist[IPL_BORDER].y=10;
+ img_picklist[IPL_BORDER].h=SCRH-20;
+ img_picklist[IPL_BORDER].x=10;
+ img_picklist[IPL_BORDER].w=SCRW-20;
+ img_picklist[IPL_BORDER].fg=ACOL(GUI_TEXT);
+ img_picklist[IPL_BORDER].bg=ACOL(GUI_MID);
+ img_picklist[IPL_BORDER].key=0;
+ img_picklist[IPL_BORDER].flags=0;
+ img_picklist[IPL_BORDER].d1=img_picklist[IPL_BORDER].d2=0;
+ img_picklist[IPL_BORDER].dp=img_picklist[IPL_BORDER].dp2=
+ img_picklist[IPL_BORDER].dp3=NULL;
+
+ /* Title
+ */
+ img_picklist[IPL_TITLE].proc=d_my_ctext_proc;
+ img_picklist[IPL_TITLE].x=SCRW/2;
+ img_picklist[IPL_TITLE].w=SCRW-20;
+ img_picklist[IPL_TITLE].y=20;
+ img_picklist[IPL_TITLE].h=10;
+ img_picklist[IPL_TITLE].fg=ACOL(GUI_TEXTBOLD);
+ img_picklist[IPL_TITLE].bg=ACOL(GUI_MID);
+ img_picklist[IPL_TITLE].key=0;
+ img_picklist[IPL_TITLE].flags=0;
+ img_picklist[IPL_TITLE].d1=img_picklist[IPL_TITLE].d2=0;
+ img_picklist[IPL_TITLE].dp2=img_picklist[IPL_TITLE].dp3=NULL;
+
+ /* List
+ */
+ img_picklist[IPL_PICKLIST].proc=d_img_list_proc;
+ img_picklist[IPL_PICKLIST].y=30;
+ img_picklist[IPL_PICKLIST].h=SCRH-60-FH*2;
+ img_picklist[IPL_PICKLIST].x=30;
+ img_picklist[IPL_PICKLIST].w=SCRW/2;
+ img_picklist[IPL_PICKLIST].fg=ACOL(BLACK);
+ img_picklist[IPL_PICKLIST].bg=ACOL(WHITE);
+ img_picklist[IPL_PICKLIST].key=0;
+ img_picklist[IPL_PICKLIST].flags=D_EXIT;
+ img_picklist[IPL_PICKLIST].dp=img_picklist_cb;
+ img_picklist[IPL_PICKLIST].dp2=img_picklist[IPL_PICKLIST].dp3=NULL;
+
+ /* Image border
+ */
+ img_picklist[IPL_IMG_BORDER].proc=d_inv_3d_box;
+ img_picklist[IPL_IMG_BORDER].y=30;
+ img_picklist[IPL_IMG_BORDER].h=MAX_GFXBM_H+4;
+ img_picklist[IPL_IMG_BORDER].x=SCRW-MAX_GFXBM_W-24;
+ img_picklist[IPL_IMG_BORDER].w=MAX_GFXBM_W+4;
+ img_picklist[IPL_IMG_BORDER].fg=ACOL(WHITE);
+ img_picklist[IPL_IMG_BORDER].bg=ACOL(BLACK);
+ img_picklist[IPL_IMG_BORDER].key=0;
+ img_picklist[IPL_IMG_BORDER].flags=0;
+ img_picklist[IPL_IMG_BORDER].dp=img_picklist[IPL_IMG_BORDER].dp2=
+ img_picklist[IPL_IMG_BORDER].dp3=NULL;
+ img_picklist[IPL_IMG_BORDER].d1=img_picklist[IPL_IMG_BORDER].d2=0;
+
+ /* Image
+ */
+ img_picklist[IPL_IMAGE].proc=d_img_bmap_proc;
+ img_picklist[IPL_IMAGE].x=SCRW-MAX_GFXBM_W-22;
+ img_picklist[IPL_IMAGE].y=32;
+ img_picklist[IPL_IMAGE].w=MAX_GFXBM_W;
+ img_picklist[IPL_IMAGE].h=MAX_GFXBM_H;
+ img_picklist[IPL_IMAGE].fg=ACOL(0);
+ img_picklist[IPL_IMAGE].bg=ACOL(0);
+ img_picklist[IPL_IMAGE].key=0;
+ img_picklist[IPL_IMAGE].flags=0;
+ img_picklist[IPL_IMAGE].dp2=img_picklist[IPL_IMAGE].dp3=NULL;
+ img_picklist[IPL_IMAGE].d1=img_picklist[IPL_IMAGE].d2=0;
+
+ /* OK
+ */
+ img_picklist[IPL_OK].proc=my_d_button_proc;
+ img_picklist[IPL_OK].x=img_picklist[IPL_PICKLIST].x;
+ img_picklist[IPL_OK].y=img_picklist[IPL_PICKLIST].y+
+ img_picklist[IPL_PICKLIST].h+7;
+ img_picklist[IPL_OK].w=FW*8;
+ img_picklist[IPL_OK].h=FH+3+BEVEL;
+ img_picklist[IPL_OK].fg=ACOL(GUI_TEXT);
+ img_picklist[IPL_OK].bg=ACOL(GUI_MID);
+ img_picklist[IPL_OK].key=0;
+ img_picklist[IPL_OK].flags=D_EXIT;
+ img_picklist[IPL_OK].d1=img_picklist[IPL_OK].d2=0;
+ img_picklist[IPL_OK].dp="OK";
+ img_picklist[IPL_OK].dp2=img_picklist[IPL_OK].dp3=NULL;
+
+ /* Cancel
+ */
+ img_picklist[IPL_CANCEL].proc=my_d_button_proc;
+ img_picklist[IPL_CANCEL].x=img_picklist[IPL_OK].x+img_picklist[IPL_OK].w+20;
+ img_picklist[IPL_CANCEL].y=img_picklist[IPL_OK].y;
+ img_picklist[IPL_CANCEL].w=img_picklist[IPL_OK].w;
+ img_picklist[IPL_CANCEL].h=FH+3+BEVEL;
+ img_picklist[IPL_CANCEL].fg=ACOL(GUI_TEXT);
+ img_picklist[IPL_CANCEL].bg=ACOL(GUI_MID);
+ img_picklist[IPL_CANCEL].key=0;
+ img_picklist[IPL_CANCEL].flags=D_EXIT;
+ img_picklist[IPL_CANCEL].d1=img_picklist[IPL_CANCEL].d2=0;
+ img_picklist[IPL_CANCEL].dp="Cancel";
+ img_picklist[IPL_CANCEL].dp2=img_picklist[IPL_CANCEL].dp3=NULL;
+
+ memset(&img_picklist[IPL_END],0,sizeof(DIALOG));
+ img_picklist[IPL_END].proc=NULL;
+}
+
+
+/* ---------------------------------------- EXPORTED FUNCTIONS
+*/
+
+void GUI_setscreen(int w,int h)
+{
+ gui_fg_color=ACOL(GUI_TEXT);
+ gui_bg_color=ACOL(GUI_MID);
+
+ /* Disabled objects are used for bold text
+ */
+ gui_mg_color=ACOL(GUI_TEXTBOLD);
+
+ SCRW=w;
+ SCRH=h;
+
+ FW=GFX_fw();
+ FH=GFX_fh();
+}
+
+
+int GUI_yesno(char *question)
+{
+ DIALOG *d;
+ char *t;
+ char *p;
+ int no;
+ char *tl[64]; /* Should be enough... */
+ int ml,l;
+ int yl;
+ int f;
+ int h;
+ int x,y;
+ int ret;
+
+ t=Strdup(question);
+
+ no=0;
+ p=t;
+
+ tl[no++]=p;
+
+ while(*p)
+ {
+ if (*p=='|')
+ {
+ *p++=0;
+
+ if (*p)
+ tl[no++]=p;
+ }
+ else
+ p++;
+ }
+
+ h=(FH+1)*(no+1)+FH*4;
+
+ ml=FW*14;
+
+ for(f=0;f<no;f++)
+ {
+ l=(strlen(tl[f])+2)*FW;
+ ml=MAX(ml,l);
+ }
+
+ x=SCRW/2-ml/2;
+ y=SCRH/2-h/2;
+
+ d=Grab(sizeof(DIALOG)*(3+no));
+
+ /* Surrounding box
+ */
+ d[0].proc=d_3d_box;
+ d[0].x=x;
+ d[0].y=y;
+ d[0].w=ml;
+ d[0].h=h;
+ d[0].fg=ACOL(GUI_TEXT);
+ d[0].bg=ACOL(GUI_MID);
+ d[0].key=0;
+ d[0].flags=0;
+ d[0].d1=d[0].d2=0;
+ d[0].dp=d[0].dp2=d[0].dp3=NULL;
+
+ /* Text
+ */
+ yl=d[0].y+FH;
+
+ for(f=0;f<no;f++)
+ {
+ d[1+f].proc=d_my_ctext_proc;
+ d[1+f].x=SCRW/2;
+ d[1+f].w=ml-FW;
+ d[1+f].y=yl;
+ d[1+f].h=FH;
+ d[1+f].fg=ACOL(GUI_TEXT);
+ d[1+f].bg=ACOL(GUI_MID);
+ d[1+f].key=0;
+ d[1+f].flags=0;
+ d[1+f].d1=d[1+f].d2=0;
+ d[1+f].dp=tl[f];
+ d[1+f].dp2=d[1+f].dp3=NULL;
+
+ yl+=FH+1;
+ }
+
+ /* Yes
+ */
+ d[1+no].proc=my_d_button_proc;
+ d[1+no].x=x+10;
+ d[1+no].w=(ml/2)-20;
+ d[1+no].h=FH+3+BEVEL;
+ d[1+no].y=y+h-d[1+no].h-5-BEVEL;
+ d[1+no].fg=ACOL(GUI_TEXT);
+ d[1+no].bg=ACOL(GUI_MID);
+ d[1+no].key='Y';
+ d[1+no].flags=D_EXIT;
+ d[1+no].d1=d[1+no].d2=0;
+ d[1+no].dp="&Yes";
+ d[1+no].dp2=d[1+no].dp3=NULL;
+
+ /* No
+ */
+ d[2+no].proc=my_d_button_proc;
+ d[2+no].x=SCRW/2+10;
+ d[2+no].y=d[1+no].y;
+ d[2+no].w=(ml/2)-20;
+ d[2+no].h=d[1+no].h;
+ d[2+no].fg=ACOL(GUI_TEXT);
+ d[2+no].bg=ACOL(GUI_MID);
+ d[2+no].key='N';
+ d[2+no].flags=D_EXIT;
+ d[2+no].d1=d[2+no].d2=0;
+ d[2+no].dp="&No";
+ d[2+no].dp2=d[2+no].dp3=NULL;
+
+ d[3+no].proc=NULL;
+
+ GFX_bounce();
+
+ if(do_dialog(d,-1)==(1+no))
+ ret=TRUE;
+ else
+ ret=FALSE;
+
+ GFX_FORCE_REDRAW();
+
+ Release(d);
+ Release(t);
+
+ return(ret);
+}
+
+
+void GUI_start_yesno_all(void)
+{
+ all_pressed=FALSE;
+ all_result=FALSE;
+}
+
+
+int GUI_yesno_all(char *question)
+{
+ DIALOG *d;
+ char *t;
+ char *p;
+ int no;
+ char *tl[64]; /* Should be enough... */
+ int ml,l;
+ int yl;
+ int f;
+ int h;
+ int x,y;
+ int ret;
+
+ if (all_pressed)
+ return(all_result);
+
+ t=Strdup(question);
+
+ no=0;
+ p=t;
+
+ tl[no++]=p;
+
+ while(*p)
+ {
+ if (*p=='|')
+ {
+ *p++=0;
+
+ if (*p)
+ tl[no++]=p;
+ }
+ else
+ p++;
+ }
+
+ h=(FH+1)*(no+1)+FH*5;
+
+ ml=FW*26;
+
+ for(f=0;f<no;f++)
+ {
+ l=(strlen(tl[f])+2)*FW;
+ ml=MAX(ml,l);
+ }
+
+ x=SCRW/2-ml/2;
+ y=SCRH/2-h/2;
+
+ d=Grab(sizeof(DIALOG)*(5+no));
+
+ /* Surrounding box
+ */
+ d[0].proc=d_3d_box;
+ d[0].x=x;
+ d[0].y=y;
+ d[0].w=ml;
+ d[0].h=h;
+ d[0].fg=ACOL(GUI_TEXT);
+ d[0].bg=ACOL(GUI_MID);
+ d[0].key=0;
+ d[0].flags=0;
+ d[0].d1=d[0].d2=0;
+ d[0].dp=d[0].dp2=d[0].dp3=NULL;
+
+ /* Text
+ */
+ yl=d[0].y+FH;
+
+ for(f=0;f<no;f++)
+ {
+ d[1+f].proc=d_my_ctext_proc;
+ d[1+f].x=SCRW/2;
+ d[1+f].w=ml-FW;
+ d[1+f].y=yl;
+ d[1+f].h=FH;
+ d[1+f].fg=ACOL(GUI_TEXT);
+ d[1+f].bg=ACOL(GUI_MID);
+ d[1+f].key=0;
+ d[1+f].flags=0;
+ d[1+f].d1=d[1+f].d2=0;
+ d[1+f].dp=tl[f];
+ d[1+f].dp2=d[1+f].dp3=NULL;
+
+ yl+=FH+1;
+ }
+
+ /* Yes
+ */
+ d[1+no].proc=my_d_button_proc;
+ d[1+no].x=x+10;
+ d[1+no].w=(ml/2)-20;
+ d[1+no].h=FH+3+BEVEL;
+ d[1+no].y=y+h-d[1+no].h-5-BEVEL;
+ d[1+no].fg=ACOL(GUI_TEXT);
+ d[1+no].bg=ACOL(GUI_MID);
+ d[1+no].key='Y';
+ d[1+no].flags=D_EXIT;
+ d[1+no].d1=d[1+no].d2=0;
+ d[1+no].dp="&Yes";
+ d[1+no].dp2=d[1+no].dp3=NULL;
+
+ /* No
+ */
+ d[2+no].proc=my_d_button_proc;
+ d[2+no].x=SCRW/2+10;
+ d[2+no].y=d[1+no].y;
+ d[2+no].w=(ml/2)-20;
+ d[2+no].h=d[1+no].h;
+ d[2+no].fg=ACOL(GUI_TEXT);
+ d[2+no].bg=ACOL(GUI_MID);
+ d[2+no].key='N';
+ d[2+no].flags=D_EXIT;
+ d[2+no].d1=d[2+no].d2=0;
+ d[2+no].dp="&No";
+ d[2+no].dp2=d[2+no].dp3=NULL;
+
+ /* Yes to All
+ */
+ d[3+no].proc=my_d_button_proc;
+ d[3+no].x=x+10;
+ d[3+no].w=(ml/2)-20;
+ d[3+no].h=FH+3+BEVEL;
+ d[3+no].y=y+h-d[1+no].h-5-BEVEL;
+ d[3+no].fg=ACOL(GUI_TEXT);
+ d[3+no].bg=ACOL(GUI_MID);
+ d[3+no].key='A';
+ d[3+no].flags=D_EXIT;
+ d[3+no].d1=d[3+no].d2=0;
+ d[3+no].dp="Yes to &All";
+ d[3+no].dp2=d[3+no].dp3=NULL;
+
+ /* Yes to All
+ */
+ d[4+no].proc=my_d_button_proc;
+ d[4+no].x=SCRW/2+10;
+ d[4+no].w=(ml/2)-20;
+ d[4+no].h=FH+3+BEVEL;
+ d[4+no].y=y+h-d[1+no].h-5-BEVEL;
+ d[4+no].fg=ACOL(GUI_TEXT);
+ d[4+no].bg=ACOL(GUI_MID);
+ d[4+no].key='O';
+ d[4+no].flags=D_EXIT;
+ d[4+no].d1=d[4+no].d2=0;
+ d[4+no].dp="N&o to All";
+ d[4+no].dp2=d[4+no].dp3=NULL;
+
+ d[1+no].y=d[3+no].y-FH*2;
+ d[2+no].y=d[4+no].y-FH*2;
+
+ d[5+no].proc=NULL;
+
+ GFX_bounce();
+
+ ret=do_dialog(d,-1);
+
+ if (ret==(1+no))
+ all_result=TRUE;
+ else if (ret==(2+no))
+ all_result=FALSE;
+ else if (ret==(3+no))
+ {
+ all_result=TRUE;
+ all_pressed=TRUE;
+ }
+ else if (ret==(4+no))
+ {
+ all_result=FALSE;
+ all_pressed=TRUE;
+ }
+
+ GFX_FORCE_REDRAW();
+
+ Release(d);
+ Release(t);
+
+ return(all_result);
+}
+
+
+void GUI_alert(char *title, char *text, char *button_text)
+{
+ DIALOG *d;
+ char *t;
+ char *p;
+ int no;
+ char *tl[64]; /* Should be enough... */
+ int ml,l;
+ int yl;
+ int f;
+ int h;
+ int x,y;
+
+ t=Strdup(text);
+
+ no=0;
+ p=t;
+
+ tl[no++]=p;
+
+ while(*p)
+ {
+ if (*p=='|')
+ {
+ *p++=0;
+
+ if (*p)
+ tl[no++]=p;
+ }
+ else
+ p++;
+ }
+
+ h=(FH+1)*(no+2)+FH*4;
+
+ ml=(strlen(button_text)+2)*FW;
+
+ l=(strlen(title)+2)*FW;
+ ml=MAX(ml,l);
+
+ for(f=0;f<no;f++)
+ {
+ l=(strlen(tl[f])+2)*FW;
+ ml=MAX(ml,l);
+ }
+
+ x=SCRW/2-ml/2;
+ y=SCRH/2-h/2;
+
+ d=Grab(sizeof(DIALOG)*(4+no));
+
+ /* Surrounding box
+ */
+ d[0].proc=d_3d_box;
+ d[0].x=x;
+ d[0].y=y;
+ d[0].w=ml;
+ d[0].h=h;
+ d[0].fg=ACOL(GUI_TEXT);
+ d[0].bg=ACOL(GUI_MID);
+ d[0].key=0;
+ d[0].flags=0;
+ d[0].d1=d[0].d2=0;
+ d[0].dp=d[0].dp2=d[0].dp3=NULL;
+
+ /* Title
+ */
+ d[1].proc=d_title_proc;
+ d[1].x=SCRW/2;
+ d[1].w=ml-FW;
+ d[1].y=y+BEVEL+2;
+ d[1].h=FH;
+ d[1].fg=ACOL(GUI_TEXTBOLD);
+ d[1].bg=ACOL(GUI_MID);
+ d[1].key=0;
+ d[1].flags=0;
+ d[1].d1=d[1].d2=0;
+ d[1].dp=title;
+ d[1].dp2=d[1].dp3=NULL;
+
+ /* Text
+ */
+ yl=d[1].y+FH*2;
+
+ for(f=0;f<no;f++)
+ {
+ d[2+f].proc=d_my_ctext_proc;
+ d[2+f].x=SCRW/2;
+ d[2+f].w=ml-FW;
+ d[2+f].y=yl;
+ d[2+f].h=FH;
+ d[2+f].fg=ACOL(GUI_TEXT);
+ d[2+f].bg=ACOL(GUI_MID);
+ d[2+f].key=0;
+ d[2+f].flags=0;
+ d[2+f].d1=d[2+f].d2=0;
+ d[2+f].dp=tl[f];
+ d[2+f].dp2=d[2+f].dp3=NULL;
+
+ yl+=FH+1;
+ }
+
+ /* Button
+ */
+ d[2+no].proc=my_d_button_proc;
+ d[2+no].w=((strlen(button_text)+1)*FW)+BEVEL*2;
+ d[2+no].x=SCRW/2-d[2+no].w/2;
+ d[2+no].h=FH+3+BEVEL;
+ d[2+no].y=y+h-d[2+no].h-5-BEVEL;
+ d[2+no].fg=ACOL(GUI_TEXT);
+ d[2+no].bg=ACOL(GUI_MID);
+ d[2+no].key='\r';
+ d[2+no].flags=D_EXIT;
+ d[2+no].d1=d[2+no].d2=0;
+ d[2+no].dp=button_text;
+ d[2+no].dp2=d[2+no].dp3=NULL;
+
+ d[3+no].proc=NULL;
+
+ GFX_bounce();
+
+ do_dialog(d,2+no);
+
+ GFX_FORCE_REDRAW();
+ Release(d);
+ Release(t);
+}
+
+
+static MenuControl do_GUI_menu(char *title, int x, int y,
+ PLAT_MENU menu[],int defval,int is_child)
+{
+ MenuControl ret;
+ MenuControl cr;
+ int lx,ly;
+ int no;
+ int f;
+ BITMAP *under;
+ int cur;
+ int last_cur;
+ int cx;
+ int by;
+ int done;
+ int quit;
+ int child_done;
+ BoundBox *box;
+ BoundBox menu_box;
+ int do_child;
+
+ /* Calc dimensions
+ */
+ no=0;
+ menu_box.x=x;
+ menu_box.y=y;
+ menu_box.w=text_length(font,title);
+
+ while(menu[no].text)
+ {
+ int l;
+
+ l=text_length(font,menu[no].text)+(menu[no].child ? 12 : 0);
+ menu_box.w=MAX(menu_box.w,l);
+ no++;
+ }
+
+ menu_box.h=BEVEL*2+FH+4;
+ menu_box.h+=(FH+SMALL_BEVEL*2+2)*no;
+ menu_box.h+=2;
+ menu_box.w+=BEVEL+SMALL_BEVEL+4;
+
+ box=Grab(sizeof(BoundBox)*no);
+
+ if ((menu_box.x+menu_box.w)>SCRW)
+ menu_box.x=SCRW-menu_box.w;
+
+ if ((menu_box.y+menu_box.h)>SCRH)
+ menu_box.y=SCRH-menu_box.h;
+
+ if ((menu_box.x<0)||(menu_box.y<0))
+ {
+ alert("Cannot display menu:",title,"Menu is bigger than display!",
+ "OK",NULL,0,0);
+
+ ret.mode=MENU_CHILD_RETURN;
+ ret.ret=defval;
+
+ return(ret);
+ }
+
+ cx=menu_box.x+menu_box.w/2;
+
+ /* Save screen contents
+ */
+ show_mouse(NULL);
+
+ if (!(under=create_bitmap(menu_box.w+1,menu_box.h+1)))
+ GFX_exit(EXIT_FAILURE,"No more memory to create MENU save under\n");
+
+ blit(screen,under,menu_box.x,menu_box.y,0,0,menu_box.w+1,menu_box.h+1);
+
+ /* Draw menu border and title
+ */
+ Rect3D(menu_box.x,menu_box.y,menu_box.w,menu_box.h,FALSE,BEVEL);
+ text_mode(-1);
+ textout_centre(screen,font,title,cx,menu_box.y+BEVEL*2,ACOL(GUI_TEXTBOLD));
+
+ /* Draw menu items
+ */
+ cur=0;
+ last_cur=-1;
+
+ by=menu_box.y+BEVEL*2+FH+4;
+
+ for(f=0;f<no;f++)
+ {
+ box[f].x=menu_box.x+BEVEL;
+ box[f].y=by;
+ box[f].w=menu_box.w-BEVEL*2;
+ box[f].h=FH+SMALL_BEVEL*2+2;
+ by+=box[f].h;
+
+ DrawMenuItem(&box[f],menu[f].text,(f==cur),menu[f].child);
+ }
+
+ show_mouse(screen);
+ GFX_bounce();
+
+ /* Main loop
+ */
+ quit=FALSE;
+ done=FALSE;
+ child_done=FALSE;
+ lx=mouse_x;
+ ly=mouse_y;
+ do_child=FALSE;
+
+ while((!done)&&(!quit)&&(!child_done))
+ {
+ /* Handle input
+ */
+ if (!do_child)
+ {
+ if (mouse_b)
+ {
+ int new;
+
+ new=MouseInBox(box,no);
+
+ if (new==-1)
+ {
+ if (MouseInBox(&menu_box,1)==-1)
+ {
+ quit=TRUE;
+ ret.mode=MENU_CANCEL_CLICK;
+
+ while(mouse_b);
+ }
+ }
+ else
+ {
+ if (menu[new].child)
+ {
+ cur=new;
+ while(mouse_b);
+ do_child=TRUE;
+ }
+ else
+ {
+ done=TRUE;
+ cur=new;
+ ret.mode=MENU_OK;
+ while(mouse_b);
+ }
+ }
+ }
+ else if (keypressed())
+ switch(readkey()>>8)
+ {
+ case KEY_ESC:
+ quit=TRUE;
+ ret.mode=MENU_CANCEL_ESC;
+ break;
+
+ case KEY_ENTER:
+ ret.mode=MENU_OK;
+ done=TRUE;
+ break;
+
+ case KEY_DOWN:
+ show_mouse(NULL);
+ DrawMenuItem(&box[cur],menu[cur].text,FALSE,
+ menu[cur].child);
+
+ cur=(cur+1)%no;
+
+ DrawMenuItem(&box[cur],menu[cur].text,TRUE,
+ menu[cur].child);
+ show_mouse(screen);
+ break;
+
+ case KEY_UP:
+ show_mouse(NULL);
+ DrawMenuItem(&box[cur],menu[cur].text,FALSE,
+ menu[cur].child);
+
+ if (cur)
+ cur--;
+ else
+ cur=no-1;
+
+ DrawMenuItem(&box[cur],menu[cur].text,TRUE,
+ menu[cur].child);
+ show_mouse(screen);
+ break;
+
+ case KEY_RIGHT:
+ if (menu[cur].child)
+ do_child=TRUE;
+
+ break;
+
+ case KEY_LEFT:
+ if (is_child)
+ {
+ quit=TRUE;
+ ret.mode=MENU_CHILD_RETURN;
+ }
+ break;
+ }
+ else if ((lx!=mouse_x)||(ly!=mouse_y))
+ {
+ int new;
+
+ lx=mouse_x;
+ ly=mouse_y;
+
+ new=MouseInBox(box,no);
+
+ if (new!=-1)
+ cur=new;
+ }
+ }
+
+
+ /* Draw menu selection if changed
+ */
+ if (cur!=last_cur)
+ {
+ show_mouse(NULL);
+
+ if (last_cur!=-1)
+ DrawMenuItem(&box[last_cur],menu[last_cur].text,FALSE,
+ menu[last_cur].child);
+
+ DrawMenuItem(&box[cur],menu[cur].text,TRUE,
+ menu[cur].child);
+ show_mouse(screen);
+ }
+
+ last_cur=cur;
+
+ /* Handle child menus
+ */
+ if (do_child)
+ {
+ do_child=FALSE;
+
+ cr=do_GUI_menu(menu[cur].text,
+ box[cur].x+box[cur].w,box[cur].y,
+ menu[cur].child,defval,TRUE);
+
+ switch(cr.mode)
+ {
+ case MENU_OK:
+ child_done=TRUE;
+ break;
+
+ case MENU_CANCEL_ESC:
+ quit=TRUE;
+ ret.mode=MENU_CANCEL_ESC;
+ break;
+
+ case MENU_CANCEL_CLICK:
+ if (MouseInBox(&menu_box,1)==-1)
+ {
+ quit=TRUE;
+ ret.mode=MENU_CANCEL_CLICK;
+ }
+ else
+ {
+ if ((cur=MouseInBox(box,no))==-1)
+ cur=0;
+ else if (menu[cur].child)
+ do_child=TRUE;
+ }
+
+ break;
+
+ case MENU_CHILD_RETURN:
+ break;
+ }
+ }
+ }
+
+ show_mouse(NULL);
+ blit(under,screen,0,0,menu_box.x,menu_box.y,menu_box.w+1,menu_box.h+1);
+ show_mouse(screen);
+ destroy_bitmap(under);
+ Release(box);
+
+ if (child_done)
+ ret=cr;
+ else
+ {
+ if (!quit)
+ ret.ret=menu[cur].client_index;
+ else
+ ret.ret=defval;
+ }
+
+ return(ret);
+}
+
+
+int GUI_menu(char *title, int x, int y, PLAT_MENU menu[],int defval)
+{
+ return(do_GUI_menu(title,x,y,menu,defval,FALSE).ret);
+}
+
+
+char *GUI_fsel(char *title, char *default_path, char *filter)
+{
+ int ret;
+ char path[PATH_MAX+1];
+
+ if ((filter)&&(*filter=='.'))
+ filter++;
+
+ strcpy(path,default_path);
+
+ GFX_bounce();
+
+ ret=my_file_select(title,path,filter);
+
+ GFX_FORCE_REDRAW();
+
+ if (ret)
+ return(Strdup(path));
+
+ return(NULL);
+}
+
+
+int GUI_picklist(char *title,char *opt[])
+{
+ int ml;
+ int ret;
+
+ pick_no=0;
+
+ /* Enough room for the OK/CANCEL
+ */
+ ml=(FW*16)+30;
+ ml=MAX(ml,gui_strlen(title));
+
+ while(opt[pick_no])
+ {
+ if (gui_strlen(opt[pick_no])>ml)
+ ml=gui_strlen(opt[pick_no]);
+ pick_no++;
+ }
+
+ pick_data=opt;
+
+ init_picklist_dialog(title,ml);
+
+ GFX_bounce();
+ ret=do_dialog(picklist,-1);
+ GFX_FORCE_REDRAW();
+
+ switch(ret)
+ {
+ case PL_OK:
+ case PL_PICKLIST:
+ return(picklist[IPL_PICKLIST].d1);
+ break;
+
+ default:
+ return(-1);
+ break;
+ }
+}
+
+
+int GUI_client_picklist(char *title,PLAT_PICKLIST opt[],int defval)
+{
+ int ml;
+ int ret;
+ char **c_opt;
+ int f;
+
+ pick_no=0;
+
+ /* Enough room for the OK/CANCEL
+ */
+ ml=(FW*16)+30;
+ ml=MAX(ml,gui_strlen(title));
+
+ while(opt[pick_no].text)
+ {
+ if (gui_strlen(opt[pick_no].text)>ml)
+ ml=gui_strlen(opt[pick_no].text);
+ pick_no++;
+ }
+
+ c_opt=Grab(sizeof(char *)*(pick_no+1));
+
+ for(f=0;f<pick_no;f++)
+ c_opt[f]=opt[f].text;
+
+ c_opt[f]=NULL;
+
+ pick_data=c_opt;
+
+ init_picklist_dialog(title,ml);
+
+ GFX_bounce();
+ ret=do_dialog(picklist,-1);
+ GFX_FORCE_REDRAW();
+ Release(c_opt);
+
+ switch(ret)
+ {
+ case PL_OK:
+ case PL_PICKLIST:
+ return(opt[picklist[PL_PICKLIST].d1].client_index);
+ break;
+
+ default:
+ return(defval);
+ break;
+ }
+}
+
+
+int GUI_image_picklist(char *title,PLAT_IMG_PICKLIST opt[],int defval)
+{
+ int ret;
+
+ img_pick_no=0;
+ while(opt[img_pick_no].text)
+ img_pick_no++;
+
+ img_pick_data=opt;
+
+ init_img_picklist_dialog(title);
+
+ GFX_bounce();
+ ret=do_dialog(img_picklist,-1);
+ GFX_FORCE_REDRAW();
+
+ if (ret==-1)
+ return(defval);
+
+ switch(ret)
+ {
+ case IPL_OK:
+ case IPL_PICKLIST:
+ return(opt[img_picklist[IPL_PICKLIST].d1].client_index);
+ break;
+
+ default:
+ return(defval);
+ break;
+ }
+}
+
+
+int GUI_radio_box(char *title,PLAT_RADIO opt[],int current,int defval)
+{
+ int no;
+ DIALOG *d;
+ int ml,l;
+ int h;
+ int f;
+ int ret;
+ int x,y;
+
+ no=0;
+ while(opt[no].text)
+ no++;
+
+ d=Grab(sizeof(DIALOG)*(no+6));
+
+ h=(FH+5)*no;
+ ml=text_length(font,"CANCEL CANCEL");
+
+ for(f=0;f<no;f++)
+ if ((l=text_length(font,opt[f].text))>ml)
+ ml=l;
+
+ h+=FH*4;
+ ml+=FW*4;
+ x=SCRW/2-ml/2;
+ y=SCRH/2-h/2;
+
+ /* Surrounding box
+ */
+ d[0].proc=d_3d_box;
+ d[0].x=x;
+ d[0].y=y;
+ d[0].w=ml;
+ d[0].h=h;
+ d[0].fg=ACOL(GUI_TEXT);
+ d[0].bg=ACOL(GUI_MID);
+ d[0].key=0;
+ d[0].flags=0;
+ d[0].d1=d[0].d2=0;
+ d[0].dp=d[0].dp2=d[0].dp3=NULL;
+
+ /* Title
+ */
+ d[1].proc=d_my_ctext_proc;
+ d[1].x=SCRW/2;
+ d[1].w=ml-20;
+ d[1].y=y+10;
+ d[1].h=10;
+ d[1].fg=ACOL(GUI_TEXTBOLD);
+ d[1].bg=ACOL(GUI_MID);
+ d[1].key=0;
+ d[1].flags=0;
+ d[1].d1=d[1].d2=0;
+ d[1].dp=title;
+ d[1].dp2=d[1].dp3=NULL;
+
+ /* OK
+ */
+ d[2].proc=my_d_button_proc;
+ d[2].x=x+10;
+ d[2].y=y+h-15;
+ d[2].w=(ml/2)-20;
+ d[2].h=10+BEVEL;
+ d[2].fg=ACOL(GUI_TEXT);
+ d[2].bg=ACOL(GUI_MID);
+ d[2].key=0;
+ d[2].flags=D_EXIT;
+ d[2].d1=d[2].d2=0;
+ d[2].dp="OK";
+ d[2].dp2=d[2].dp3=NULL;
+
+ /* CANCEL
+ */
+ d[3].proc=my_d_button_proc;
+ d[3].x=SCRW/2+10;
+ d[3].y=y+h-15;
+ d[3].w=(ml/2)-20;
+ d[3].h=10+BEVEL;
+ d[3].fg=ACOL(GUI_TEXT);
+ d[3].bg=ACOL(GUI_MID);
+ d[3].key=0;
+ d[3].flags=D_EXIT;
+ d[3].d1=d[3].d2=0;
+ d[3].dp="Cancel";
+ d[3].dp2=d[3].dp3=NULL;
+
+ /* Buttons
+ */
+ for(f=0;f<no;f++)
+ {
+ d[4+f].proc=my_d_radio_proc;
+ d[4+f].x=x+10;
+ d[4+f].y=y+20+f*10;
+ d[4+f].w=ml-20;
+ d[4+f].h=10;
+ d[4+f].fg=ACOL(GUI_TEXT);
+ d[4+f].bg=ACOL(GUI_MID);
+ d[4+f].key=0;
+ d[4+f].flags=(f==0 ? D_SELECTED : 0);
+ d[4+f].d1=d[4+f].d2=0;
+ d[4+f].dp=opt[f].text;
+ d[4+f].dp2=d[4+f].dp3=NULL;
+ }
+
+ d[4+no].proc=NULL;
+
+ for(f=0;f<no;f++)
+ if (opt[f].client_index==current)
+ {
+ d[4].flags=0;
+ d[4+f].flags=D_SELECTED;
+ }
+
+ ret=defval;
+
+ GFX_bounce();
+ if(do_dialog(d,-1)==2)
+ for(f=0;f<no;f++)
+ if (d[4+f].flags&D_SELECTED)
+ ret=opt[f].client_index;
+
+ Release(d);
+
+ return(ret);
+}
+
+
+int GUI_multi_box(char *title,PLAT_MULTI p[])
+{
+ int no;
+ DIALOG *d;
+ int ml,l;
+ int h;
+ int f;
+ int ret;
+ int x,y;
+
+ no=0;
+ while(p[no].text)
+ no++;
+
+ d=Grab(sizeof(DIALOG)*(no+6));
+
+ h=(FH+5)*no;
+ ml=text_length(font,"CANCEL CANCEL");
+
+ for(f=0;f<no;f++)
+ if ((l=text_length(font,p[f].text))>ml)
+ ml=l;
+
+ h+=FH*4;
+ ml+=FW*4;
+ x=SCRW/2-ml/2;
+ y=SCRH/2-h/2;
+
+ /* Surrounding box
+ */
+ d[0].proc=d_3d_box;
+ d[0].x=x;
+ d[0].y=y;
+ d[0].w=ml;
+ d[0].h=h;
+ d[0].fg=ACOL(GUI_TEXT);
+ d[0].bg=ACOL(GUI_MID);
+ d[0].key=0;
+ d[0].flags=0;
+ d[0].d1=d[0].d2=0;
+ d[0].dp=d[0].dp2=d[0].dp3=NULL;
+
+ /* Title
+ */
+ d[1].proc=d_my_ctext_proc;
+ d[1].x=SCRW/2;
+ d[1].w=ml-20;
+ d[1].y=y+10;
+ d[1].h=10;
+ d[1].fg=ACOL(GUI_TEXTBOLD);
+ d[1].bg=ACOL(GUI_MID);
+ d[1].key=0;
+ d[1].flags=0;
+ d[1].d1=d[1].d2=0;
+ d[1].dp=title;
+ d[1].dp2=d[1].dp3=NULL;
+
+ /* OK
+ */
+ d[2].proc=my_d_button_proc;
+ d[2].x=x+10;
+ d[2].y=y+h-15;
+ d[2].w=(ml/2)-20;
+ d[2].h=10+BEVEL;
+ d[2].fg=ACOL(GUI_TEXT);
+ d[2].bg=ACOL(GUI_MID);
+ d[2].key=0;
+ d[2].flags=D_EXIT;
+ d[2].d1=d[2].d2=0;
+ d[2].dp="OK";
+ d[2].dp2=d[2].dp3=NULL;
+
+ /* CANCEL
+ */
+ d[3].proc=my_d_button_proc;
+ d[3].x=SCRW/2+10;
+ d[3].y=y+h-15;
+ d[3].w=(ml/2)-20;
+ d[3].h=10+BEVEL;
+ d[3].fg=ACOL(GUI_TEXT);
+ d[3].bg=ACOL(GUI_MID);
+ d[3].key=0;
+ d[3].flags=D_EXIT;
+ d[3].d1=d[3].d2=0;
+ d[3].dp="Cancel";
+ d[3].dp2=d[3].dp3=NULL;
+
+ /* Buttons
+ */
+ for(f=0;f<no;f++)
+ {
+ d[4+f].proc=my_d_check_proc;
+ d[4+f].x=x+10;
+ d[4+f].y=y+20+f*10;
+ d[4+f].w=ml-20;
+ d[4+f].h=10;
+ d[4+f].fg=ACOL(GUI_TEXT);
+ d[4+f].bg=ACOL(GUI_MID);
+ d[4+f].key=0;
+
+ if (p[f].val)
+ d[4+f].flags=D_SELECTED;
+ else
+ d[4+f].flags=0;
+
+ d[4+f].d1=p[f].group;
+ d[4+f].d2=0;
+ d[4+f].dp=p[f].text;
+ d[4+f].dp2=d[4+f].dp3=NULL;
+ }
+
+ d[4+no].proc=NULL;
+
+ GFX_bounce();
+
+ if(do_dialog(d,-1)==2)
+ {
+ for(f=0;f<no;f++)
+ if (d[4+f].flags&D_SELECTED)
+ p[f].val=TRUE;
+ else
+ p[f].val=FALSE;
+
+ ret=TRUE;
+ }
+ else
+ ret=FALSE;
+
+ GFX_FORCE_REDRAW();
+ Release(d);
+
+ return(ret);
+}
+
+
+int GUI_dialog(char *title, int no, PLAT_DIALOG pd[])
+{
+ DIALOG *d;
+ int tl,ml,pl,l;
+ int h;
+ int f,r;
+ int ret;
+ int x,y;
+ char *p;
+ int tmp;
+ double d_tmp;
+
+ d=Grab(sizeof(DIALOG)*(no*3+6));
+
+ h=(FH+10)*no;
+ tl=0;
+
+ for(f=0;f<no;f++)
+ if ((pd[f].text)&&((l=text_length(font,pd[f].text))>tl))
+ tl=l;
+
+ pl=DIALOG_STRLEN*FW;
+
+ for(f=0;f<no;f++)
+ if (pd[f].type==PLAT_DIAL_PICKLIST)
+ for(r=0;r<pd[f].data.pl.no;r++)
+ if ((l=text_length(font,pd[f].data.pl.text[r])+10)>pl)
+ pl=l;
+
+ ml=tl+pl+(FW*4);
+
+ if (ml<(text_length(font,title)+FW*4))
+ ml=text_length(font,title)+FW*4;
+
+ h+=FH*5;
+ x=SCRW/2-ml/2;
+ y=SCRH/2-h/2;
+
+ /* Surrounding box
+ */
+ d[0].proc=d_3d_box;
+ d[0].x=x;
+ d[0].y=y;
+ d[0].w=ml;
+ d[0].h=h;
+ d[0].fg=ACOL(GUI_TEXT);
+ d[0].bg=ACOL(GUI_MID);
+ d[0].key=0;
+ d[0].flags=0;
+ d[0].d1=d[0].d2=0;
+ d[0].dp=d[0].dp2=d[0].dp3=NULL;
+
+ /* Title
+ */
+ d[1].proc=d_my_ctext_proc;
+ d[1].x=SCRW/2;
+ d[1].w=ml-20;
+ d[1].y=y+3;
+ d[1].h=10;
+ d[1].fg=ACOL(GUI_TEXTBOLD);
+ d[1].bg=ACOL(GUI_MID);
+ d[1].key=0;
+ d[1].flags=0;
+ d[1].d1=d[1].d2=0;
+ d[1].dp=title;
+ d[1].dp2=d[1].dp3=NULL;
+
+ /* OK
+ */
+ d[2].proc=my_d_button_proc;
+ d[2].x=x+10;
+ d[2].w=(ml/2)-20;
+ d[2].h=FH+3+BEVEL;
+ d[2].y=y+h-d[2].h-5-BEVEL;
+ d[2].fg=ACOL(GUI_TEXT);
+ d[2].bg=ACOL(GUI_MID);
+ d[2].key=0;
+ d[2].flags=D_EXIT;
+ d[2].d1=d[2].d2=0;
+ d[2].dp="OK";
+ d[2].dp2=d[2].dp3=NULL;
+
+ /* CANCEL
+ */
+ d[3].proc=my_d_button_proc;
+ d[3].x=SCRW/2+10;
+ d[3].y=d[2].y;
+ d[3].w=(ml/2)-20;
+ d[3].h=d[2].h;
+ d[3].fg=ACOL(GUI_TEXT);
+ d[3].bg=ACOL(GUI_MID);
+ d[3].key=0;
+ d[3].flags=D_EXIT;
+ d[3].d1=d[3].d2=0;
+ d[3].dp="Cancel";
+ d[3].dp2=d[3].dp3=NULL;
+
+ /* Labels and text entries
+ */
+ for(f=0;f<no;f++)
+ {
+ if (pd[f].text)
+ p=pd[f].text;
+ else
+ p="";
+
+ d[4+(f*3)].proc=d_my_text_proc;
+ d[4+(f*3)].x=x+FW;
+ d[4+(f*3)].y=y+23+f*15;
+ d[4+(f*3)].w=text_length(font,p);
+ d[4+(f*3)].h=10;
+ d[4+(f*3)].fg=ACOL(GUI_TEXT);
+ d[4+(f*3)].bg=ACOL(GUI_MID);
+ d[4+(f*3)].key=0;
+ d[4+(f*3)].flags=0;
+ d[4+(f*3)].d1=0;
+ d[4+(f*3)].d2=0;
+ d[4+(f*3)].dp=p;
+ d[4+(f*3)].dp2=d[4+(f*3)].dp3=NULL;
+
+ if (pd[f].type==PLAT_DIAL_PICKLIST)
+ {
+ d[5+(f*3)].proc=d_inv_3d_box;
+ d[5+(f*3)].x=d[4+(f*3)].x+tl+FW;
+ d[5+(f*3)].y=y+21+f*15;
+ d[5+(f*3)].h=FH+BEVEL*2;
+ d[5+(f*3)].fg=ACOL(GUI_LO);
+ d[5+(f*3)].bg=ACOL(GUI_MID);
+ d[5+(f*3)].key=0;
+ d[5+(f*3)].flags=0;
+ d[5+(f*3)].d1=d[5+(f*3)].d2=0;
+ d[5+(f*3)].dp=d[5+(f*3)].dp2=d[5+(f*3)].dp3=NULL;
+
+ d[6+(f*3)].w=0;
+
+ for(r=0;r<pd[f].data.pl.no;r++)
+ if ((l=text_length(font,pd[f].data.pl.text[r])+10)>d[6+(f*3)].w)
+ d[6+(f*3)].w=l;
+
+ d[5+(f*3)].w=d[6+(f*3)].w+BEVEL*2;
+
+ d[6+(f*3)].proc=d_dial_picklist;
+ d[6+(f*3)].x=d[5+(f*3)].x+BEVEL;
+ d[6+(f*3)].y=y+20+BEVEL+1+f*15;
+ d[6+(f*3)].h=FH;
+ d[6+(f*3)].fg=ACOL(BLACK);
+ d[6+(f*3)].bg=ACOL(WHITE);
+ d[6+(f*3)].key=0;
+ d[6+(f*3)].flags=0;
+ d[6+(f*3)].d1=pd[f].data.pl.current;
+ d[6+(f*3)].d2=pd[f].data.pl.no;
+ d[6+(f*3)].dp=pd[f].data.pl.text;
+ d[6+(f*3)].dp2=d[6+(f*3)].dp3=NULL;
+ }
+ else
+ {
+ if (pd[f].type==PLAT_DIAL_INTEGER)
+ {
+ tmp=pd[f].data.i;
+ sprintf(pd[f].data.s,"%d",tmp);
+ }
+
+ if (pd[f].type==PLAT_DIAL_DOUBLE)
+ {
+ d_tmp=pd[f].data.d;
+ sprintf(pd[f].data.s,"%G",d_tmp);
+ }
+
+ d[5+(f*3)].proc=d_inv_3d_box;
+ d[5+(f*3)].x=d[4+(f*3)].x+tl+FW;
+ d[5+(f*3)].y=y+21+f*15;
+ d[5+(f*3)].w=text_length(font," ")*DIALOG_STRLEN+2*BEVEL;
+ d[5+(f*3)].h=8+BEVEL*2;
+ d[5+(f*3)].fg=ACOL(GUI_LO);
+ d[5+(f*3)].bg=ACOL(GUI_MID);
+ d[5+(f*3)].key=0;
+ d[5+(f*3)].flags=0;
+ d[5+(f*3)].d1=d[5+(f*3)].d2=0;
+ d[5+(f*3)].dp=d[5+(f*3)].dp2=d[5+(f*3)].dp3=NULL;
+
+ d[6+(f*3)].proc=d_edit_proc;
+ d[6+(f*3)].x=d[5+(f*3)].x+BEVEL;
+ d[6+(f*3)].y=y+20+BEVEL+1+f*15;
+ d[6+(f*3)].w=text_length(font," ")*DIALOG_STRLEN;
+ d[6+(f*3)].h=10;
+ /*
+ d[6+(f*3)].fg=ACOL(GUI_TEXT);
+ d[6+(f*3)].bg=ACOL(GUI_MID);
+ */
+ d[6+(f*3)].fg=ACOL(BLACK);
+ d[6+(f*3)].bg=ACOL(WHITE);
+ d[6+(f*3)].key=0;
+ d[6+(f*3)].flags=0;
+ d[6+(f*3)].d1=PLAT_DIAL_MAXSTRLEN;
+ d[6+(f*3)].d2=strlen(pd[f].data.s);
+ d[6+(f*3)].dp=pd[f].data.s;
+ d[6+(f*3)].dp2=d[6+(f*3)].dp3=NULL;
+ }
+ }
+
+ d[4+(no*3)].proc=NULL;
+
+ GFX_bounce();
+ if(do_dialog(d,-1)==2)
+ {
+ for(f=0;f<no;f++)
+ {
+ if (pd[f].type==PLAT_DIAL_INTEGER)
+ {
+ tmp=(int)strtol(pd[f].data.s,NULL,0);
+ pd[f].data.i=tmp;
+ }
+ else if (pd[f].type==PLAT_DIAL_DOUBLE)
+ {
+ d_tmp=strtod(pd[f].data.s,NULL);
+ pd[f].data.d=d_tmp;
+ }
+ else if (pd[f].type==PLAT_DIAL_PICKLIST)
+ pd[f].data.pl.current=d[6+(f*3)].d1;
+ }
+
+ ret=TRUE;
+ }
+ else
+ ret=FALSE;
+
+ GFX_FORCE_REDRAW();
+ Release(d);
+
+ return(ret);
+}
+
+
+void GUI_view_file (char *title, char *path)
+{
+ FILE *fp;
+ int no;
+ char s[BUFF_LEN];
+ char **line;
+ int f;
+ int ml;
+ int bw;
+ int bh;
+
+ if ((fp=fopen(path,"r")))
+ {
+ no=0;
+ fgets(s,BUFF_LEN,fp);
+
+ while(!feof(fp))
+ {
+ no++;
+ fgets(s,BUFF_LEN,fp);
+ }
+
+ fclose(fp);
+
+ line=Grab(sizeof(char *)*(no+1));
+
+ f=0;
+ fp=fopen(path,"r");
+
+ fgets(s,BUFF_LEN,fp);
+
+ ml=0;
+
+ while(!feof(fp))
+ {
+ line[f]=Strdup(ConvertFileText(s));
+ ml=MAX(ml,strlen(line[f]));
+ f++;
+ fgets(s,BUFF_LEN,fp);
+ }
+
+ fclose(fp);
+
+ line[f]=NULL;
+ }
+ else
+ {
+ no=2;
+ ml=0;
+ line=Grab(sizeof(char *)*3);
+ line[0]=Strdup("File not found:");
+ line[1]=Strdup(path);
+ line[2]=NULL;
+ }
+
+ bw=FV_WIDTH*FW+20+FV_SCROLLWIDTH;
+ bh=FV_HEIGHT*FH+20+FV_SCROLLWIDTH+20+FH*2;
+
+ /* Box
+ */
+ fv_dialog[FV_BORDER].proc=d_3d_box;
+ fv_dialog[FV_BORDER].y=0;
+ fv_dialog[FV_BORDER].h=bh;
+ fv_dialog[FV_BORDER].x=0;
+ fv_dialog[FV_BORDER].w=bw;
+ fv_dialog[FV_BORDER].fg=ACOL(GUI_TEXT);
+ fv_dialog[FV_BORDER].bg=ACOL(GUI_MID);
+ fv_dialog[FV_BORDER].key=0;
+ fv_dialog[FV_BORDER].flags=0;
+ fv_dialog[FV_BORDER].d1=fv_dialog[FV_BORDER].d2=0;
+ fv_dialog[FV_BORDER].dp=fv_dialog[FV_BORDER].dp2=
+ fv_dialog[FV_BORDER].dp3=NULL;
+
+ /* Title
+ */
+ fv_dialog[FV_TITLE].proc=d_my_ctext_proc;
+ fv_dialog[FV_TITLE].x=bw/2;
+ fv_dialog[FV_TITLE].w=bw-20;
+ fv_dialog[FV_TITLE].y=BEVEL+5;
+ fv_dialog[FV_TITLE].h=FH;
+ fv_dialog[FV_TITLE].fg=ACOL(GUI_TEXTBOLD);
+ fv_dialog[FV_TITLE].bg=ACOL(GUI_MID);
+ fv_dialog[FV_TITLE].key=0;
+ fv_dialog[FV_TITLE].flags=0;
+ fv_dialog[FV_TITLE].d1=fv_dialog[FV_TITLE].d2=0;
+ fv_dialog[FV_TITLE].dp2=fv_dialog[FV_TITLE].dp3=NULL;
+ fv_dialog[FV_TITLE].dp=title;
+
+ /* Text Box Pt 1
+ */
+ fv_dialog[FV_TEXTBOX].proc=d_inv_3d_box;
+ fv_dialog[FV_TEXTBOX].y=BEVEL+5+FH+5;
+ fv_dialog[FV_TEXTBOX].x=BEVEL+5;
+ fv_dialog[FV_TEXTBOX].fg=ACOL(GUI_TEXT);
+ fv_dialog[FV_TEXTBOX].bg=ACOL(GUI_MID);
+ fv_dialog[FV_TEXTBOX].key=0;
+ fv_dialog[FV_TEXTBOX].flags=0;
+ fv_dialog[FV_TEXTBOX].d1=fv_dialog[FV_TEXTBOX].d2=0;
+ fv_dialog[FV_TEXTBOX].dp=fv_dialog[FV_TEXTBOX].dp2=
+ fv_dialog[FV_TEXTBOX].dp3=NULL;
+
+ /* Text
+ */
+ fv_dialog[FV_TEXT].proc=d_ro_textbox;
+ fv_dialog[FV_TEXT].y=fv_dialog[FV_TEXTBOX].y+BEVEL;
+ fv_dialog[FV_TEXT].h=FH*FV_HEIGHT;
+ fv_dialog[FV_TEXT].x=fv_dialog[FV_TEXTBOX].x+BEVEL;
+ fv_dialog[FV_TEXT].w=FW*FV_WIDTH;
+ fv_dialog[FV_TEXT].fg=ACOL(BLACK);
+ fv_dialog[FV_TEXT].bg=ACOL(WHITE);
+ fv_dialog[FV_TEXT].key=0;
+ fv_dialog[FV_TEXT].flags=0;
+ fv_dialog[FV_TEXT].d1=0;
+ fv_dialog[FV_TEXT].d2=0;
+ fv_dialog[FV_TEXT].dp=line;
+ fv_dialog[FV_TEXT].dp2=fv_dialog[FV_TEXT].dp3=NULL;
+
+ /* Text Box Pt 2
+ */
+ fv_dialog[FV_TEXTBOX].w=fv_dialog[FV_TEXT].w+BEVEL*2;
+ fv_dialog[FV_TEXTBOX].h=fv_dialog[FV_TEXT].h+BEVEL*2;
+
+ /* Vertical scrollbar
+ */
+ fv_dialog[FV_VERT_SCROLL].proc=d_vert_scrollbar;
+ fv_dialog[FV_VERT_SCROLL].x=fv_dialog[FV_TEXTBOX].x+
+ fv_dialog[FV_TEXTBOX].w+3;
+ fv_dialog[FV_VERT_SCROLL].y=fv_dialog[FV_TEXTBOX].y;
+ fv_dialog[FV_VERT_SCROLL].w=FV_SCROLLWIDTH;
+ fv_dialog[FV_VERT_SCROLL].h=fv_dialog[FV_TEXTBOX].h;
+ fv_dialog[FV_VERT_SCROLL].fg=ACOL(GUI_TEXT);
+ fv_dialog[FV_VERT_SCROLL].bg=ACOL(GUI_MID);
+ fv_dialog[FV_VERT_SCROLL].key=0;
+ fv_dialog[FV_VERT_SCROLL].flags=0;
+ fv_dialog[FV_VERT_SCROLL].d1=FV_HEIGHT;
+ fv_dialog[FV_VERT_SCROLL].d2=MAX(0,no-FV_HEIGHT);
+ fv_dialog[FV_VERT_SCROLL].dp=&fv_dialog[FV_TEXT].d2;
+ fv_dialog[FV_VERT_SCROLL].dp2=&fv_dialog[FV_TEXT];
+ fv_dialog[FV_VERT_SCROLL].dp3=NULL;
+
+ /* Horizontal scrollbar
+ */
+ fv_dialog[FV_HORIZ_SCROLL].proc=d_horiz_scrollbar;
+ fv_dialog[FV_HORIZ_SCROLL].x=fv_dialog[FV_TEXTBOX].x;
+ fv_dialog[FV_HORIZ_SCROLL].y=fv_dialog[FV_TEXTBOX].y+
+ fv_dialog[FV_TEXTBOX].h+3;
+ fv_dialog[FV_HORIZ_SCROLL].w=fv_dialog[FV_TEXTBOX].w;
+ fv_dialog[FV_HORIZ_SCROLL].h=FV_SCROLLWIDTH;
+ fv_dialog[FV_HORIZ_SCROLL].fg=ACOL(GUI_TEXT);
+ fv_dialog[FV_HORIZ_SCROLL].bg=ACOL(GUI_MID);
+ fv_dialog[FV_HORIZ_SCROLL].key=0;
+ fv_dialog[FV_HORIZ_SCROLL].flags=0;
+ fv_dialog[FV_HORIZ_SCROLL].d1=FV_WIDTH;
+ fv_dialog[FV_HORIZ_SCROLL].d2=MAX(0,ml-FV_WIDTH);
+ fv_dialog[FV_HORIZ_SCROLL].dp=&fv_dialog[FV_TEXT].d1;
+ fv_dialog[FV_HORIZ_SCROLL].dp2=&fv_dialog[FV_TEXT];
+ fv_dialog[FV_HORIZ_SCROLL].dp3=NULL;
+
+ /* OK
+ */
+ fv_dialog[FV_OK].proc=my_d_button_proc;
+ fv_dialog[FV_OK].x=fv_dialog[FV_TEXTBOX].x;
+ fv_dialog[FV_OK].y=fv_dialog[FV_HORIZ_SCROLL].y+
+ fv_dialog[FV_HORIZ_SCROLL].h+5;
+ fv_dialog[FV_OK].w=FW*5;
+ fv_dialog[FV_OK].h=FH+3+BEVEL;
+ fv_dialog[FV_OK].fg=ACOL(GUI_TEXT);
+ fv_dialog[FV_OK].bg=ACOL(GUI_MID);
+ fv_dialog[FV_OK].key=0;
+ fv_dialog[FV_OK].flags=D_EXIT;
+ fv_dialog[FV_OK].d1=fv_dialog[FV_OK].d2=0;
+ fv_dialog[FV_OK].dp="OK";
+ fv_dialog[FV_OK].dp2=fv_dialog[FV_OK].dp3=NULL;
+
+ fv_dialog[FV_END].proc=NULL;
+
+ do_dialog(fv_dialog,-1);
+
+ for(f=0;f<no;f++)
+ Release(line[f]);
+
+ Release(line);
+
+ GFX_FORCE_REDRAW();
+}
+
+
+char *GUI_text_edit (char *title, char *text)
+{
+ char *cp_text;
+ char *p;
+ TextEditLine *line;
+ char *ret;
+ int f;
+ int size;
+ int no;
+ int bw;
+ int bh;
+
+ p=text;
+
+ if (*(p+strlen(p)-1)=='\n')
+ no=0;
+ else
+ no=1;
+
+ while(*p)
+ if (*p++=='\n')
+ no++;
+
+ line=Grab(sizeof(TextEditLine)*(no+1));
+ cp_text=Strdup(text);
+ p=cp_text;
+
+ for(f=0;f<no;f++)
+ {
+ char *e;
+
+ e=p;
+
+ while((*e)&&(*e!='\n'))
+ e++;
+
+ *e=0;
+
+ /* We rely on the fact that Grab() zeroes data...
+ */
+ line[f].len=strlen(p);
+ line[f].p=Grab((line[f].len/TE_CHUNK+1)*TE_CHUNK+1);
+ strcpy(line[f].p,p);
+ p=e+1;
+ }
+
+ line[f].p=NULL;
+ line[f].len=0;
+ Release(cp_text);
+
+ bw=(TE_WIDTH+1)*FW+20;
+ bh=TE_HEIGHT*FH+40+FH*2;
+
+ /* Box
+ */
+ te_dialog[TE_BORDER].proc=d_3d_box;
+ te_dialog[TE_BORDER].y=0;
+ te_dialog[TE_BORDER].h=bh;
+ te_dialog[TE_BORDER].x=0;
+ te_dialog[TE_BORDER].w=bw;
+ te_dialog[TE_BORDER].fg=ACOL(GUI_TEXT);
+ te_dialog[TE_BORDER].bg=ACOL(GUI_MID);
+ te_dialog[TE_BORDER].key=0;
+ te_dialog[TE_BORDER].flags=0;
+ te_dialog[TE_BORDER].d1=te_dialog[TE_BORDER].d2=0;
+ te_dialog[TE_BORDER].dp=te_dialog[TE_BORDER].dp2=
+ te_dialog[TE_BORDER].dp3=NULL;
+
+ /* Title
+ */
+ te_dialog[TE_TITLE].proc=d_my_ctext_proc;
+ te_dialog[TE_TITLE].x=bw/2;
+ te_dialog[TE_TITLE].w=bw-20;
+ te_dialog[TE_TITLE].y=BEVEL+5;
+ te_dialog[TE_TITLE].h=FH;
+ te_dialog[TE_TITLE].fg=ACOL(GUI_TEXTBOLD);
+ te_dialog[TE_TITLE].bg=ACOL(GUI_MID);
+ te_dialog[TE_TITLE].key=0;
+ te_dialog[TE_TITLE].flags=0;
+ te_dialog[TE_TITLE].d1=te_dialog[TE_TITLE].d2=0;
+ te_dialog[TE_TITLE].dp2=te_dialog[TE_TITLE].dp3=NULL;
+ te_dialog[TE_TITLE].dp=title;
+
+ /* Text Box Pt 1
+ */
+ te_dialog[TE_TEXTBOX].proc=d_inv_3d_box;
+ te_dialog[TE_TEXTBOX].y=BEVEL+5+FH+5;
+ te_dialog[TE_TEXTBOX].x=BEVEL+5;
+ te_dialog[TE_TEXTBOX].fg=ACOL(GUI_TEXT);
+ te_dialog[TE_TEXTBOX].bg=ACOL(GUI_MID);
+ te_dialog[TE_TEXTBOX].key=0;
+ te_dialog[TE_TEXTBOX].flags=0;
+ te_dialog[TE_TEXTBOX].d1=te_dialog[TE_TEXTBOX].d2=0;
+ te_dialog[TE_TEXTBOX].dp=te_dialog[TE_TEXTBOX].dp2=
+ te_dialog[TE_TEXTBOX].dp3=NULL;
+
+ /* Text
+ */
+ te_dialog[TE_TEXT].proc=d_textedit;
+ te_dialog[TE_TEXT].y=te_dialog[TE_TEXTBOX].y+BEVEL;
+ te_dialog[TE_TEXT].h=FH*TE_HEIGHT;
+ te_dialog[TE_TEXT].x=te_dialog[TE_TEXTBOX].x+BEVEL;
+ te_dialog[TE_TEXT].w=FW*(TE_WIDTH+1);
+ te_dialog[TE_TEXT].fg=ACOL(BLACK);
+ te_dialog[TE_TEXT].bg=ACOL(WHITE);
+ te_dialog[TE_TEXT].key=0;
+ te_dialog[TE_TEXT].flags=0;
+ te_dialog[TE_TEXT].d1=0;
+ te_dialog[TE_TEXT].d2=0;
+ te_dialog[TE_TEXT].dp=line;
+ te_dialog[TE_TEXT].dp2=te_dialog[TE_TEXT].dp3=NULL;
+
+ /* Text Box Pt 2
+ */
+ te_dialog[TE_TEXTBOX].w=te_dialog[TE_TEXT].w+BEVEL*2;
+ te_dialog[TE_TEXTBOX].h=te_dialog[TE_TEXT].h+BEVEL*2;
+
+ /* OK
+ */
+ te_dialog[TE_OK].proc=my_d_button_proc;
+ te_dialog[TE_OK].x=te_dialog[TE_TEXTBOX].x;
+ te_dialog[TE_OK].y=te_dialog[TE_TEXTBOX].y+te_dialog[TE_TEXTBOX].h+7;
+ te_dialog[TE_OK].w=FW*8;
+ te_dialog[TE_OK].h=FH+3+BEVEL;
+ te_dialog[TE_OK].fg=ACOL(GUI_TEXT);
+ te_dialog[TE_OK].bg=ACOL(GUI_MID);
+ te_dialog[TE_OK].key=0;
+ te_dialog[TE_OK].flags=D_EXIT;
+ te_dialog[TE_OK].d1=te_dialog[TE_OK].d2=0;
+ te_dialog[TE_OK].dp="OK";
+ te_dialog[TE_OK].dp2=te_dialog[TE_OK].dp3=NULL;
+
+ /* CANCEL
+ */
+ te_dialog[TE_CANCEL].proc=my_d_button_proc;
+ te_dialog[TE_CANCEL].x=te_dialog[TE_OK].x+te_dialog[TE_OK].w+20;
+ te_dialog[TE_CANCEL].y=te_dialog[TE_TEXTBOX].y+te_dialog[TE_TEXTBOX].h+7;
+ te_dialog[TE_CANCEL].w=FW*8;
+ te_dialog[TE_CANCEL].h=FH+3+BEVEL;
+ te_dialog[TE_CANCEL].fg=ACOL(GUI_TEXT);
+ te_dialog[TE_CANCEL].bg=ACOL(GUI_MID);
+ te_dialog[TE_CANCEL].key=0;
+ te_dialog[TE_CANCEL].flags=D_EXIT;
+ te_dialog[TE_CANCEL].d1=te_dialog[TE_CANCEL].d2=0;
+ te_dialog[TE_CANCEL].dp="Cancel";
+ te_dialog[TE_CANCEL].dp2=te_dialog[TE_CANCEL].dp3=NULL;
+
+ te_dialog[TE_END].proc=NULL;
+
+ no=do_dialog(te_dialog,TE_TEXT);
+ line=te_dialog[TE_TEXT].dp;
+
+ if (no==TE_OK)
+ {
+ f=0;
+ size=0;
+
+ while(line[f].p)
+ size+=line[f++].len+1;
+
+ size++;
+
+ ret=Grab(size);
+ *ret=0;
+
+ f=0;
+
+ while(line[f].p)
+ {
+ strcat(ret,line[f++].p);
+
+ if (line[f].p)
+ strcat(ret,"\n");
+ }
+ }
+ else
+ ret=NULL;
+
+ f=0;
+ while(line[f].p)
+ Release(line[f++].p);
+
+ Release(line);
+
+ GFX_FORCE_REDRAW();
+
+ return(ret);
+}
+
+
+/* END OF FILE */
diff --git a/djgpp/runcmd.c b/djgpp/runcmd.c
new file mode 100644
index 0000000..2148806
--- /dev/null
+++ b/djgpp/runcmd.c
@@ -0,0 +1,143 @@
+/*
+
+ viDOOM - level editor for DOOM
+
+ Copyright (C) 2000 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ Command execution interface
+
+*/
+static const char rcs_id[]="$Id$";
+
+#include "config.h"
+#include "mem.h"
+
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <process.h>
+
+#define MAX_ARGS 128
+
+static void CopyArgs(char *argv[],char *new[])
+{
+ char *na;
+ char *p;
+ int len;
+ int f;
+
+ len=0;
+ f=0;
+ while(argv[f])
+ len+=strlen(argv[f++])+1;
+
+ len++;
+
+ na=Grab(len);
+
+ f=0;
+ while(argv[f])
+ {
+ strcat(na,argv[f++]);
+ strcat(na," ");
+ }
+
+ f=0;
+ p=strtok(na," \t");
+
+ while((f<MAX_ARGS-1)&&(p))
+ {
+ new[f++]=Strdup(p);
+ p=strtok(NULL," \t");
+ }
+
+ new[f]=NULL;
+
+ Release(na);
+}
+
+
+static void Write(int fd, char *p)
+{
+ write(fd,p,strlen(p));
+}
+
+
+int RunCommand(char *argv[], char *path)
+{
+ static int old_stdout=-1;
+ static int old_stderr=-1;
+ int ret;
+ int f;
+ int fd;
+ char *new[MAX_ARGS];
+
+ if (old_stdout==-1)
+ if ((old_stdout=dup(STDOUT_FILENO))==-1)
+ return(FALSE);
+
+ if (old_stderr==-1)
+ if ((old_stderr=dup(STDERR_FILENO))==-1)
+ return(FALSE);
+
+ tmpnam(path);
+
+ if ((fd=open(path,O_WRONLY|O_CREAT|O_TRUNC,0666))==-1)
+ return(FALSE);
+
+ CopyArgs(argv,new);
+
+ if (!new[0])
+ {
+ close(fd);
+ return(FALSE);
+ }
+
+ dup2(fd,STDOUT_FILENO);
+ dup2(fd,STDERR_FILENO);
+
+ ret=spawnvp(P_WAIT,new[0],new);
+
+ f=0;
+ while(new[f])
+ Release(new[f++]);
+
+ if (ret==-1)
+ {
+ Write(fd,"Exec failed:\n");
+ Write(fd,sys_errlist[errno]);
+ Write(fd,"\n");
+ }
+
+ dup2(old_stdout,STDOUT_FILENO);
+ dup2(old_stderr,STDERR_FILENO);
+ close(fd);
+
+ if (ret==-1)
+ return(FALSE);
+
+ /* Assume that non-zero is error
+ */
+ return(ret==0);
+}
+
+
+/* END OF FILE */
diff --git a/djgpp/vstring.c b/djgpp/vstring.c
new file mode 100644
index 0000000..947ca99
--- /dev/null
+++ b/djgpp/vstring.c
@@ -0,0 +1,48 @@
+/*
+
+ viDOOM - level editor for DOOM
+
+ Copyright (C) 2000 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ Provides portable versions of necessary string routines
+
+*/
+static const char rcs_id[]="$Id$";
+
+#include <string.h>
+
+
+int StrCaseCmp(char *a, char *b)
+{
+ if (!a || !b)
+ return 0;
+
+ return strcasecmp(a,b);
+}
+
+int StrNCaseCmp(char *a, char *b, int n)
+{
+ if (!a || !b)
+ return 0;
+
+ return strncasecmp(a,b,n);
+}
+
+
+/* END OF FILE */