summaryrefslogtreecommitdiff
path: root/djgpp
diff options
context:
space:
mode:
Diffstat (limited to 'djgpp')
-rw-r--r--djgpp/file.c129
-rw-r--r--djgpp/gfx.c535
-rw-r--r--djgpp/install31
-rw-r--r--djgpp/install.c119
-rw-r--r--djgpp/main.c34
-rw-r--r--djgpp/mem.c325
-rw-r--r--djgpp/platgui.c1975
-rw-r--r--djgpp/runcmd.c61
-rw-r--r--djgpp/vstring.c42
9 files changed, 3251 insertions, 0 deletions
diff --git a/djgpp/file.c b/djgpp/file.c
new file mode 100644
index 0000000..583a9df
--- /dev/null
+++ b/djgpp/file.c
@@ -0,0 +1,129 @@
+/*
+
+ 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);
+
+ if (s[strlen(s)-1]!='\\')
+ strcat(s,"\\");
+
+ 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)
+{
+ FILE *fp;
+
+ if ((fp=fopen(path,"rb")))
+ {
+ fclose(fp);
+ return(TRUE);
+ }
+ else
+ return(FALSE);
+}
+
+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..8d8e849
--- /dev/null
+++ b/djgpp/gfx.c
@@ -0,0 +1,535 @@
+/*
+
+ 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_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..f40c226
--- /dev/null
+++ b/djgpp/mem.c
@@ -0,0 +1,325 @@
+/*
+
+ 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 "debug.h"
+
+/* Comment out this define to switch off memory stats in the working version
+*/
+#define MEMSTAT
+
+#ifdef MEMSTAT
+
+typedef struct
+ {
+ Long size;
+ Long realloc;
+ Long free;
+ char file[32];
+ Long line;
+ } MemInfo;
+
+static Long grab_call=0;
+static Long regrab_call=0;
+static Long release_call=0;
+static Long copy_call=0;
+static Long strdup_call=0;
+static Long total=0;
+static Long total_grab=0;
+static Long total_regrab=0;
+static Long total_copy=0;
+static Long total_free=0;
+static Long total_strdup=0;
+
+static void status(void)
+{
+ Debug(("Total calls to Grab() : %lu\n",grab_call));
+ Debug(("Total calls to Regrab() : %lu\n",regrab_call));
+ Debug(("Total calls to Release() : %lu\n",release_call));
+ Debug(("Total calls to Copy() : %lu\n",copy_call));
+ Debug(("Total calls to Strdup() : %lu\n",strdup_call));
+ Debug(("Total bytes allocated : %lu\n",total));
+ Debug(("Total bytes allocated over life : %lu\n",total_grab));
+ Debug(("Total bytes regrabbed over life : %lu\n",total_regrab));
+ Debug(("Total bytes copied over life : %lu\n",total_copy));
+ Debug(("Total bytes released over life : %lu\n",total_free));
+ Debug(("Total bytes strdupped over life : %lu\n\n",total_strdup));
+}
+
+#endif
+
+
+#ifdef MEMSTAT
+
+void *FGrab(char *fn, int line, int len)
+{
+ char *ptr;
+ MemInfo *mi;
+
+ if (len==0)
+ len=1;
+
+ if (!(ptr=malloc(len+sizeof(MemInfo))))
+ {
+ status();
+ GFX_exit(EXIT_FAILURE,"Memory allocation failed!\n"
+ "%s:%d Grab(%d)\n",fn,line,len);
+ }
+
+ mi=(MemInfo *)ptr;
+ mi->size=len;
+ mi->realloc=0;
+ mi->free=0;
+ ptr+=sizeof(MemInfo);
+
+ grab_call++;
+ total_grab+=len;
+ total+=len;
+
+ memset(ptr,0,len);
+
+ return(ptr);
+}
+
+#else
+
+void *FGrab(char *fn, int line, int len)
+{
+ void *ptr;
+
+ if (len==0)
+ len=1;
+
+ if (!(ptr=malloc(len)))
+ GFX_exit(EXIT_FAILURE,"Memory allocation failed!\n"
+ "%s:%d Grab(%d)\n",fn,line,len);
+
+ memset(ptr,0,len);
+
+ return(ptr);
+}
+
+#endif
+
+
+#ifdef MEMSTAT
+
+void *FReGrab(char *fn, int line, void *ptr, int len)
+{
+ Long old;
+ MemInfo *mi;
+ char *p;
+
+ if (len==0)
+ len=1;
+
+ p=ptr;
+
+ if (p)
+ p-=sizeof(MemInfo);
+
+ if (!(p=realloc(p,len+sizeof(MemInfo))))
+ {
+ status();
+ GFX_exit(EXIT_FAILURE,"Memory allocation failed!\n"
+ "%s:%d ReGrab(%d)\n",fn,line,len);
+ }
+
+ regrab_call++;
+ total_regrab+=len;
+
+ mi=(MemInfo *)p;
+ old=mi->size;
+ mi->size=len;
+ mi->realloc++;
+ total-=old;
+ total+=len;
+
+ p+=sizeof(MemInfo);
+
+ return(p);
+}
+
+#else
+
+void *FReGrab(char *fn, int line, void *ptr, int len)
+{
+ if (len==0)
+ len=1;
+
+ if (!(ptr=realloc(ptr,len)))
+ GFX_exit(EXIT_FAILURE,"Memory allocation failed!\n"
+ "%s:%d ReGrab(%d)\n",fn,line,len);
+
+ return(ptr);
+}
+
+#endif
+
+
+#ifdef MEMSTAT
+
+void FRelease(char *fn, int line, void *p)
+{
+ char *cp;
+ MemInfo *mi;
+
+ if (!p)
+ return;
+
+ cp=p;
+ cp-=sizeof(MemInfo);
+ mi=(MemInfo *)cp;
+
+ if (mi->free==1)
+ Debug(("%p already freed!!! Current=%s:%d, previous=%s:%d\n",
+ p,fn,line,mi->file,mi->line));
+
+ release_call++;
+
+ total_free+=mi->size;
+ total-=mi->size;
+
+ strcpy(mi->file,fn);
+ mi->line=line;
+ mi->free=1;
+
+ free(cp);
+}
+
+#else
+
+void FRelease(char *fn, int line, void *p)
+{
+ free(p);
+}
+
+#endif
+
+
+#ifdef MEMSTAT
+
+void *FCopy(char *fn, int line, void *p,int len)
+{
+ char s[128];
+ void *ptr;
+
+ strcpy(s,fn);
+ strcat(s," [FCopy()]");
+
+ if (len==0)
+ ptr=FGrab(s,line,1);
+ else
+ ptr=FGrab(s,line,len);
+
+ copy_call++;
+ total_copy+=len;
+
+ if (len)
+ memcpy(ptr,p,len);
+
+ return(ptr);
+}
+
+#else
+
+void *FCopy(char *fn, int line, void *p,int len)
+{
+ void *ptr;
+
+ if (len==0)
+ ptr=malloc(1);
+ else
+ ptr=malloc(len);
+
+ if (!ptr)
+ GFX_exit(EXIT_FAILURE,"Memory allocation failed!\n"
+ "%s:%d Copy(%p,%d)\n",fn,line,p,len);
+
+ if (len)
+ memcpy(ptr,p,len);
+
+ return(ptr);
+}
+
+#endif
+
+
+#ifdef MEMSTAT
+
+char *FStrdup(char *fn, int line, char *p)
+{
+ char s[128];
+ char *ptr;
+
+ strcpy(s,fn);
+ strcat(s," [Strdup()]");
+
+ if (p)
+ {
+ ptr=FGrab(s,line,strlen(p)+1);
+
+ strdup_call++;
+ total_strdup+=strlen(p)+1;
+
+ strcpy(ptr,p);
+ return(ptr);
+ }
+ else
+ return(NULL);
+}
+
+#else
+
+char *FStrdup(char *fn, int line, char *p)
+{
+ char *ptr;
+
+ if (p)
+ {
+ if (!(ptr=malloc(strlen(p)+1)))
+ GFX_exit(EXIT_FAILURE,"Memory allocation failed!\n"
+ "%s:%d Stdup(%s)\n",fn,line,p);
+
+ strcpy(ptr,p);
+ return(ptr);
+ }
+ else
+ return(NULL);
+}
+
+#endif
+
+
+/* END OF FILE */
diff --git a/djgpp/platgui.c b/djgpp/platgui.c
new file mode 100644
index 0000000..887ab9c
--- /dev/null
+++ b/djgpp/platgui.c
@@ -0,0 +1,1975 @@
+/*
+
+ 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 "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
+
+/* ---------------------------------------- VARS
+*/
+static int SCRW,SCRH;
+
+/* Global picklist data and the picklist dialog
+*/
+#define PL_BORDER 0
+#define PL_TITLE 1
+#define PL_PICKLIST 2
+#define PL_END 3
+
+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_END 5
+
+static DIALOG img_picklist[IPL_END+1];
+static int img_pick_no;
+static PLAT_IMG_PICKLIST
+ *img_pick_data;
+
+
+typedef struct
+ {
+ int x;
+ int y;
+ int w;
+ int h;
+ } BoundBox;
+
+
+/* ---------------------------------------- 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)
+ {
+ d_inv_3d_box(MSG_DRAW,&img_picklist[IPL_IMG_BORDER],0);
+
+ if ((bm=d->dp))
+ draw_rle_sprite(screen,bm,d->x,d->y);
+ else
+ gui_textout(screen,"No Image",
+ d->x+d->w/2,d->y+d->h/2,ACOL(BLACK),TRUE);
+ }
+
+ 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_inv_3d_box(MSG_DRAW,&img_picklist[IPL_IMG_BORDER],0);
+ 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 = (d->flags & D_DISABLED) ? gui_mg_color : d->fg;
+ 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)
+ DrawTick(x+SMALL_BEVEL,d->y+SMALL_BEVEL,
+ d->h-SMALL_BEVEL*2,d->h-SMALL_BEVEL*2);
+
+ return D_O_K;
+ }
+
+ return d_button_proc(msg, d, 0);
+}
+
+
+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_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-GFX_fh()/2,d->fg,TRUE);
+
+ break;
+
+ default:
+ return(d_button_proc(msg,d,c));
+ break;
+ }
+
+ 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.
+
+ Shawn Hargreaves can be contacted at:
+
+ http://www.talula.demon.co.uk/allegro/
+ shawn@talula.demon.co.uk
+
+ 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_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)
+{
+ 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-GFX_fh()/2,fg);
+}
+
+
+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;
+
+ 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_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;
+ 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;
+
+ 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_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;
+ 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;
+
+ 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;
+}
+
+
+int GUI_yesno(char *question)
+{
+ extern void GFX_FORCE_REDRAW(void);
+ DIALOG *d;
+ int ml;
+ int h;
+ int ret;
+ int x,y;
+
+ d=Grab(sizeof(DIALOG)*5);
+
+ h=(GFX_fh()+10)*3;
+ ml=text_length(font,question)+GFX_fw()*2;
+
+ 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;
+
+ /* Question
+ */
+ d[1].proc=d_ctext_proc;
+ d[1].x=SCRW/2;
+ d[1].w=ml-20;
+ d[1].y=y+BEVEL+GFX_fh();
+ d[1].h=10;
+ d[1].fg=ACOL(GUI_TEXT);
+ d[1].bg=ACOL(GUI_MID);
+ d[1].key=0;
+ d[1].flags=0;
+ d[1].d1=d[1].d2=0;
+ d[1].dp=question;
+ d[1].dp2=d[1].dp3=NULL;
+
+ /* YES
+ */
+ d[2].proc=my_d_button_proc;
+ d[2].x=x+10;
+ d[2].w=(ml/2)-20;
+ d[2].h=GFX_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='Y';
+ d[2].flags=D_EXIT;
+ d[2].d1=d[2].d2=0;
+ d[2].dp="&Yes";
+ d[2].dp2=d[2].dp3=NULL;
+
+ /* NO
+ */
+ 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='N';
+ d[3].flags=D_EXIT;
+ d[3].d1=d[3].d2=0;
+ d[3].dp="&No";
+ d[3].dp2=d[3].dp3=NULL;
+
+ d[4].proc=NULL;
+
+ GFX_bounce();
+
+ if(do_dialog(d,-1)==2)
+ ret=TRUE;
+ else
+ ret=FALSE;
+
+ GFX_FORCE_REDRAW();
+ Release(d);
+
+ return(ret);
+}
+
+
+int GUI_menu(char *title, int x, int y, PLAT_MENU menu[],int defval)
+{
+ int lx,ly;
+ int no;
+ int f;
+ int h;
+ int w;
+ BITMAP *under;
+ int cur;
+ int cx;
+ int by;
+ int done;
+ int quit;
+ BoundBox *box;
+
+ /* Calc dimensions
+ */
+ no=0;
+ w=text_length(font,title);
+
+ while(menu[no].text)
+ {
+ w=MAX(w,text_length(font,menu[no].text));
+ no++;
+ }
+
+ h=BEVEL*2+GFX_fh()+4;
+
+ for(f=0;f<no;f++)
+ h+=GFX_fh()+SMALL_BEVEL*2+2;
+
+ h+=2;
+ w+=BEVEL+SMALL_BEVEL+4;
+
+ box=Grab(sizeof(BoundBox)*no);
+
+ if ((x+w)>SCRW)
+ x=SCRW-w;
+
+ if ((y+h)>SCRH)
+ y=SCRH-h;
+
+ if ((x<0)||(y<0))
+ {
+ alert("Cannot display menu:",title,"Menu is bigger than display!",
+ "OK",NULL,0,0);
+
+ return(defval);
+ }
+
+ cx=x+w/2;
+
+ cur=0;
+
+ /* Save screen contents
+ */
+ show_mouse(NULL);
+
+ if (!(under=create_bitmap(w+1,h+1)))
+ GFX_exit(EXIT_FAILURE,"No more memory to create MENU save under\n");
+
+ blit(screen,under,x,y,0,0,w+1,h+1);
+
+ /* Draw menu border and title
+ */
+ Rect3D(x,y,w,h,FALSE,BEVEL);
+ text_mode(-1);
+ textout_centre(screen,font,title,cx,y+BEVEL*2,ACOL(GUI_TEXTBOLD));
+
+ /* Draw menu items
+ */
+ by=y+BEVEL*2+GFX_fh()+4;
+
+ for(f=0;f<no;f++)
+ {
+ box[f].x=x+BEVEL;
+ box[f].y=by;
+ box[f].w=w-BEVEL*2;
+ box[f].h=GFX_fh()+SMALL_BEVEL*2+2;
+ by+=box[f].h;
+
+ DrawMenuItem(&box[f],menu[f].text,(f==cur));
+ }
+
+ show_mouse(screen);
+ GFX_bounce();
+
+ /* Main loop
+ */
+ quit=FALSE;
+ done=FALSE;
+ lx=mouse_x;
+ ly=mouse_y;
+
+ while((!done)&&(!quit))
+ {
+ if (mouse_b)
+ {
+ int new;
+
+ new=MouseInBox(box,no);
+
+ if (new==-1)
+ {
+ quit=TRUE;
+
+ while(mouse_b);
+ }
+ else
+ {
+ done=TRUE;
+ cur=new;
+ }
+ }
+ else
+ if (keypressed())
+ switch(readkey()>>8)
+ {
+ case KEY_ESC:
+ quit=TRUE;
+ break;
+
+ case KEY_ENTER:
+ done=TRUE;
+ break;
+
+ case KEY_DOWN:
+ show_mouse(NULL);
+ DrawMenuItem(&box[cur],menu[cur].text,FALSE);
+
+ cur=(cur+1)%no;
+
+ DrawMenuItem(&box[cur],menu[cur].text,TRUE);
+ show_mouse(screen);
+ break;
+
+ case KEY_UP:
+ show_mouse(NULL);
+ DrawMenuItem(&box[cur],menu[cur].text,FALSE);
+
+ if (cur)
+ cur--;
+ else
+ cur=no-1;
+
+ DrawMenuItem(&box[cur],menu[cur].text,TRUE);
+ show_mouse(screen);
+ break;
+ }
+ else
+ if ((lx!=mouse_x)||(ly!=mouse_y))
+ {
+ int new;
+
+ lx=mouse_x;
+ ly=mouse_y;
+
+ new=MouseInBox(box,no);
+
+ if ((new!=-1)&&(new!=cur))
+ {
+ show_mouse(NULL);
+ DrawMenuItem(&box[cur],menu[cur].text,FALSE);
+ cur=new;
+ DrawMenuItem(&box[cur],menu[cur].text,TRUE);
+ show_mouse(screen);
+ }
+ }
+ }
+
+ show_mouse(NULL);
+ blit(under,screen,0,0,x,y,w+1,h+1);
+ show_mouse(screen);
+ destroy_bitmap(under);
+ Release(box);
+
+ if (!quit)
+ no=menu[cur].client_index;
+ else
+ no=defval;
+
+ return(no);
+}
+
+
+char *GUI_fsel(char *title, char *default_path, char *filter)
+{
+ char path[PATH_MAX+1];
+
+ if ((filter)&&(*filter=='.'))
+ filter++;
+
+ strcpy(path,default_path);
+
+ GFX_bounce();
+ if (my_file_select(title,path,filter))
+ return(Strdup(path));
+
+ return(NULL);
+}
+
+
+int GUI_picklist(char *title,char *opt[])
+{
+ extern void GFX_FORCE_REDRAW(void);
+ int ml;
+ int ret;
+
+ pick_no=0;
+
+ 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();
+
+ if (ret==-1)
+ return(-1);
+
+ return(picklist[IPL_PICKLIST].d1);
+}
+
+
+int GUI_client_picklist(char *title,PLAT_PICKLIST opt[],int defval)
+{
+ extern void GFX_FORCE_REDRAW(void);
+ int ml;
+ int ret;
+ char **c_opt;
+ int f;
+
+ pick_no=0;
+
+ 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);
+
+ if (ret==-1)
+ return(defval);
+
+ return(opt[picklist[IPL_PICKLIST].d1].client_index);
+}
+
+
+int GUI_image_picklist(char *title,PLAT_IMG_PICKLIST opt[],int defval)
+{
+ extern void GFX_FORCE_REDRAW(void);
+ 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);
+
+ return(opt[img_picklist[IPL_PICKLIST].d1].client_index);
+}
+
+
+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=(GFX_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+=GFX_fh()*4;
+ ml+=GFX_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_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,char *opt[],int *val)
+{
+ extern void GFX_FORCE_REDRAW(void);
+ int no;
+ DIALOG *d;
+ int ml,l;
+ int h;
+ int f;
+ int ret;
+ int x,y;
+
+ no=0;
+ while(opt[no])
+ no++;
+
+ d=Grab(sizeof(DIALOG)*(no+6));
+
+ h=(GFX_fh()+5)*no;
+ ml=text_length(font,"CANCEL CANCEL");
+
+ for(f=0;f<no;f++)
+ if ((l=text_length(font,opt[f]))>ml)
+ ml=l;
+
+ h+=GFX_fh()*4;
+ ml+=GFX_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_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 ((*val)&(1<<f))
+ d[4+f].flags=D_SELECTED;
+ else
+ d[4+f].flags=0;
+
+ d[4+f].d1=f;
+ d[4+f].d2=0;
+ d[4+f].dp=opt[f];
+ d[4+f].dp2=d[4+f].dp3=NULL;
+ }
+
+ d[4+no].proc=NULL;
+
+ GFX_bounce();
+ if(do_dialog(d,-1)==2)
+ {
+ *val=0;
+
+ for(f=0;f<no;f++)
+ if (d[4+f].flags&D_SELECTED)
+ *val|=(1<<f);
+
+ ret=TRUE;
+ }
+ else
+ ret=FALSE;
+
+ GFX_FORCE_REDRAW();
+ Release(d);
+
+ return(ret);
+}
+
+
+int GUI_dialog(char *title, int no, PLAT_DIALOG pd[])
+{
+ extern void GFX_FORCE_REDRAW(void);
+ DIALOG *d;
+ int ml,l;
+ int h;
+ int f;
+ int ret;
+ int x,y;
+ char *p;
+ int tmp;
+ double d_tmp;
+
+ d=Grab(sizeof(DIALOG)*(no*3+6));
+
+ h=(GFX_fh()+10)*no;
+ ml=0;
+
+ for(f=0;f<no;f++)
+ if ((pd[f].text)&&((l=text_length(font,pd[f].text))>ml))
+ ml=l;
+
+ ml+=text_length(font," ")*(DIALOG_STRLEN+3);
+
+ h+=GFX_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_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=GFX_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_text_proc;
+ d[4+(f*3)].x=x+10;
+ 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_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=x+ml-text_length(font," ")*DIALOG_STRLEN-9-BEVEL;
+ 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=x+ml-text_length(font," ")*DIALOG_STRLEN-9;
+ 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*4)].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;
+ }
+ }
+
+ ret=TRUE;
+ }
+ else
+ ret=FALSE;
+
+ GFX_FORCE_REDRAW();
+ Release(d);
+
+ return(ret);
+}
+
+
+/* END OF FILE */
diff --git a/djgpp/runcmd.c b/djgpp/runcmd.c
new file mode 100644
index 0000000..66d56ba
--- /dev/null
+++ b/djgpp/runcmd.c
@@ -0,0 +1,61 @@
+/*
+
+ 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 <unistd.h>
+#include <string.h>
+#include <stdio.h>
+
+int RunCommand(char *argv[], char *path)
+{
+ char cmd[PATH_MAX*2];
+ int ret;
+ int f;
+
+ tmpnam(path);
+
+ f=0;
+ cmd[0]=0;
+ while(argv[f])
+ {
+ strcat(cmd,argv[f]);
+ strcat(cmd," ");
+ f++;
+ }
+
+ strcat(cmd,">> ");
+ strcat(cmd,path);
+
+ ret=system(cmd);
+
+ /* 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..2cc5ee4
--- /dev/null
+++ b/djgpp/vstring.c
@@ -0,0 +1,42 @@
+/*
+
+ 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)
+{
+ return(strcasecmp(a,b));
+}
+
+int StrNCaseCmp(char *a, char *b, int n)
+{
+ return(strncasecmp(a,b,n));
+}
+
+
+/* END OF FILE */