123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593 |
- /* $Id$
- * MegaZeux
- *
- * Copyright (C) 1996 Greg Janson
- * Copyright (C) 1998 Matthew D. Williams - dbwilli@scsn.net
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- // Windowing code- Save/restore screen and draw windows and other elements,
- // also displays and runs dialog boxes.
- #include "helpsys.h"
- #include "hexchar.h"
- #include "timer.h"
- #include "sfx.h"
- #include "ezboard.h"
- #include "mod.h"
- #include "error.h"
- #include "boardmem.h"
- #include <stdio.h>
- #include "mouse.h"
- #include "beep.h"
- #include "intake.h"
- #include <stdlib.h>
- #include "cursor.h"
- #include "window.h"
- #include "getkey.h"
- #include "graphics.h"
- #include "string.h"
- extern "C" int _CType strcmp(const char *__s1, const char *__s2);
- #include <_null.h>
- #include "meminter.h"
- #include <dos.h>
- #include "const.h"
- #include "data.h"
- #include <dir.h>
- #include "helpsys.h"
- #define NUM_SAVSCR 2
- // Storage for NUM_SAVSCR saved screens- dynamically allocated at runtime
- // Another two saved screens use ega pages 2 and 3.
- char far *screen_storage[NUM_SAVSCR+2]={ NULL,NULL,
- (char far *)MK_FP(0xBA00,0),(char far *)MK_FP(0xBB00,0) };
- char curr_screen=0;//Current space for save_screen and restore_screen
- char far *vid_usage=NULL;//Mouse video usage array (for dialogs)
- // Reserve memory- returns 0 if ok, non-0 for error.
- char window_cpp_entry(void) {
- int t1=0;
- if((vid_usage=(char far *)farmalloc(2000))==NULL) return 1;
- for(;t1<NUM_SAVSCR;t1++) {
- screen_storage[t1]=(char far *)farmalloc(4000);
- if(screen_storage[t1]==NULL) break;
- }
- if(t1<NUM_SAVSCR) {//Allocation error
- if(t1>0) {
- for(t1--;t1>=0;t1--) {
- farfree(screen_storage[t1]);
- screen_storage[t1]=NULL;
- }
- }
- farfree(vid_usage);
- vid_usage=NULL;
- return 1;
- }
- return 0;
- }
- // Free up memory.
- void window_cpp_exit(void) {
- int t1=0;
- if(vid_usage!=NULL) farfree(vid_usage);
- for(;t1<NUM_SAVSCR;t1++) {
- if(screen_storage[t1]!=NULL) farfree(screen_storage[t1]);
- }
- }
- // The following functions do NOT check to see if memory is reserved, in
- // the interest of time, space, and simplicity. Make sure you have already
- // called window_cpp_init.
- // Saves current screen to buffer and increases buffer count. Returns
- // non-0 if the buffer for screens is already full. (IE 6 count)
- char save_screen(unsigned int segment) {
- if(curr_screen>=(NUM_SAVSCR+2)) {
- curr_screen=0;
- error("Windowing code bug",2,20,segment,0x1F01);
- }
- m_hide();
- mem_cpy(screen_storage[curr_screen++],(char far *)MK_FP(segment,0),4000);
- m_show();
- return 0;
- }
- // Restores top screen from buffer to screen and decreases buffer count.
- // Returns non-0 if there are no screens in the buffer.
- char restore_screen(unsigned int segment) {
- if(curr_screen==0)
- error("Windowing code bug",2,20,segment,0x1F02);
- m_hide();
- mem_cpy((char far *)MK_FP(segment,0),screen_storage[--curr_screen],4000);
- m_show();
- return 0;
- }
- // Draws an outlined and filled box from x1/y1 to x2/y2. Color is used to
- // fill box and for upper left lines. Dark_color is used for lower right
- // lines. Corner_color is used for the single chars in the upper right and
- // lower left corners. If Corner_color equals 0, these are auto calculated.
- // Returns non-0 for invalid parameters. Shadow (black spaces) is drawn and
- // clipped if specified. Operation on a size smaller than 3x3 is undefined.
- // This routine is highly unoptimized. Center is not filled if fill_center
- // is set to 0. (defaults to 1)
- char draw_window_box(int x1,int y1,int x2,int y2,unsigned int segment,
- unsigned char color,unsigned char dark_color,unsigned char corner_color,
- char shadow,char fill_center) {
- int t1,t2;
- //Validate parameters
- if((x1<0)||(y1<0)||(x1>79)||(y1>24)) return 1;
- if((x2<0)||(y2<0)||(x2>79)||(y2>24)) return 1;
- if(x2<x1) {
- t1=x1;
- x1=x2;
- x2=t1;
- }
- if(y2<y1) {
- t1=y1;
- y1=y2;
- y2=t1;
- }
- m_hide();
- //Fill center
- if(fill_center) {
- for(t1=x1+1;t1<x2;t1++) {
- for(t2=y1+1;t2<y2;t2++) {
- draw_char(' ',color,t1,t2,segment);
- }
- }
- }
- //Draw top and bottom edges
- for(t1=x1+1;t1<x2;t1++) {
- draw_char('Ä',color,t1,y1,segment);
- draw_char('Ä',dark_color,t1,y2,segment);
- }
- //Draw left and right edges
- for(t2=y1+1;t2<y2;t2++) {
- draw_char('³',color,x1,t2,segment);
- draw_char('³',dark_color,x2,t2,segment);
- }
- //Draw corners
- draw_char('Ú',color,x1,y1,segment);
- draw_char('Ù',dark_color,x2,y2,segment);
- if(corner_color) {
- draw_char('À',corner_color,x1,y2,segment);
- draw_char('¿',corner_color,x2,y1,segment);
- }
- else {
- draw_char('À',color,x1,y2,segment);
- draw_char('¿',dark_color,x2,y1,segment);
- }
- //Draw shadow if applicable
- if(shadow) {
- //Right edge
- if(x2<79) {
- for(t2=y1+1;t2<=y2;t2++) {
- draw_char(' ',0,x2+1,t2,segment);
- }
- }
- //Lower edge
- if(y2<24) {
- for(t1=x1+1;t1<=x2;t1++) {
- draw_char(' ',0,t1,y2+1,segment);
- }
- }
- //Lower right corner
- if((y2<24)&&(x2<79)) {
- draw_char(' ',0,x2+1,y2+1,segment);
- }
- }
- m_show();
- return 0;
- }
- // Strings for drawing different dialog box elements.
- // All parts are assumed 3 wide.
- #define check_on "[û]"
- #define check_off "[ ]"
- #define radio_on "()"
- #define radio_off "( )"
- #define color_blank ' '
- #define color_wild '?'
- #define color_dot 'þ'
- #define list_button " "
- #define num_buttons " "
- //Foreground colors that look nice for each background color
- char fg_per_bk[16]={ 15,15,15,15,15,15,15,0,15,15,0,0,15,15,0,0 };
- // For list/choice menus-
- #define arrow_char ''
- // List/choice menu colors- Box same as dialog, elements same as
- // inactive question, current element same as active question, pointer
- // same as text, title same as title.
- // Put up a box listing choices. Move pointer and enter to pick. choice
- // size is the size in bytes per choice in the array of choices. This size
- // includes null terminator and any junk padding. All work is done on
- // segment given, no page flipping. Choices are drawn using color_string.
- // On ESC, returns negative current choice, unless current choice is 0,
- // then returns -32767. Returns OUT_OF_WIN_MEM if out of screen storage space.
- // A progress column is displayed directly to the right of the list, using
- // the following characters. This is mainly used for mouse support.
- #define pc_top_arrow ''
- #define pc_bottom_arrow ''
- #define pc_filler '±'
- #define pc_dot 'þ'
- // Mouse support- Click on a choice to move there auto, click on progress
- // column arrows to move one line, click on progress meter itself to move
- // there percentage-wise. If you click on the current choice, it exits.
- // If you click on a choice to move there, the mouse cursor moves with it.
- int list_menu(char far *choices,char choice_size,char far *title,int
- current,int num_choices,unsigned int segment,char xpos) {
- int width=choice_size+6,t1;
- if(str_len(title)>choice_size) width=str_len(title)+6;
- //Save screen
- if(save_screen(segment)) return OUT_OF_WIN_MEM;
- //Display box
- m_hide();
- draw_window_box(xpos,2,xpos+width-1,22,segment,DI_MAIN,DI_DARK,DI_CORNER);
- //Add title
- write_string(title,xpos+3,2,DI_TITLE,segment);
- draw_char(' ',DI_TITLE,xpos+2,2,segment);
- draw_char(' ',DI_TITLE,xpos+3+str_len(title),2,segment);
- //Add pointer
- draw_char(arrow_char,DI_TEXT,xpos+2,12,segment);
- //Add meter arrows
- if(num_choices>1) {
- draw_char(pc_top_arrow,DI_PCARROW,xpos+4+choice_size,3,segment);
- draw_char(pc_bottom_arrow,DI_PCARROW,xpos+4+choice_size,21,segment);
- }
- do {
- //Fill over old menu
- draw_window_box(xpos+3,3,xpos+3+choice_size,21,segment,DI_DARK,DI_MAIN,
- DI_CORNER,0);
- //Draw current
- color_string(&(choices[choice_size*current]),xpos+4,12,DI_ACTIVE,
- segment);
- //Draw above current
- for(t1=1;t1<9;t1++) {
- if((current-t1)<0) break;
- color_string(&(choices[choice_size*(current-t1)]),xpos+4,12-t1,
- DI_NONACTIVE,segment);
- }
- //Draw below current
- for(t1=1;t1<9;t1++) {
- if((current+t1)>=num_choices) break;
- color_string(&(choices[choice_size*(current+t1)]),xpos+4,12+t1,
- DI_NONACTIVE,segment);
- }
- //Draw meter (xpos 9+choice_size, ypos 4 thru 20)
- if(num_choices>1) {
- for(t1=4;t1<21;t1++)
- draw_char(pc_filler,DI_PCFILLER,xpos+4+choice_size,t1,segment);
- //Add progress dot
- t1=(current*16)/(num_choices-1);
- draw_char(pc_dot,DI_PCDOT,xpos+4+choice_size,t1+4,segment);
- }
- //Get keypress
- m_show();
- t1=getkey();
- m_hide();
- //Act upon it
- switch(t1) {
- case MOUSE_EVENT:
- //Clicking on- List, column, arrow, or nothing?
- if((mouse_event.cx==xpos+4+choice_size)&&(mouse_event.cy>3)&&
- (mouse_event.cy<21)) {//Column
- t1=mouse_event.cy-4;
- current=(t1*(num_choices-1))/16;
- }
- else if((mouse_event.cy>3)&&(mouse_event.cy<21)&&
- (mouse_event.cx>xpos+3)&&(mouse_event.cx<xpos+3+choice_size)) {
- //List
- if(mouse_event.cy==12) goto enter;
- current+=(mouse_event.cy)-12;
- if(current<0) current=0;
- if(current>=num_choices) current=num_choices-1;
- //Move mouse with choices
- m_move(mouse_event.cx,12);
- }
- else if((mouse_event.cx==xpos+4+choice_size)&&
- (mouse_event.cy==3)) {//Top arrow
- if(current>0) current--;
- }
- else if((mouse_event.cx==xpos+4+choice_size)&&
- (mouse_event.cy==21)) {//Bottom arrow
- if(current<(num_choices-1)) current++;
- }
- else beep();//Nothing of importance was clicked on
- break;
- case 27:
- //ESC
- restore_screen(segment);
- m_show();
- if(current==0) return -32767;
- else return -current;
- case ' ':
- case 13:
- enter:
- //Selected
- restore_screen(segment);
- m_show();
- return current;
- case -72:
- case '8':
- //Up
- if(current>0) current--;
- break;
- case -80:
- case '2':
- //Down
- if(current<(num_choices-1)) current++;
- break;
- case -73:
- //Page Up
- current-=8;
- if(current<0) current=0;
- break;
- case -81:
- //Page Down
- current+=8;
- if(current>=num_choices) current=num_choices-1;
- break;
- case -71:
- //Home
- current=0;
- break;
- case -79:
- //End
- current=num_choices-1;
- break;
- default:
- //Invalid character
- beep();
- case 0:
- break;
- }
- //Loop
- } while(1);
- }
- // For char selection screen
- #define char_sel_arrows_0 ''
- #define char_sel_arrows_1 ''
- #define char_sel_arrows_2 ''
- #define char_sel_arrows_3 ''
- // Char selection screen colors- Window colors same as dialog, non-current
- // characters same as nonactive, current character same as active, arrows
- // along edges same as text, title same as title.
- // Put up a character selection box. Returns selected, or negative selected
- // for ESC, -256 for -0. Returns OUT_OF_WIN_MEM if out of window mem.
- // Display is 32 across, 8 down. All work done on given segment.
- // Mouse support- Click on a character to select it. If it is the current
- // character, it exits.
- int char_selection(unsigned char current,unsigned int segment) {
- int t1,t2,t3;
- //Save screen
- if(save_screen(segment)) return OUT_OF_WIN_MEM;
- if(context==72) set_context(98);
- else set_context(context);
- //Draw box
- m_hide();
- draw_window_box(20,5,57,16,segment,DI_MAIN,DI_DARK,DI_CORNER);
- //Add title
- write_string(" Select a character ",22,5,DI_TITLE,segment);
- //Draw character set
- for(t1=0;t1<32;t1++) {
- for(t2=0;t2<8;t2++) {
- draw_char(t1+t2*32,DI_NONACTIVE,t1+23,t2+7,segment);
- }
- }
- do {
- //Calculate x/y
- t1=(current&31)+23; t2=(current>>5)+7,
- //Highlight active character
- draw_char(current,DI_ACTIVE,t1,t2,segment);
- //Draw arrows
- draw_window_box(22,6,55,15,segment,DI_DARK,DI_MAIN,DI_CORNER,0,0);
- draw_char(char_sel_arrows_0,DI_TEXT,t1,15,segment);
- draw_char(char_sel_arrows_1,DI_TEXT,t1,6,segment);
- draw_char(char_sel_arrows_2,DI_TEXT,22,t2,segment);
- draw_char(char_sel_arrows_3,DI_TEXT,55,t2,segment);
- //Write number of character
- write_number(current,DI_MAIN,53,16,segment,3);
- //Get key
- m_show();
- t3=getkey();
- m_hide();
- //Erase marks
- draw_char(current,DI_NONACTIVE,t1,t2,segment);
- //Process key
- switch(t3) {
- case MOUSE_EVENT:
- //Within area?
- if((mouse_event.cx<23)||(mouse_event.cx>54)||
- (mouse_event.cy<7)||(mouse_event.cy>14)) {//Nope!
- beep();
- break;
- }
- //Yep!
- t1=(mouse_event.cx-23)+((mouse_event.cy-7)<<5);
- if(current==t1) goto enter;
- current=t1;
- break;
- case 27:
- //ESC
- pop_context();
- restore_screen(segment);
- m_show();
- if(current==0) return -256;
- else return -current;
- case ' ':
- case 13:
- enter:
- //Selected
- pop_context();
- restore_screen(segment);
- m_show();
- return current;
- case -72:
- case '8':
- //Up
- if(current>31) current-=32;
- break;
- case -80:
- case '2':
- //Down
- if(current<224) current+=32;
- break;
- case -75:
- case '4':
- //Left
- if(t1>23) current--;
- break;
- case -77:
- case '6':
- //Right
- if(t1<54) current++;
- break;
- case -71:
- //Home
- current=0;
- break;
- case -79:
- //End
- current=255;
- break;
- default:
- //If this is from 32 to 255, jump there.
- //Else beep.
- if(t3>31) current=t3;
- else beep();
- case 0:
- break;
- }
- //Loop
- } while(1);
- }
- // For color selection screen
- #define color_sel_char 'þ'
- #define color_sel_wild '?'
- // Color selection screen colors- see char selection screen.
- // Put up a color selection box. Returns selected, or negative selected
- // for ESC, -512 for -0. Returns OUT_OF_WIN_MEM if out of window mem.
- // Display is 16 across, 16 down. All work done on given segment. Current
- // uses bit 256 for the wild bit.
- // Mouse support- Click on a color to select it. If it is the current color,
- // it exits.
- int color_selection(int current,unsigned int segment,char allow_wild) {
- int t1,t2,t3;
- char currx,curry;
- //Save screen
- if(save_screen(segment)) return OUT_OF_WIN_MEM;
- if(context==72) set_context(98);
- else set_context(context);
- //Ensure allow_wild is 0 or 1
- allow_wild=(allow_wild!=0);
- //Calculate current x/y
- if((current&256)&&(allow_wild)) {
- //Wild
- current-=256;
- if(current<16) {
- currx=current;
- curry=16;
- }
- else {
- curry=current-16;
- currx=16;
- }
- }
- else if(current&256) {
- //Wild when not allowed to be
- current-=256;
- currx=current&15;
- curry=current>>4;
- }
- else {
- //Normal
- currx=current&15;
- curry=current>>4;
- }
- //Draw box
- m_hide();
- draw_window_box(12,2,33+allow_wild,21+allow_wild,segment,DI_MAIN,DI_DARK,
- DI_CORNER);
- //Add title
- write_string(" Select a color ",14,2,DI_TITLE,segment);
- do {
- //Draw outer edge
- draw_window_box(14,3,31+allow_wild,20+allow_wild,segment,DI_DARK,
- DI_MAIN,DI_CORNER,0,0);
- //Draw colors
- for(t1=0;t1<16+allow_wild;t1++) {
- for(t2=0;t2<16+allow_wild;t2++) {
- if(t1==16) {
- if(t2==16) draw_char(color_sel_wild,135,t1+15,t2+4,segment);
- else draw_char(color_sel_wild,fg_per_bk[t2]+t2*16,t1+15,t2+4,
- segment);
- }
- else if(t2==16) {
- if(t1==0) draw_char(color_sel_wild,128,t1+15,t2+4,segment);
- else draw_char(color_sel_wild,t1,t1+15,t2+4,segment);
- }
- else draw_char(color_sel_char,t1+t2*16,t1+15,t2+4,segment);
- }
- }
- //Add selection box
- draw_window_box(currx+14,curry+3,currx+16,curry+5,segment,DI_MAIN,DI_MAIN,
- DI_MAIN,0,0);
- //Write number of color
- if((allow_wild)&&((currx==16)||(curry==16))) {
- //Convert wild
- if(currx==16) {
- if(curry==16) t1=288;
- else t1=272+curry;
- }
- else t1=256+currx;
- }
- else t1=currx+curry*16;
- write_number(t1,DI_MAIN,28+allow_wild,21+allow_wild,segment,3);
- //Get key
- m_show();
- t3=getkey();
- m_hide();
- //Process
- switch(t3) {
- case MOUSE_EVENT:
- //Within area?
- if((mouse_event.cx<15)||(mouse_event.cx>30+allow_wild)||
- (mouse_event.cy<4)||(mouse_event.cy>19+allow_wild)) {//Nope!
- beep();
- break;
- }
- //Yep!
- t1=mouse_event.cx-15;
- t2=mouse_event.cy-4;
- if((currx==t1)&&(curry==t2)) {
- t3=13;
- goto enter;
- }
- currx=t1;
- curry=t2;
- break;
- case 27:
- //ESC
- case ' ':
- case 13:
- enter:
- pop_context();
- //Selected
- restore_screen(segment);
- m_show();
- if((allow_wild)&&((currx==16)||(curry==16))) {
- //Convert wild
- if(currx==16) {
- if(curry==16) current=288;
- else current=272+curry;
- }
- else current=256+currx;
- }
- else current=currx+curry*16;
- if(t3==27) {
- if(current==0) current=-512;
- else current=-current;
- }
- return current;
- case -72:
- case '8':
- //Up
- if(curry>0) curry--;
- break;
- case -80:
- case '2':
- //Down
- if(curry<(15+allow_wild)) curry++;
- break;
- case -75:
- case '4':
- //Left
- if(currx>0) currx--;
- break;
- case -77:
- case '6':
- //Right
- if(currx<(15+allow_wild)) currx++;
- break;
- case -71:
- //Home
- currx=curry=0;
- break;
- case -79:
- //End
- currx=curry=15+allow_wild;
- break;
- default:
- //Invalid character- beep.
- beep();
- case 0:
- break;
- }
- //Loop
- } while(1);
- }
- //Short function to display a color as a colored box
- void draw_color_box(unsigned char color,char q_bit,char x,char y,
- unsigned int segment) {
- m_hide();
- //If q_bit is set, there are unknowns
- if(q_bit) {
- if(color<16) {
- //Unknown background
- //Use black except for black fg, which uses grey
- if(color==0) color+=128;
- draw_char(color_wild,color,x,y,segment);
- draw_char(color_dot,color,x+1,y,segment);
- draw_char(color_wild,color,x+2,y,segment);
- }
- else if(color<32) {
- //Unkown foreground
- //Use foreground from array
- color-=16;
- color=(color<<4)+fg_per_bk[color];
- draw_char(color_wild,color,x,y,segment);
- draw_char(color_wild,color,x+1,y,segment);
- draw_char(color_wild,color,x+2,y,segment);
- }
- else {
- //Both unknown
- draw_char(color_wild,8,x,y,segment);
- draw_char(color_wild,135,x+1,y,segment);
- draw_char(color_wild,127,x+2,y,segment);
- }
- }
- else {
- draw_char(color_blank,color,x,y,segment);
- draw_char(color_dot,color,x+1,y,segment);
- draw_char(color_blank,color,x+2,y,segment);
- }
- m_show();
- }
- //Prototype- Internal function that displays a dialog box element.
- void display_element(unsigned int segment,char type,char x,char y,
- char far *str,int p1,int p2,void far *value,char active=0,
- char curr_check=0,char set_vid_usage=0);
- //The code that runs the dialog boxes... Returns OUT_OF_WIN_MEM if can't
- //save screen.
- //Mouse support- Click to move/select/choose.
- int run_dialog(dialog far *di,unsigned int segment,char reset_curr,
- char sfx_alt_t) {
- int t1,t2,key;
- long tlng;
- char mouse_held=0;
- //Current radio button or check box
- int curr_check=0;
- //Use these to save time and coding hassle
- int num_e=di->num_elements;
- int curr_e=di->curr_element;
- int x1=di->x1;
- int y1=di->y1;
- //X pos of title
- int titlex=x1+((di->x2-x1+1)>>1)-(str_len(di->title)>>1);
- //Save screen
- if(save_screen(segment)) return OUT_OF_WIN_MEM;
- if(context==72) set_context(98);
- else set_context(context);
- //Clear mouse usage array
- for(t1=0;t1<2000;t1++)
- vid_usage[t1]=-1;
- //Turn cursor off
- cursor_off();
- //Draw main box and title
- m_hide();
- draw_window_box(x1,y1,di->x2,di->y2,segment,DI_MAIN,DI_DARK,
- DI_CORNER);
- write_string(di->title,titlex,y1,DI_TITLE,segment);
- draw_char(' ',DI_TITLE,titlex-1,y1,segment);
- draw_char(' ',DI_TITLE,titlex+str_len(di->title),y1,segment);
- //Reset current
- if(reset_curr) di->curr_element=curr_e=0;
- //Initial draw of elements, as well as init of vid_usage
- for(t1=0;t1<num_e;t1++)
- display_element(segment,di->element_types[t1],x1+di->element_xs[t1],
- y1+di->element_ys[t1],di->element_strs[t1],di->element_param1s[t1],
- di->element_param2s[t1],di->element_storage[t1],t1==curr_e,0,t1+1);
- //Loop of selection
- do {
- //Check current...
- do {
- if(curr_e>=num_e) curr_e=0;
- t1=di->element_types[curr_e];
- if((t1==DE_BOX)||(t1==DE_TEXT)||(t1==DE_LINE))
- curr_e++;
- else break;
- } while(1);
- if(t1==DE_CHECK) {
- if(curr_check>=di->element_param1s[curr_e]) curr_check=0;
- }
- //Highlight current...
- display_element(segment,t1,x1+di->element_xs[curr_e],
- y1+di->element_ys[curr_e],di->element_strs[curr_e],
- di->element_param1s[curr_e],di->element_param2s[curr_e],
- di->element_storage[curr_e],1,curr_check);
- //Get key (through intake for DE_INPUT)
- m_show();
- if(mouse_held) {
- if(m_buttonstatus()&LEFTBDOWN) {
- if(mouse_held<3) {
- delay_time(100);
- if(!(m_buttonstatus()&LEFTBDOWN)) goto nombuttondn;
- mouse_held+=2;
- }
- if(mouse_held==3) {
- delay_time(5);
- key=-72;
- goto change_up;
- }
- else {
- delay_time(5);
- key=-80;
- goto change_down;
- }
- }
- nombuttondn:
- mouse_held=0;
- }
- if(t1==DE_INPUT) {
- key=intake((char far *)di->element_storage[curr_e],
- di->element_param1s[curr_e],x1+di->element_xs[curr_e]+
- str_len(di->element_strs[curr_e]),
- y1+di->element_ys[curr_e],segment,DI_INPUT,2,
- di->element_param2s[curr_e]);
- if(key==MOUSE_EVENT) acknowledge_mouse();
- }
- else key=getkey();
- //Process key (t1 still holds element type)
- switch(key) {
- case -20://Alt+T
- //Test sfx
- if(sfx_alt_t!=1) break;
- if((di->element_types[curr_e])!=DE_INPUT) break;
- //Play a sfx
- clear_sfx_queue();
- play_str((char far *)di->element_storage[curr_e]);
- break;
- case MOUSE_EVENT:
- //Is it over anything important?
- if(vid_usage[mouse_event.cx+mouse_event.cy*80]==-1) beep();//No.
- else {//Yes.
- //Get id number
- t2=vid_usage[mouse_event.cx+mouse_event.cy*80];
- if(t2!=curr_e) {
- //Unhighlight old element
- m_hide();
- display_element(segment,t1,x1+di->element_xs[curr_e],
- y1+di->element_ys[curr_e],di->element_strs[curr_e],
- di->element_param1s[curr_e],di->element_param2s[curr_e],
- di->element_storage[curr_e],0,curr_check);
- m_show();
- curr_e=t2;
- t2=-1;
- }
- //Get type of new one
- t1=di->element_types[curr_e];
- //Code for clicking on something... (t1!=-1 means it was
- //already current)
- switch(t1) {
- case DE_INPUT:
- //Nothing special
- break;
- case DE_CHECK:
- //Move curr_check and toggle
- curr_check=(mouse_event.cy-y1)-di->element_ys[curr_e];
- ((char far *)di->element_storage[curr_e])[curr_check]^=1;
- break;
- case DE_RADIO:
- //Move radio button
- ((char far *)di->element_storage[curr_e])[0]=
- (mouse_event.cy-y1)-di->element_ys[curr_e];
- break;
- case DE_COLOR:
- case DE_CHAR:
- case DE_LIST:
- case DE_BOARD:
- //Just like enter
- goto enter;
- case DE_BUTTON:
- //If it was already current, select. (enter)
- //Otherwise nothing happens.
- if(t2!=-1) goto enter;
- break;
- case DE_NUMBER:
- //Two types of numeral apply here.
- if((di->element_param1s[curr_e]==1)&&
- (di->element_param2s[curr_e]<10)) {//Number line
- //Select number IF on the number line itself
- t2=mouse_event.cx-x1;
- t2-=di->element_xs[curr_e];
- t2-=str_len(di->element_strs[curr_e]);
- if((t2<di->element_param2s[curr_e])&&(t2>=0))
- ((int far *)di->element_storage[curr_e])[0]=t2+1;
- break;
- }
- case DE_FIVE:
- //Numeric selector
- //Go to change_up w/-72 as key for up button
- //Go to change_down w/-80 as key for down button
- //Anything else is ignored
- //Set mouse_held to cycle.
- t2=mouse_event.cx-7-x1;
- t2-=di->element_xs[curr_e];
- t2-=str_len(di->element_strs[curr_e]);
- if((t2>=0)&&(t2<=2)) {
- key=-72;
- mouse_held=1;
- goto change_up;
- }
- else if((t2>=3)&&(t2<=5)) {
- key=-80;
- mouse_held=2;
- goto change_down;
- }
- break;
- }
- }
- break;
- case 9://Tab
- next_elem:
- //Unhighlight old element
- m_hide();
- display_element(segment,t1,x1+di->element_xs[curr_e],
- y1+di->element_ys[curr_e],di->element_strs[curr_e],
- di->element_param1s[curr_e],di->element_param2s[curr_e],
- di->element_storage[curr_e],0,curr_check);
- m_show();
- //Move to next element
- curr_e++;
- break;
- case -15://Shift + Tab
- prev_elem:
- //Unhighlight old element
- m_hide();
- display_element(segment,t1,x1+di->element_xs[curr_e],
- y1+di->element_ys[curr_e],di->element_strs[curr_e],
- di->element_param1s[curr_e],di->element_param2s[curr_e],
- di->element_storage[curr_e],0,curr_check);
- m_show();
- //Move to previous element, going past text/box/line
- do {
- curr_e--;
- if(curr_e<0) curr_e=num_e-1;
- t1=di->element_types[curr_e];
- if((t1==DE_BOX)||(t1==DE_TEXT)||(t1==DE_LINE)) continue;
- } while(0);
- break;
- case 32://Space
- case 13://Enter
- enter:
- //Activate button, choose from list/menu, or toggle check.
- switch(t1) {
- case DE_CHECK:
- ((char far *)di->element_storage[curr_e])[curr_check]^=1;
- break;
- case DE_COLOR:
- t2=color_selection(
- ((int far *)di->element_storage[curr_e])[0],segment,
- di->element_param1s[curr_e]);
- if(t2>=0) ((int far *)di->element_storage[curr_e])[0]=t2;
- break;
- case DE_CHAR:
- t2=char_selection(
- ((unsigned char far *)di->element_storage[curr_e])[0],
- segment);
- if(t2==0) t2=1;
- if((t2==255)&&(di->element_param1s[curr_e]==0)) t2=1;
- if(t2>=0)
- ((unsigned char far *)di->element_storage[curr_e])[0]=t2;
- break;
- case DE_BUTTON:
- //Restore screen, set current, and return answer
- pop_context();
- restore_screen(segment);
- di->curr_element=curr_e;
- return di->element_param1s[curr_e];
- case DE_BOARD:
- t2=choose_board(((int far *)di->element_storage[curr_e])[0],
- di->element_strs[curr_e],segment,
- di->element_param1s[curr_e]);
- if(t2>=0) ((int far *)di->element_storage[curr_e])[0]=t2;
- break;
- case DE_LIST:
- t2=di->element_param2s[curr_e];
- t2=list_menu(&(di->element_strs[curr_e][t2]),t2,
- di->element_strs[curr_e],
- ((int far *)di->element_storage[curr_e])[0],
- di->element_param1s[curr_e],segment);
- if(t2>=0) ((int far *)di->element_storage[curr_e])[0]=t2;
- break;
- default:
- //Same as a tab
- goto next_elem;
- }
- break;
- case -77://Right
- if((t1!=DE_NUMBER)&&(t1!=DE_FIVE)) goto change_down;
- case -72://Up
- case -152://Alt + Up
- case -141://Ctrl + Up
- case -73://PageUp
- change_up:
- //Change numeric, radio, or current check. Otherwise, move
- //to previous element.
- switch(t1) {
- case DE_RADIO:
- if(key==-73)
- ((char far *)di->element_storage[curr_e])[0]=0;
- else {
- if(((char far *)di->element_storage[curr_e])[0]>0)
- ((char far *)di->element_storage[curr_e])[0]--;
- }
- break;
- case DE_CHECK:
- if(key==-73) curr_check=0;
- else if(curr_check>0) curr_check--;
- break;
- case DE_NUMBER:
- case DE_FIVE:
- switch(key) {
- case -77://Right
- case -72://Up
- t2=1;
- break;
- case -152://Alt + Up
- case -141://Ctrl + Up
- t2=10;
- break;
- case -73://PageUp
- t2=100;
- break;
- }
- change_num:
- tlng=((int far *)di->element_storage[curr_e])[0];
- if((tlng+t2)<di->element_param1s[curr_e]) {
- ((int far *)di->element_storage[curr_e])[0]=
- di->element_param1s[curr_e];
- break;
- }
- if((tlng+t2)>di->element_param2s[curr_e]) {
- ((int far *)di->element_storage[curr_e])[0]=
- di->element_param2s[curr_e];
- break;
- }
- ((int far *)di->element_storage[curr_e])[0]+=t2;
- break;
- default:
- goto prev_elem;
- }
- break;
- case -71://Home
- //Change numeric, radio, or current check. Otherwise, move
- //to first element.
- switch(t1) {
- case DE_NUMBER:
- case DE_FIVE:
- ((int far *)di->element_storage[curr_e])[0]=
- di->element_param2s[curr_e];
- break;
- default:
- //Unhighlight old element
- m_hide();
- display_element(segment,t1,x1+di->element_xs[curr_e],
- y1+di->element_ys[curr_e],di->element_strs[curr_e],
- di->element_param1s[curr_e],di->element_param2s[curr_e],
- di->element_storage[curr_e],0,curr_check);
- m_show();
- //Jump to first
- curr_e=0;
- if(sfx_alt_t>1) curr_e=sfx_alt_t;
- else if(sfx_alt_t==1) curr_e=4;
- break;
- }
- break;
- case -75://Left
- if((t1!=DE_NUMBER)&&(t1!=DE_FIVE)) goto change_up;
- case -80://Down
- case -160://Alt + Down
- case -145://Ctrl + Down
- case -81://PageDown
- change_down:
- //Change numeric, radio, or current check. Otherwise, move
- //to next element.
- switch(t1) {
- case DE_RADIO:
- if(key==-81)
- ((char far *)di->element_storage[curr_e])[0]=
- di->element_param1s[curr_e]-1;
- else {
- if(((char far *)di->element_storage[curr_e])[0]<
- di->element_param1s[curr_e]-1)
- ((char far *)di->element_storage[curr_e])[0]++;
- }
- break;
- case DE_CHECK:
- if(key==-81) curr_check=di->element_param1s[curr_e]-1;
- else if(curr_check<di->element_param1s[curr_e]-1)
- curr_check++;
- break;
- case DE_NUMBER:
- case DE_FIVE:
- switch(key) {
- case -75://Left
- case -80://Down
- t2=-1;
- break;
- case -160://Alt + Down
- case -145://Ctrl + Down
- t2=-10;
- break;
- case -81://PageDown
- t2=-100;
- break;
- }
- goto change_num;
- default:
- goto next_elem;
- }
- break;
- case -79://End
- //Change numeric, radio, or current check. Otherwise, move
- //to last element.
- switch(t1) {
- case DE_NUMBER:
- case DE_FIVE:
- ((int far *)di->element_storage[curr_e])[0]=
- di->element_param1s[curr_e];
- break;
- default:
- //Unhighlight old element
- m_hide();
- display_element(segment,t1,x1+di->element_xs[curr_e],
- y1+di->element_ys[curr_e],di->element_strs[curr_e],
- di->element_param1s[curr_e],di->element_param2s[curr_e],
- di->element_storage[curr_e],0,curr_check);
- m_show();
- //Jump to end
- if(sfx_alt_t>0) curr_e=0;
- else {
- curr_e=num_e-1;
- //Work backwards past found text, box, or line
- do {
- curr_e--;
- t1=di->element_types[curr_e];
- if((t1==DE_BOX)||(t1==DE_TEXT)||(t1==DE_LINE)) continue;
- } while(0);
- }
- break;
- }
- break;
- case 27://ESC
- //Restore screen, set current, and return -1
- restore_screen(segment);
- di->curr_element=curr_e;
- pop_context();
- return -1;
- default:
- //Change character to key. Otherwise beep.
- if((t1==DE_CHAR)&&(key>31)&&(key<255))
- ((char far *)di->element_storage[curr_e])[0]=key;
- else beep();
- case 0:
- break;
- }
- m_hide();
- //Loop
- } while(1);
- }
- //Internal function to display an element, whether active or not.
- //Does NOT preserve mouse cursor.
- void display_element(unsigned int segment,char type,char x,char y,
- char far *str,int p1,int p2,void far *value,char active,char curr_check,
- char set_vid_usage) {
- //If set_vid_usage is non-0, set the vid_usage array appropriately.
- //set_vid_usage is equal to the element number plus 1.
- int t1,t2;
- char temp[7];
- //Color for elements (active vs. inactive)
- int color=DI_NONACTIVE;
- if(active) color=DI_ACTIVE;
- //Act according to type, and fill vid_usage array as well if flag set
- switch(type) {
- case DE_TEXT:
- color_string(str,x,y,DI_TEXT,segment);
- break;
- case DE_BOX:
- draw_window_box(x,y,x+p1-1,y+p2-1,segment,DI_DARK,DI_MAIN,DI_CORNER,
- 0,0);
- break;
- case DE_LINE:
- if(p2) {
- //Vertical
- for(t1=0;t1<p1;t1++)
- draw_char('³',DI_LINE,x,y+t1,segment);
- }
- else {
- //Horizontal
- fill_line(p1,x,y,(DI_LINE<<8)+196,segment);
- }
- break;
- case DE_INPUT:
- write_string(str,x,y,color,segment);
- write_string((char far *)value,x+str_len(str),y,DI_INPUT,segment);
- fill_line(p1-str_len((char far *)value)+1,
- x+str_len(str)+str_len((char far *)value),y,(DI_INPUT<<8)+32,
- segment);
- //Fill vid_usage
- if(set_vid_usage) {
- for(t1=0;t1<=p1+str_len(str);t1++)
- vid_usage[t1+x+y*80]=set_vid_usage-1;
- }
- break;
- case DE_CHECK:
- write_string(str,x+4,y,DI_NONACTIVE,segment);
- //Draw boxes
- for(t1=0;t1<p1;t1++) {
- if(((char far *)value)[t1]) write_string(check_on,x,y+t1,
- DI_NONACTIVE,segment);
- else write_string(check_off,x,y+t1,DI_NONACTIVE,segment);
- }
- //Highlight current
- if(active) {
- if(curr_check>=p1) curr_check=p1-1;
- color_line(p2+4,x,y+curr_check,DI_ACTIVE,segment);
- }
- //Fill vid_usage
- if(set_vid_usage) {
- for(t1=0;t1<p1;t1++)
- for(t2=0;t2<p2+4;t2++)
- vid_usage[t2+x+(t1+y)*80]=set_vid_usage-1;
- }
- break;
- case DE_RADIO:
- write_string(str,x+4,y,DI_NONACTIVE,segment);
- //Draw boxes
- for(t1=0;t1<p1;t1++) {
- if(t1==((char far *)value)[0]) write_string(radio_on,x,y+t1,
- DI_NONACTIVE,segment);
- else write_string(radio_off,x,y+t1,DI_NONACTIVE,segment);
- }
- //Highlight current
- if(active) {
- color_line(p2+4,x,y+((char far *)value)[0],DI_ACTIVE,segment);
- }
- //Fill vid_usage
- if(set_vid_usage) {
- for(t1=0;t1<p1;t1++)
- for(t2=0;t2<p2+4;t2++)
- vid_usage[t2+x+(t1+y)*80]=set_vid_usage-1;
- }
- break;
- case DE_COLOR:
- write_string(str,x,y,color,segment);
- t1=((int far *)value)[0];
- draw_color_box(t1&255,(t1&256)==256,x+str_len(str),y,segment);
- //Fill vid_usage
- if(set_vid_usage) {
- t2=str_len(str)+3;
- for(t1=0;t1<t2;t1++)
- vid_usage[t1+x+y*80]=set_vid_usage-1;
- }
- break;
- case DE_CHAR:
- write_string(str,x,y,color,segment);
- draw_char(((unsigned char far *)value)[0],DI_CHAR,x+str_len(str)+1,
- y,segment);
- draw_char(' ',DI_CHAR,x+str_len(str),y,segment);
- draw_char(' ',DI_CHAR,x+str_len(str)+2,y,segment);
- //Fill vid_usage
- if(set_vid_usage) {
- t2=str_len(str)+3;
- for(t1=0;t1<t2;t1++)
- vid_usage[t1+x+y*80]=set_vid_usage-1;
- }
- break;
- case DE_BUTTON:
- if(active) color=DI_ACTIVEBUTTON;
- else color=DI_BUTTON;
- write_string(str,x+1,y,color,segment);
- draw_char(' ',color,x,y,segment);
- draw_char(' ',color,x+str_len(str)+1,y,segment);
- //Fill vid_usage
- if(set_vid_usage) {
- t2=str_len(str)+2;
- for(t1=0;t1<t2;t1++)
- vid_usage[t1+x+y*80]=set_vid_usage-1;
- }
- break;
- case DE_NUMBER:
- case DE_FIVE:
- t1=1;
- if(type==DE_FIVE) t1=5;
- write_string(str,x,y,color,segment);
- x+=str_len(str);
- if((p1==1)&&(p2<10)&&(t1==1)) {
- //Number line
- for(t1=1;t1<=p2;t1++) {
- if(t1==((int far *)value)[0]) draw_char(t1+'0',DI_ACTIVE,
- x+t1-1,y,segment);
- else draw_char(t1+'0',DI_NONACTIVE,x+t1-1,y,segment);
- }
- //Fill vid_usage
- if(set_vid_usage) {
- t2=str_len(str);
- x-=t2;
- t2+=p2;
- for(t1=0;t1<t2;t1++)
- vid_usage[t1+x+y*80]=set_vid_usage-1;
- }
- }
- else {
- //Number
- itoa(((int far *)value)[0]*t1,temp,10);
- fill_line(7,x,y,(DI_NUMERIC<<8)+32,segment);
- write_string(temp,x+6-str_len(temp),y,DI_NUMERIC,segment);
- //Buttons
- write_string(num_buttons,x+7,y,DI_ARROWBUTTON,segment);
- //Fill vid_usage
- if(set_vid_usage) {
- t2=str_len(str);
- x-=t2;
- t2+=13;
- for(t1=0;t1<t2;t1++)
- vid_usage[t1+x+y*80]=set_vid_usage-1;
- }
- }
- break;
- case DE_LIST:
- write_string(str,x,y,color,segment);
- //Draw in current choice
- t1=p2*(((int far *)value)[0]+1);
- fill_line(p2+1,x,y+1,(DI_LIST<<8)+32,segment);
- color_string(&str[t1],x+1,y+1,DI_LIST,segment);
- //Draw button
- write_string(list_button,x+p2+1,y+1,DI_ARROWBUTTON,
- segment);
- //Fill vid_usage
- if(set_vid_usage) {
- for(t1=0;t1<=p2+3;t1++) {
- vid_usage[t1+x+y*80]=set_vid_usage-1;
- vid_usage[t1+x+(y+1)*80]=set_vid_usage-1;
- }
- }
- break;
- case DE_BOARD:
- write_string(str,x,y,color,segment);
- fill_line(BOARD_NAME_SIZE+1,x,y+1,(DI_LIST<<8)+32,segment);
- if(board_where[((int far *)value)[0]]==W_NOWHERE)
- color_string("(no board)",x+1,y+1,DI_LIST,segment);
- else if((((int far *)value)[0]==0)&&(p1))
- color_string("(none)",x+1,y+1,DI_LIST,segment);
- else color_string(&board_list[((int far *)value)[0]*BOARD_NAME_SIZE],
- x+1,y+1,DI_LIST,segment);
- //Draw button
- write_string(list_button,x+BOARD_NAME_SIZE+1,y+1,DI_ARROWBUTTON,
- segment);
- //Fill vid_usage
- if(set_vid_usage) {
- for(t1=0;t1<=BOARD_NAME_SIZE+3;t1++) {
- vid_usage[t1+x+y*80]=set_vid_usage-1;
- vid_usage[t1+x+(y+1)*80]=set_vid_usage-1;
- }
- }
- break;
- }
- //Done!
- }
- //Shell for list_menu()
- int choose_board(int current,char far *title,unsigned int segment,
- char board0_none) {
- int t1,t2=1,old_curr=curr_board,add_board=-1;
- char temp[BOARD_NAME_SIZE];
- //Go through- blank boards get a (no board) marker. t2 keeps track
- //of the number of boards.
- for(t1=0;t1<NUM_BOARDS;t1++) {
- if(board_where[t1]==W_NOWHERE)
- str_cpy(&board_list[t1*BOARD_NAME_SIZE],"(no board)");
- else t2=t1+1;
- }
- if((current<0)||(current>=t2)) current=0;
- //Add (new board) to bottom
- if(t2<NUM_BOARDS) {
- str_cpy(&board_list[t2*BOARD_NAME_SIZE],"(add board)");
- add_board=t2;
- t2++;
- }
- //Change top to (none) if needed
- if(board0_none) {
- str_cpy(temp,board_list);
- str_cpy(board_list,"(none)");
- }
- //Run the list_menu()
- current=list_menu(board_list,BOARD_NAME_SIZE,title,current,t2,segment);
- //Fix board list
- for(t1=0;t1<NUM_BOARDS;t1++)
- if(board_where[t1]==W_NOWHERE)
- board_list[t1*BOARD_NAME_SIZE]=0;
- if(board0_none) str_cpy(board_list,temp);
- //New board? (if select no board or add board)
- if((board_where[current]==W_NOWHERE)&&(current>=0)) {
- //Yepper! Save current board...
- t1=curr_board;
- //Find the first available...
- if(t2==add_board) {
- for(t2=0;t2<NUM_BOARDS;t2++)
- if(board_where[t2]==W_NOWHERE) break;
- }
- else t2=current;//Use the board selected
- //..get a name...
- m_hide();
- save_screen(segment);
- draw_window_box(16,12,64,14,segment,79,64,70);
- write_string("Name for new board:",18,13,78,segment);
- board_list[t2*BOARD_NAME_SIZE]=0;
- m_show();
- if(intake(&board_list[t2*BOARD_NAME_SIZE],BOARD_NAME_SIZE-1,38,13,
- segment,15,1,0)==27) {
- restore_screen(segment);
- return -1;
- }
- restore_screen(segment);
- //...make a new board and return to current board
- store_current();
- clear_current_and_select(t2);
- board_where[curr_board=t2]=W_CURRENT;
- board_sizes[t2]=0;
- swap_with(old_curr);
- return t2;
- }
- //Return board number
- return current;
- }
- char cd_types[2]={ DE_BUTTON,DE_BUTTON };
- char cd_xs[2]={ 15,37 };
- char cd_ys[2]={ 2,2 };
- char far *cd_strs[2]={ "OK","Cancel" };
- int cd_p1s[2]={ 0,1 };
- dialog c_di={ 10,9,69,13,NULL,2,cd_types,cd_xs,cd_ys,cd_strs,cd_p1s,NULL,
- NULL,0 };
- //Shell for run_dialog()
- char confirm(char far *str) {
- c_di.title=str;
- return run_dialog(&c_di,current_pg_seg);
- }
- char yn_types[2]={ DE_BUTTON,DE_BUTTON };
- char yn_xs[2]={ 15,37 };
- char yn_ys[2]={ 2,2 };
- char far *yn_strs[2]={ "Yes","No" };
- int yn_p1s[2]={ 0,1 };
- dialog yn_di={ 10,9,69,13,NULL,2,yn_types,yn_xs,yn_ys,yn_strs,yn_p1s,NULL,
- NULL,0 };
- //Shell for run_dialog()
- char ask_yes_no(char far *str) {
- yn_di.title=str;
- return run_dialog(&yn_di,current_pg_seg);
- }
- //Sort function for below use in qsort
- int cdecl sort_function( const void *a, const void *b) {
- //If one has a space first and the other doesn't, and the other
- //doesn't have a 'ú' first, the other comes first.
- if((((char *)a)[0]==32)&&(((char *)b)[0]!=32)&&
- (((char *)b)[0]!='ú')) return 1;
- if((((char *)b)[0]==32)&&(((char *)a)[0]!=32)&&
- (((char *)a)[0]!='ú')) return -1;
- return strcmp((char *)a,(char *)b);
- }
- //Shell for list_menu() (copies file chosen to ret and returns -1 for ESC)
- //dirs_okay of 1 means drive and directory changing is allowed.
- //Use NULL for wildcards to mean "all module files"
- #define NUM_MOD_TYPES 5
- #define MAX_FILES 1638
- char *mod_types[NUM_MOD_TYPES]={
- "*.MOD","*.NST","*.GDM","*.WOW","*.OCT" };
- char choose_file(char far *wildcards,char far *ret,char far *title,
- char dirs_okay) {
- char prevdir[PATHNAME_SIZE],prevdrive;
- long max_files;
- struct ffblk ff;
- int num=0,t1,t2,t3,curr_mod_type=-1;
- char use_titles=0;
- /* Room for filename AND title */
- char far *list;
- FILE *fp;
- prevdrive=getdisk();
- getcwd(prevdir,PATHNAME_SIZE);
- //Allocate array
- if(wildcards==NULL) free_sam_cache(1);//Okay in editor
- max_files=farcoreleft()/40;
- if(max_files>MAX_FILES) max_files=MAX_FILES;
- if(max_files>100) list=(char far *)farmalloc(40*max_files);
- else list=NULL;
- if(list==NULL) {/* Attempt to grab some memory */
- free_sam_cache(1);
- max_files=farcoreleft()/40;
- if(max_files>MAX_FILES) max_files=MAX_FILES;
- if(max_files>100) list=(char far *)farmalloc(40*max_files);
- else list=NULL;
- if(list==NULL) {/* Free up sample mem */
- free_up_board_memory();
- max_files=farcoreleft()/40;
- if(max_files>MAX_FILES) max_files=MAX_FILES;
- if(max_files>100) list=(char far *)farmalloc(40*max_files);
- else list=NULL;
- if(list==NULL) {/* Clear module.. :( */
- end_mod();
- max_files=farcoreleft()/40;
- if(max_files>MAX_FILES) max_files=MAX_FILES;
- if(max_files>100) list=(char far *)farmalloc(40*max_files);
- else list=NULL;
- if(list==NULL)//Out of mem
- error("Out of memory and/or disk space",2,4,
- current_pg_seg,0x203);
- }
- }
- }
- re_search:
- if(_fstricmp(wildcards,"*.MZX")==0) use_titles=1;
- if(wildcards==NULL) wildcards=mod_types[curr_mod_type=0];
- if(findfirst(wildcards,&ff,0)==-1) goto call_fc;
- do {
- str_cpy(&list[40*num]," ");
- str_cpy(&list[40*num],ff.ff_name);/* Save filename, update num */
- list[40*num+39]=str_len(ff.ff_name);// Save size for copying later
- if(use_titles==1) {
- fp=fopen(ff.ff_name,"rb");/* Open file to read name */
- if(fp!=NULL) {
- list[(40*num)+str_len(ff.ff_name)]=' ';
- fread(&list[(40*num)+14],1,24,fp);/* Read title ! */
- list[(40*num)+38]=0;
- fclose(fp);
- }
- }
- num++;
- if(findnext(&ff)==-1) break;
- if(num==max_files) goto file_lim;/* Limit on files because of memory... :( */
- } while(1);
- call_fc:
- //Next mod type?
- if((curr_mod_type>-1)&&(curr_mod_type<14)) {
- wildcards=mod_types[++curr_mod_type];
- goto re_search;
- }
- //Find directorys too, if wanted
- if(dirs_okay) {
- if(findfirst("*.*",&ff,FA_DIREC)==-1) goto call_fc2;
- do {
- if(!(ff.ff_attrib&FA_DIREC)) goto not_direc;
- if(!_fstricmp(ff.ff_name,".")) goto not_direc;
- str_cpy(&list[40*num]," [subdirectory]");
- str_cpy(&list[40*num+1],ff.ff_name);/* Save filename, update num */
- list[40*num+1+str_len(ff.ff_name)]=' ';
- list[40*num+39]=str_len(ff.ff_name);
- num++;
- not_direc:
- if(findnext(&ff)==-1) break;
- if(num==max_files) goto file_lim;/* Limit on files because of memory... :( */
- } while(1);
- call_fc2:
- //Add drives if room
- t1=setdisk(t3=getdisk());
- //t1=# drives
- for(t2=0;t2<t1;t2++) {
- if(num==max_files) goto file_lim;
- setdisk(t2);
- if(getdisk()!=t2) continue;
- str_cpy(&list[40*num],"úA: [drive]");
- list[40*num+1]+=t2;
- num++;
- }
- setdisk(t3);
- }
- file_lim:
- if(num==0) {
- farfree(list);
- error("No files found to select from",0,24,current_pg_seg,0x1701);
- return -1;//No files to choose from!
- }
- //Sort
- //(directorys automatically at bottom because of starting dot)
- qsort((void *)list,num,40,sort_function);
- num=list_menu(list,40,title,0,num,current_pg_seg,15);
- if(num<0) {
- setdisk(prevdrive);
- chdir(prevdir);
- farfree(list);
- return -1;/* ESC or exit. */
- }
- //Directory or drive
- if(list[40*num]=='ú') {
- setdisk(list[40*num+1]-'A');
- num=0;
- use_titles=0;
- goto re_search;
- }
- else if(list[40*num]==' ') {
- list[40*num+1+list[40*num+39]]=0;
- chdir(&list[40*num+1]);
- num=0;
- use_titles=0;
- goto re_search;
- }
- mem_cpy(ret,&list[40*num],list[40*num+39]);
- ret[list[40*num+39]]=0;
- farfree(list);
- return 0;
- }
|