/* 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 #include #include #include #include #include #include #include #include #include #include #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)&&(fox) { x--; y--; } for(f=0;fx, 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; id2+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;(fx) 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)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)d2)) { while((sd->posd2)) { (*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)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)d2)) { while((sd->posd2)) { (*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;sxt[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;sylines) { for(sx=0;sxcol+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->xcol) te->col--; } do { if (te->x) te->x--; else ctrl=FALSE; if (te->xcol) 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->xy].len)&& (isspace(p[te->y].p[te->x]))) { te->x++; if ((te->x-TE_WIDTH)>te->col) te->col++; } do { if (te->xy].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->ytop) 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->ytop) 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;fy].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;flines;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;fy].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->xcol) 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;flines;f++) p[f]=p[f+1]; if (--te->ytop) 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;fd2;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;fd2;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; csize; 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; isize; i++) if (flist->name[i]) free(flist->name[i]); } if (!flist) { errno = ENOMEM; return D_CLOSE; } flist->size = 0; for (i=0; isize; 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; isize; 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=box[f].x)&&(mouse_x=box[f].y)&&(mouse_ySCRW) 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>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;fml) 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;fml) 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;ftl)) tl=l; pl=DIALOG_STRLEN*FW; for(f=0;fpl) 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;fd[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