diff options
Diffstat (limited to 'djgpp')
-rw-r--r-- | djgpp/file.c | 118 | ||||
-rw-r--r-- | djgpp/gfx.c | 559 | ||||
-rw-r--r-- | djgpp/install | 31 | ||||
-rw-r--r-- | djgpp/install.c | 119 | ||||
-rw-r--r-- | djgpp/main.c | 34 | ||||
-rw-r--r-- | djgpp/mem.c | 262 | ||||
-rw-r--r-- | djgpp/platgui.c | 4235 | ||||
-rw-r--r-- | djgpp/runcmd.c | 143 | ||||
-rw-r--r-- | djgpp/vstring.c | 48 |
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 */ |