/* Miscellaneous C routines used only in DOS Fractint. */ #include #ifndef XFRACT #include #include #endif #include #include #include #include /* see Fractint.c for a description of the "include" hierarchy */ #include "port.h" #include "prototyp.h" #include "fractype.h" #include "helpdefs.h" #include "drivers.h" static int menu_checkkey(int curkey,int choice); /* uncomment following for production version */ /* #define PRODUCTION */ int g_release = 2099; /* this has 2 implied decimals; increment it every synch */ int g_patch_level = 7; /* patchlevel for DOS version */ #ifdef XFRACT int xrelease=304; #endif /* int stopmsg(flags,message) displays message and waits for a key: message should be a max of 9 lines with \n's separating them; no leading or trailing \n's in message; no line longer than 76 chars for best appearance; flag options: &1 if already in text display mode, stackscreen is not called and message is displayed at (12,0) instead of (4,0) &2 if continue/cancel indication is to be returned; when not set, "Any key to continue..." is displayed when set, "Escape to cancel, any other key to continue..." -1 is returned for cancel, 0 for continue &4 set to suppress buzzer &8 for Fractint for Windows & parser - use a fixed pitch font &16 for info only message (green box instead of red in DOS vsn) */ int stopmsg (int flags, char *msg) { int ret,toprow,color,savelookatmouse; static unsigned char batchmode = 0; if (debugflag != 0 || initbatch >= 1) { static FILE *fp = NULL; if (fp==NULL && initbatch == 0) fp=dir_fopen(workdir,"stopmsg.txt","w"); else fp=dir_fopen(workdir,"stopmsg.txt","a"); if (fp != NULL) fprintf(fp,"%s\n",msg); fclose(fp); } if (first_init) { /* & cmdfiles hasn't finished 1st try */ #ifdef XFRACT driver_set_for_text(); driver_buzzer(BUZZER_ERROR); driver_put_string(0,0,15, "*** Error during startup:"); driver_put_string(2,0,15,msg); driver_move_cursor(8,0); #if !defined(WIN32) sleep(1); #endif close_drivers(); exit(1); #else printf("%s\n",msg); dopause(1); /* pause deferred until after cmdfiles */ return(0); #endif } if (initbatch >= 1 || batchmode) { /* in batch mode */ initbatch = 4; /* used to set errorlevel */ batchmode = 1; /* fixes *second* stopmsg in batch mode bug */ return (-1); } ret = 0; savelookatmouse = lookatmouse; lookatmouse = -13; if ((flags & STOPMSG_NO_STACK)) blankrows(toprow=12,10,7); else { driver_stack_screen(); toprow = 4; driver_move_cursor(4,0); } g_text_cbase = 2; /* left margin is 2 */ driver_put_string(toprow,0,7,msg); if (flags & STOPMSG_CANCEL) driver_put_string(g_text_row+2,0,7, "Escape to cancel, any other key to continue..."); else driver_put_string(g_text_row+2,0,7, "Any key to continue..."); g_text_cbase = 0; /* back to full line */ color = (flags & STOPMSG_INFO_ONLY) ? C_STOP_INFO : C_STOP_ERR; driver_set_attr(toprow,0,color,(g_text_row+1-toprow)*80); driver_hide_text_cursor(); /* cursor off */ if ((flags & STOPMSG_NO_BUZZER) == 0) driver_buzzer((flags & STOPMSG_INFO_ONLY) ? 0 : 2); while (driver_key_pressed()) /* flush any keyahead */ driver_get_key(); if (debugflag != 324) if (getakeynohelp() == FIK_ESC) ret = -1; if ((flags & STOPMSG_NO_STACK)) blankrows(toprow,10,7); else driver_unstack_screen(); lookatmouse = savelookatmouse; return ret; } static U16 temptextsave = 0; static int textxdots,textydots; /* texttempmsg(msg) displays a text message of up to 40 characters, waits for a key press, restores the prior display, and returns (without eating the key). It works in almost any video mode - does nothing in some very odd cases (HCGA hi-res with old bios), or when there isn't 10k of temp mem free. */ int texttempmsg(char *msgparm) { if (showtempmsg(msgparm)) { return -1; } driver_wait_key_pressed(0); /* wait for a keystroke but don't eat it */ cleartempmsg(); return 0; } void freetempmsg() { if (temptextsave != 0) { MemoryRelease(temptextsave); } temptextsave = 0; } int showtempmsg(char *msgparm) { static long size = 0; char msg[41]; BYTE buffer[640]; BYTE *fontptr = NULL; int i; int xrepeat = 0; int yrepeat = 0; int save_sxoffs, save_syoffs; strncpy(msg, msgparm, 40); msg[40] = 0; /* ensure max message len of 40 chars */ if (driver_diskp()) /* disk video, screen in text mode, easy */ { dvid_status(0, msg); return 0; } if (first_init) /* & cmdfiles hasn't finished 1st try */ { printf("%s\n", msg); return 0; } xrepeat = (sxdots >= 640) ? 2 : 1; yrepeat = (sydots >= 300) ? 2 : 1; textxdots = (int) strlen(msg) * xrepeat * 8; textydots = yrepeat * 8; /* worst case needs 10k */ if (temptextsave != 0) { if (size != (long) textxdots * (long) textydots) { freetempmsg(); } } size = (long) textxdots * (long) textydots; save_sxoffs = sxoffs; save_syoffs = syoffs; if (g_video_scroll) { sxoffs = g_video_start_x; syoffs = g_video_start_y; } else { sxoffs = syoffs = 0; } if (temptextsave == 0) /* only save screen first time called */ { /* TODO: MemoryAlloc, MoveToMemory */ temptextsave = MemoryAlloc((U16)textxdots, (long)textydots, MEMORY); if (temptextsave == 0) { return -1; /* sorry, message not displayed */ } for (i = 0; i < textydots; ++i) { get_line(i, 0, textxdots-1, buffer); MoveToMemory(buffer, (U16)textxdots, 1L, (long)i, temptextsave); } } find_special_colors(); /* get g_color_dark & g_color_medium set */ driver_display_string(0, 0, g_color_medium, g_color_dark, msg); sxoffs = save_sxoffs; syoffs = save_syoffs; return 0; } void cleartempmsg() { BYTE buffer[640]; int i; int save_sxoffs, save_syoffs; if (driver_diskp()) /* disk video, easy */ { dvid_status(0, ""); } else if (temptextsave != 0) { save_sxoffs = sxoffs; save_syoffs = syoffs; if (g_video_scroll) { sxoffs = g_video_start_x; syoffs = g_video_start_y; } else { sxoffs = syoffs = 0; } for (i = 0; i < textydots; ++i) { MoveFromMemory(buffer, (U16)textxdots, 1L, (long)i, temptextsave); put_line(i, 0, textxdots-1, buffer); } if (using_jiim == 0) /* jiim frees memory with freetempmsg() */ { MemoryRelease(temptextsave); temptextsave = 0; } sxoffs = save_sxoffs; syoffs = save_syoffs; } } void blankrows(int row,int rows,int attr) { char buf[81]; memset(buf,' ',80); buf[80] = 0; while (--rows >= 0) driver_put_string(row++,0,attr,buf); } void helptitle() { char msg[MSGLEN],buf[MSGLEN]; driver_set_clear(); /* clear the screen */ #ifdef XFRACT sprintf(msg,"XFRACTINT Version %d.%02d (FRACTINT Version %d.%02d)", xrelease/100,xrelease%100, g_release/100,g_release%100); #else *msg=0; #endif sprintf(buf,"FRACTINT Version %d.%01d",g_release/100,(g_release%100)/10); strcat(msg,buf); if (g_release%10) { sprintf(buf,"%01d",g_release%10); strcat(msg,buf); } if (g_patch_level) { sprintf(buf,".%d",g_patch_level); strcat(msg,buf); } putstringcenter(0,0,80,C_TITLE,msg); /* uncomment next for production executable: */ #if defined(PRODUCTION) || defined(XFRACT) return; /*NOTREACHED*/ #else if (debugflag == 3002) return; #define DEVELOPMENT #ifdef DEVELOPMENT driver_put_string(0, 2, C_TITLE_DEV, "Development Version"); #else driver_put_string(0, 3, C_TITLE_DEV, "Customized Version"); #endif driver_put_string(0, 55, C_TITLE_DEV, "Not for Public Release"); #endif } void footer_msg(int *i, int options, char *speedstring) { putstringcenter((*i)++, 0, 80, C_PROMPT_BKGRD, (speedstring) ? "Use the cursor keys or type a value to make a selection" : "Use the cursor keys to highlight your selection"); putstringcenter(*(i++), 0, 80, C_PROMPT_BKGRD, (options & CHOICE_MENU) ? "Press ENTER for highlighted choice, or "FK_F1" for help" : ((options & CHOICE_HELP) ? "Press ENTER for highlighted choice, ESCAPE to back out, or F1 for help" : "Press ENTER for highlighted choice, or ESCAPE to back out")); } int putstringcenter(int row, int col, int width, int attr, char *msg) { char buf[81]; int i,j,k; i = 0; #ifdef XFRACT if (width>=80) width=79; /* Some systems choke in column 80 */ #endif while (msg[i]) ++i; /* strlen for a */ if (i == 0) return(-1); if (i >= width) i = width - 1; /* sanity check */ j = (width - i) / 2; j -= (width + 10 - i) / 20; /* when wide a bit left of center looks better */ memset(buf,' ',width); buf[width] = 0; i = 0; k = j; while (msg[i]) buf[k++] = msg[i++]; /* strcpy for a */ driver_put_string(row,col,attr,buf); return j; } /* ------------------------------------------------------------------------ */ char speed_prompt[]="Speed key string"; /* For file list purposes only, it's a directory name if first char is a dot or last char is a slash */ static int isadirname(char *name) { if (*name == '.' || endswithslash(name)) return 1; else return 0; } void show_speedstring(int speedrow, char *speedstring, int (*speedprompt)(int,int,int,char *,int)) { int speed_match = 0; int i,j; char buf[81]; memset(buf,' ',80); buf[80] = 0; driver_put_string(speedrow,0,C_PROMPT_BKGRD,buf); if (*speedstring) { /* got a speedstring on the go */ driver_put_string(speedrow,15,C_CHOICE_SP_INSTR," "); if (speedprompt) j = speedprompt(speedrow,16,C_CHOICE_SP_INSTR,speedstring,speed_match); else { driver_put_string(speedrow,16,C_CHOICE_SP_INSTR,speed_prompt); j = sizeof(speed_prompt)-1; } strcpy(buf,speedstring); i = (int) strlen(buf); while (i < 30) buf[i++] = ' '; buf[i] = 0; driver_put_string(speedrow,16+j,C_CHOICE_SP_INSTR," "); driver_put_string(speedrow,17+j,C_CHOICE_SP_KEYIN,buf); driver_move_cursor(speedrow,17+j+(int) strlen(speedstring)); } else driver_hide_text_cursor(); } void process_speedstring(char *speedstring, char **choices, /* array of choice strings */ int curkey, int *pcurrent, int numchoices, int is_unsorted) { int i, comp_result; i = (int) strlen(speedstring); if (curkey == 8 && i > 0) /* backspace */ speedstring[--i] = 0; if (33 <= curkey && curkey <= 126 && i < 30) { #ifndef XFRACT curkey = tolower(curkey); #endif speedstring[i] = (char)curkey; speedstring[++i] = 0; } if (i > 0) { /* locate matching type */ *pcurrent = 0; while (*pcurrent < numchoices && (comp_result = strncasecmp(speedstring,choices[*pcurrent],i))!=0) { if (comp_result < 0 && !is_unsorted) { *pcurrent -= *pcurrent ? 1 : 0; break; } else ++*pcurrent; } if (*pcurrent >= numchoices) /* bumped end of list */ *pcurrent = numchoices - 1; /*if the list is unsorted, and the entry found is not the exact entry, then go looking for the exact entry. */ else if (is_unsorted && choices[*pcurrent][i]) { int temp = *pcurrent; while (++temp < numchoices) { if (!choices[temp][i] && !strncasecmp(speedstring, choices[temp], i)) { *pcurrent = temp; break; } } } } } int fullscreen_choice( int options, /* &2 use menu coloring scheme */ /* &4 include F1 for help in instructions */ /* &8 add caller's instr after normal set */ /* &16 menu items up one line */ char *hdg, /* heading info, \n delimited */ char *hdg2, /* column heading or NULL */ char *instr, /* instructions, \n delimited, or NULL */ int numchoices, /* How many choices in list */ char **choices, /* array of choice strings */ int *attributes, /* &3: 0 normal color, 1,3 highlight */ /* &256 marks a dummy entry */ int boxwidth, /* box width, 0 for calc (in items) */ int boxdepth, /* box depth, 0 for calc, 99 for max */ int colwidth, /* data width of a column, 0 for calc */ int current, /* start with this item */ void (*formatitem)(int,char*),/* routine to display an item or NULL */ char *speedstring, /* returned speed key value, or NULL */ int (*speedprompt)(int,int,int,char *,int),/* routine to display prompt or NULL */ int (*checkkey)(int,int) /* routine to check keystroke or NULL */ ) /* return is: n>=0 for choice n selected, -1 for escape k for checkkey routine return value k (if not 0 nor -1) speedstring[0] != 0 on return if string is present */ { int titlelines, titlewidth; int reqdrows; int topleftrow, topleftcol; int topleftchoice; int speedrow = 0; /* speed key prompt */ int boxitems; /* boxwidth*boxdepth */ int curkey, increment, rev_increment = 0; int redisplay; int i, j, k = 0; char *charptr; char buf[81]; char curitem[81]; char *itemptr; int ret, savelookatmouse; int scrunch; /* scrunch up a line */ scrunch = (options & CHOICE_CRUNCH) ? 1 : 0; savelookatmouse = lookatmouse; lookatmouse = 0; ret = -1; /* preset current to passed string */ if (speedstring && (i = (int) strlen(speedstring)) > 0) { current = 0; if (options & CHOICE_NOT_SORTED) { while (current < numchoices && (k = strncasecmp(speedstring, choices[current], i)) != 0) { ++current; } if (k != 0) { current = 0; } } else { while (current < numchoices && (k = strncasecmp(speedstring,choices[current],i)) > 0) { ++current; } if (k < 0 && current > 0) /* oops - overshot */ { --current; } } if (current >= numchoices) /* bumped end of list */ { current = numchoices - 1; } } for (;;) { if (current >= numchoices) /* no real choice in the list? */ { goto fs_choice_end; } if ((attributes[current] & 256) == 0) { break; } ++current; /* scan for a real choice */ } titlelines = titlewidth = 0; if (hdg) { charptr = hdg; /* count title lines, find widest */ i = 0; titlelines = 1; while (*charptr) { if (*(charptr++) == '\n') { ++titlelines; i = -1; } if (++i > titlewidth) { titlewidth = i; } } } if (colwidth == 0) /* find widest column */ { for (i = 0; i < numchoices; ++i) { int len; if ((len = (int) strlen(choices[i])) > colwidth) { colwidth = len; } } } /* title(1), blank(1), hdg(n), blank(1), body(n), blank(1), instr(?) */ reqdrows = 3 - scrunch; /* calc rows available */ if (hdg) { reqdrows += titlelines + 1; } if (instr) /* count instructions lines */ { charptr = instr; ++reqdrows; while (*charptr) { if (*(charptr++) == '\n') { ++reqdrows; } } if ((options & CHOICE_INSTRUCTIONS)) /* show std instr too */ { reqdrows += 2; } } else { reqdrows += 2; /* standard instructions */ } if (speedstring) { ++reqdrows; /* a row for speedkey prompt */ } if (boxdepth > (i = 25 - reqdrows)) /* limit the depth to max */ { boxdepth = i; } if (boxwidth == 0) /* pick box width and depth */ { if (numchoices <= i - 2) /* single column is 1st choice if we can */ { boxdepth = numchoices; boxwidth = 1; } else { /* sort-of-wide is 2nd choice */ boxwidth = 60 / (colwidth + 1); if (boxwidth == 0 || (boxdepth = (numchoices + boxwidth - 1)/boxwidth) > i - 2) { boxwidth = 80 / (colwidth + 1); /* last gasp, full width */ if ((boxdepth = (numchoices + boxwidth - 1)/boxwidth) > i) { boxdepth = i; } } } } #if 0 if ((i = 77 / boxwidth - colwidth) > 3) /* spaces to add @ left each choice */ { i = 3; } if (i == 0) { i = 1; } #else i = (80 / boxwidth - colwidth) / 2 - 1; if (i == 0) /* to allow wider prompts */ { i = 1; } if (i < 0) { i = 0; } if (i > 3) { i = 3; } #endif j = boxwidth * (colwidth += i) + i; /* overall width of box */ if (j < titlewidth+2) { j = titlewidth + 2; } if (j > 80) { j = 80; } if (j <= 70 && boxwidth == 2) /* special case makes menus nicer */ { ++j; ++colwidth; } k = (80 - j) / 2; /* center the box */ k -= (90 - j) / 20; topleftcol = k + i; /* column of topleft choice */ i = (25 - reqdrows - boxdepth) / 2; i -= i / 4; /* higher is better if lots extra */ topleftrow = 3 + titlelines + i; /* row of topleft choice */ /* now set up the overall display */ helptitle(); /* clear, display title line */ driver_set_attr(1, 0, C_PROMPT_BKGRD, 24*80); /* init rest to background */ for (i = topleftrow - 1 - titlelines; i < topleftrow + boxdepth + 1; ++i) { driver_set_attr(i, k, C_PROMPT_LO, j); /* draw empty box */ } if (hdg) { g_text_cbase = (80 - titlewidth) / 2; /* set left margin for putstring */ g_text_cbase -= (90 - titlewidth) / 20; /* put heading into box */ driver_put_string(topleftrow - titlelines - 1, 0, C_PROMPT_HI, hdg); g_text_cbase = 0; } if (hdg2) /* display 2nd heading */ { driver_put_string(topleftrow - 1, topleftcol, C_PROMPT_MED, hdg2); } i = topleftrow + boxdepth + 1; if (instr == NULL || (options & CHOICE_INSTRUCTIONS)) /* display default instructions */ { if (i < 20) { ++i; } if (speedstring) { speedrow = i; *speedstring = 0; if (++i < 22) { ++i; } } i -= scrunch; footer_msg(&i, options, speedstring); } if (instr) /* display caller's instructions */ { charptr = instr; j = -1; while ((buf[++j] = *(charptr++)) != 0) { if (buf[j] == '\n') { buf[j] = 0; putstringcenter(i++, 0, 80, C_PROMPT_BKGRD, buf); j = -1; } } putstringcenter(i, 0, 80, C_PROMPT_BKGRD, buf); } boxitems = boxwidth * boxdepth; topleftchoice = 0; /* pick topleft for init display */ while (current - topleftchoice >= boxitems || (current - topleftchoice > boxitems/2 && topleftchoice + boxitems < numchoices)) { topleftchoice += boxwidth; } redisplay = 1; topleftrow -= scrunch; for (;;) /* main loop */ { if (redisplay) /* display the current choices */ { memset(buf, ' ', 80); buf[boxwidth*colwidth] = 0; for (i = (hdg2) ? 0 : -1; i <= boxdepth; ++i) /* blank the box */ { driver_put_string(topleftrow + i, topleftcol, C_PROMPT_LO, buf); } for (i = 0; i + topleftchoice < numchoices && i < boxitems; ++i) { /* display the choices */ k = attributes[j = i + topleftchoice] & 3; if (k == 1) { k = C_PROMPT_LO; } else if (k == 3) { k = C_PROMPT_HI; } else { k = C_PROMPT_MED; } if (formatitem) { (*formatitem)(j, buf); charptr=buf; } else { charptr = choices[j]; } driver_put_string(topleftrow + i/boxwidth, topleftcol + (i % boxwidth)*colwidth, k, charptr); } /*** ... format differs for summary/detail, whups, force box width to ... be 72 when detail toggle available? (2 grey margin each ... side, 1 blue margin each side) ***/ if (topleftchoice > 0 && hdg2 == NULL) { driver_put_string(topleftrow - 1, topleftcol, C_PROMPT_LO, "(more)"); } if (topleftchoice + boxitems < numchoices) { driver_put_string(topleftrow + boxdepth, topleftcol, C_PROMPT_LO, "(more)"); } redisplay = 0; } i = current - topleftchoice; /* highlight the current choice */ if (formatitem) { (*formatitem)(current, curitem); itemptr = curitem; } else { itemptr = choices[current]; } driver_put_string(topleftrow + i/boxwidth, topleftcol + (i % boxwidth)*colwidth, C_CHOICE_CURRENT, itemptr); if (speedstring) /* show speedstring if any */ { show_speedstring(speedrow, speedstring, speedprompt); } else { driver_hide_text_cursor(); } driver_wait_key_pressed(0); /* enables help */ curkey = driver_get_key(); #ifdef XFRACT if (curkey == FIK_F10) { curkey = ')'; } if (curkey == FIK_F9) { curkey = '('; } if (curkey == FIK_F8) { curkey = '*'; } #endif i = current - topleftchoice; /* unhighlight current choice */ k = attributes[current] & 3; if (k == 1) { k = C_PROMPT_LO; } else if (k == 3) { k = C_PROMPT_HI; } else { k = C_PROMPT_MED; } driver_put_string(topleftrow + i/boxwidth, topleftcol + (i % boxwidth)*colwidth, k, itemptr); increment = 0; switch (curkey) { /* deal with input key */ case FIK_ENTER: case FIK_ENTER_2: ret = current; goto fs_choice_end; case FIK_ESC: goto fs_choice_end; case FIK_DOWN_ARROW: rev_increment = 0 - (increment = boxwidth); break; case FIK_CTL_DOWN_ARROW: rev_increment = 0 - (increment = boxwidth); { int newcurrent = current; while ((newcurrent += boxwidth) != current) { if (newcurrent >= numchoices) { newcurrent = (newcurrent % boxwidth) - boxwidth; } else if (!isadirname(choices[newcurrent])) { if (current != newcurrent) { current = newcurrent - boxwidth; } break; /* breaks the while loop */ } } } break; case FIK_UP_ARROW: increment = 0 - (rev_increment = boxwidth); break; case FIK_CTL_UP_ARROW: increment = 0 - (rev_increment = boxwidth); { int newcurrent = current; while ((newcurrent-=boxwidth) != current) { if (newcurrent < 0) { newcurrent = (numchoices - current) % boxwidth; newcurrent = numchoices + (newcurrent ? boxwidth - newcurrent: 0); } else if (!isadirname(choices[newcurrent])) { if (current != newcurrent) { current = newcurrent + boxwidth; } break; /* breaks the while loop */ } } } break; case FIK_RIGHT_ARROW: increment = 1; rev_increment = -1; break; case FIK_CTL_RIGHT_ARROW: /* move to next file; if at last file, go to first file */ increment = 1; rev_increment = -1; { int newcurrent = current; while (++newcurrent != current) { if (newcurrent >= numchoices) { newcurrent = -1; } else if (!isadirname(choices[newcurrent])) { if (current != newcurrent) { current = newcurrent - 1; } break; /* breaks the while loop */ } } } break; case FIK_LEFT_ARROW: increment = -1; rev_increment = 1; break; case FIK_CTL_LEFT_ARROW: /* move to previous file; if at first file, go to last file */ increment = -1; rev_increment = 1; { int newcurrent = current; while (--newcurrent != current) { if (newcurrent < 0) { newcurrent = numchoices; } else if (!isadirname(choices[newcurrent])) { if (current != newcurrent) { current = newcurrent + 1; } break; /* breaks the while loop */ } } } break; case FIK_PAGE_UP: if (numchoices > boxitems) { topleftchoice -= boxitems; increment = -boxitems; rev_increment = boxwidth; redisplay = 1; } break; case FIK_PAGE_DOWN: if (numchoices > boxitems) { topleftchoice += boxitems; increment = boxitems; rev_increment = -boxwidth; redisplay = 1; } break; case FIK_HOME: current = -1; increment = rev_increment = 1; break; case FIK_CTL_HOME: current = -1; increment = rev_increment = 1; { int newcurrent; for (newcurrent = 0; newcurrent < numchoices; ++newcurrent) { if (!isadirname(choices[newcurrent])) { current = newcurrent - 1; break; /* breaks the for loop */ } } } break; case FIK_END: current = numchoices; increment = rev_increment = -1; break; case FIK_CTL_END: current = numchoices; increment = rev_increment = -1; { int newcurrent; for (newcurrent = numchoices - 1; newcurrent >= 0; --newcurrent) { if (!isadirname(choices[newcurrent])) { current = newcurrent + 1; break; /* breaks the for loop */ } } } break; default: if (checkkey) { if ((ret = (*checkkey)(curkey, current)) < -1 || ret > 0) { goto fs_choice_end; } if (ret == -1) { redisplay = -1; } } ret = -1; if (speedstring) { process_speedstring(speedstring, choices, curkey, ¤t, numchoices, options & CHOICE_NOT_SORTED); } break; } if (increment) /* apply cursor movement */ { current += increment; if (speedstring) /* zap speedstring */ { speedstring[0] = 0; } } for (;;) { /* adjust to a non-comment choice */ if (current < 0 || current >= numchoices) { increment = rev_increment; } else if ((attributes[current] & 256) == 0) { break; } current += increment; } if (topleftchoice > numchoices - boxitems) { topleftchoice = ((numchoices + boxwidth - 1)/boxwidth)*boxwidth - boxitems; } if (topleftchoice < 0) { topleftchoice = 0; } while (current < topleftchoice) { topleftchoice -= boxwidth; redisplay = 1; } while (current >= topleftchoice + boxitems) { topleftchoice += boxwidth; redisplay = 1; } } fs_choice_end: lookatmouse = savelookatmouse; return ret; } #ifndef XFRACT /* case independent version of strncmp */ int strncasecmp(char *s,char *t,int ct) { for (; (tolower(*s) == tolower(*t)) && --ct ; s++,t++) if (*s == '\0') return(0); return(tolower(*s) - tolower(*t)); } #endif static int menutype; #define MENU_HDG 3 #define MENU_ITEM 1 int main_menu(int fullmenu) { char *choices[44]; /* 2 columns * 22 rows */ int attributes[44]; int choicekey[44]; int i; int nextleft, nextright; int oldtabmode; int showjuliatoggle; oldtabmode = tabmode; top: menutype = fullmenu; tabmode = 0; showjuliatoggle = 0; for (i = 0; i < 44; ++i) { attributes[i] = 256; choices[i] = ""; choicekey[i] = -1; } nextleft = -2; nextright = -1; if (fullmenu) { nextleft += 2; choices[nextleft] = " CURRENT IMAGE "; attributes[nextleft] = 256+MENU_HDG; nextleft += 2; choicekey[nextleft] = 13; /* enter */ attributes[nextleft] = MENU_ITEM; choices[nextleft] = (calc_status == CALCSTAT_RESUMABLE) ? "continue calculation " : "return to image "; nextleft += 2; choicekey[nextleft] = 9; /* tab */ attributes[nextleft] = MENU_ITEM; choices[nextleft] = "info about image "; nextleft += 2; choicekey[nextleft] = 'o'; attributes[nextleft] = MENU_ITEM; choices[nextleft] = "orbits window "; if (!(fractype==JULIA || fractype==JULIAFP || fractype==INVERSEJULIA)) { nextleft += 2; } } nextleft += 2; choices[nextleft] = " NEW IMAGE "; attributes[nextleft] = 256+MENU_HDG; nextleft += 2; choicekey[nextleft] = FIK_DELETE; attributes[nextleft] = MENU_ITEM; #ifdef XFRACT choices[nextleft] = "draw fractal "; #else choices[nextleft] = "select video mode... "; #endif nextleft += 2; choicekey[nextleft] = 't'; attributes[nextleft] = MENU_ITEM; choices[nextleft] = "select fractal type "; if (fullmenu) { if ((curfractalspecific->tojulia != NOFRACTAL && param[0] == 0.0 && param[1] == 0.0) || curfractalspecific->tomandel != NOFRACTAL) { nextleft += 2; choicekey[nextleft] = FIK_SPACE; attributes[nextleft] = MENU_ITEM; choices[nextleft] = "toggle to/from julia "; showjuliatoggle = 1; } if (fractype==JULIA || fractype==JULIAFP || fractype==INVERSEJULIA) { nextleft += 2; choicekey[nextleft] = 'j'; attributes[nextleft] = MENU_ITEM; choices[nextleft] = "toggle to/from inverse "; showjuliatoggle = 1; } nextleft += 2; choicekey[nextleft] = 'h'; attributes[nextleft] = MENU_ITEM; choices[nextleft] = "return to prior image "; nextleft += 2; choicekey[nextleft] = FIK_BACKSPACE; attributes[nextleft] = MENU_ITEM; choices[nextleft] = "reverse thru history "; } else { nextleft += 2; } nextleft += 2; choices[nextleft] = " OPTIONS "; attributes[nextleft] = 256+MENU_HDG; nextleft += 2; choicekey[nextleft] = 'x'; attributes[nextleft] = MENU_ITEM; choices[nextleft] = "basic options... "; nextleft += 2; choicekey[nextleft] = 'y'; attributes[nextleft] = MENU_ITEM; choices[nextleft] = "extended options... "; nextleft += 2; choicekey[nextleft] = 'z'; attributes[nextleft] = MENU_ITEM; choices[nextleft] = "type-specific parms... "; nextleft += 2; choicekey[nextleft] = 'p'; attributes[nextleft] = MENU_ITEM; choices[nextleft] = "passes options...

"; nextleft += 2; choicekey[nextleft] = 'v'; attributes[nextleft] = MENU_ITEM; choices[nextleft] = "view window options... "; if (showjuliatoggle == 0) { nextleft += 2; choicekey[nextleft] = 'i'; attributes[nextleft] = MENU_ITEM; choices[nextleft] = "fractal 3D parms... "; } nextleft += 2; choicekey[nextleft] = FIK_CTL_B; attributes[nextleft] = MENU_ITEM; choices[nextleft] = "browse parms... "; if (fullmenu) { nextleft += 2; choicekey[nextleft] = FIK_CTL_E; attributes[nextleft] = MENU_ITEM; choices[nextleft] = "evolver parms... "; #ifndef XFRACT nextleft += 2; choicekey[nextleft] = FIK_CTL_F; attributes[nextleft] = MENU_ITEM; choices[nextleft] = "sound parms... "; #endif } nextright += 2; attributes[nextright] = 256 + MENU_HDG; choices[nextright] = " FILE "; nextright += 2; choicekey[nextright] = '@'; attributes[nextright] = MENU_ITEM; choices[nextright] = "run saved command set... <@> "; if (fullmenu) { nextright += 2; choicekey[nextright] = 's'; attributes[nextright] = MENU_ITEM; choices[nextright] = "save image to file "; } nextright += 2; choicekey[nextright] = 'r'; attributes[nextright] = MENU_ITEM; choices[nextright] = "load image from file... "; nextright += 2; choicekey[nextright] = '3'; attributes[nextright] = MENU_ITEM; choices[nextright] = "3d transform from file...<3> "; if (fullmenu) { nextright += 2; choicekey[nextright] = '#'; attributes[nextright] = MENU_ITEM; choices[nextright] = "3d overlay from file.....<#> "; nextright += 2; choicekey[nextright] = 'b'; attributes[nextright] = MENU_ITEM; choices[nextright] = "save current parameters.. "; nextright += 2; choicekey[nextright] = 16; attributes[nextright] = MENU_ITEM; choices[nextright] = "print image "; } nextright += 2; choicekey[nextright] = 'd'; attributes[nextright] = MENU_ITEM; #ifdef XFRACT choices[nextright] = "shell to Linux/Unix "; #else choices[nextright] = "shell to dos "; #endif nextright += 2; choicekey[nextright] = 'g'; attributes[nextright] = MENU_ITEM; choices[nextright] = "give command string "; nextright += 2; choicekey[nextright] = FIK_ESC; attributes[nextright] = MENU_ITEM; choices[nextright] = "quit "FRACTINT" "; nextright += 2; choicekey[nextright] = FIK_INSERT; attributes[nextright] = MENU_ITEM; choices[nextright] = "restart "FRACTINT" "; #ifdef XFRACT if (fullmenu && (g_got_real_dac || fake_lut) && colors >= 16) #else if (fullmenu && g_got_real_dac && colors >= 16) #endif { nextright += 2; choices[nextright] = " COLORS "; attributes[nextright] = 256+MENU_HDG; nextright += 2; choicekey[nextright] = 'c'; attributes[nextright] = MENU_ITEM; choices[nextright] = "color cycling mode "; nextright += 2; choicekey[nextright] = '+'; attributes[nextright] = MENU_ITEM; choices[nextright] = "rotate palette <+>, <-> "; if (colors > 16) { if (!g_really_ega) { nextright += 2; choicekey[nextright] = 'e'; attributes[nextright] = MENU_ITEM; choices[nextright] = "palette editing mode "; } nextright += 2; choicekey[nextright] = 'a'; attributes[nextright] = MENU_ITEM; choices[nextright] = "make starfield "; } } nextright += 2; choicekey[nextright] = FIK_CTL_A; attributes[nextright] = MENU_ITEM; choices[nextright] = "ant automaton "; nextright += 2; choicekey[nextright] = FIK_CTL_S; attributes[nextright] = MENU_ITEM; choices[nextright] = "stereogram "; i = driver_key_pressed() ? driver_get_key() : 0; if (menu_checkkey(i, 0) == 0) { helpmode = HELPMAIN; /* switch help modes */ nextleft += 2; if (nextleft < nextright) { nextleft = nextright + 1; } i = fullscreen_choice(CHOICE_MENU | CHOICE_CRUNCH, "MAIN MENU", NULL, NULL, nextleft, (char **) choices, attributes, 2, nextleft/2, 29, 0, NULL, NULL, NULL, menu_checkkey); if (i == -1) /* escape */ { i = FIK_ESC; } else if (i < 0) { i = 0 - i; } else /* user selected a choice */ { i = choicekey[i]; if (-10 == i) { helpmode = HELPZOOM; help(0); i = 0; } } } if (i == FIK_ESC) /* escape from menu exits Fractint */ { helptitle(); driver_set_attr(1, 0, C_GENERAL_MED, 24*80); for (i = 9; i <= 11; ++i) { driver_set_attr(i, 18, C_GENERAL_INPUT, 40); } putstringcenter(10, 18, 40, C_GENERAL_INPUT, #ifdef XFRACT "Exit from Xfractint (y/n)? y" #else "Exit from Fractint (y/n)? y" #endif ); driver_hide_text_cursor(); while ((i = driver_get_key()) != 'y' && i != 'Y' && i != 13) { if (i == 'n' || i == 'N') { goto top; } } goodbye(); } if (i == FIK_TAB) { tab_display(); i = 0; } if (i == FIK_ENTER || i == FIK_ENTER_2) { i = 0; /* don't trigger new calc */ } tabmode = oldtabmode; return i; } static int menu_checkkey(int curkey, int choice) { /* choice is dummy used by other routines called by fullscreen_choice() */ int testkey; testkey = choice; /* for warning only */ testkey = (curkey>='A' && curkey<='Z') ? curkey+('a'-'A') : curkey; #ifdef XFRACT /* We use F2 for shift-@, annoyingly enough */ if (testkey == FIK_F2) return(0-testkey); #endif if (testkey == '2') testkey = '@'; if (strchr("#@2txyzgvir3dj",testkey) || testkey == FIK_INSERT || testkey == FIK_CTL_B || testkey == FIK_ESC || testkey == FIK_DELETE || testkey == FIK_CTL_F) /*RB 6== ctrl-F for sound menu */ return(0-testkey); if (menutype) { if (strchr("\\sobpkrh",testkey) || testkey == FIK_TAB || testkey == FIK_CTL_A || testkey == FIK_CTL_E || testkey == FIK_BACKSPACE || testkey == FIK_CTL_P || testkey == FIK_CTL_S || testkey == FIK_CTL_U) /* ctrl-A, E, H, P, S, U */ return(0-testkey); if (testkey == ' ') if ((curfractalspecific->tojulia != NOFRACTAL && param[0] == 0.0 && param[1] == 0.0) || curfractalspecific->tomandel != NOFRACTAL) return(0-testkey); if (g_got_real_dac && colors >= 16) { if (strchr("c+-",testkey)) return(0-testkey); if (colors > 16 && (testkey == 'a' || (!g_really_ega && testkey == 'e'))) return(0-testkey); } /* Alt-A and Alt-S */ if (testkey == FIK_ALT_A || testkey == FIK_ALT_S ) return(0-testkey); } if (check_vidmode_key(0,testkey) >= 0) return(0-testkey); return(0); } int input_field( int options, /* &1 numeric, &2 integer, &4 double */ int attr, /* display attribute */ char *fld, /* the field itself */ int len, /* field length (declare as 1 larger for \0) */ int row, /* display row */ int col, /* display column */ int (*checkkey)(int) /* routine to check non data keys, or NULL */ ) { char savefld[81]; char buf[81]; int insert, started, offset, curkey, display; int i, j; int ret,savelookatmouse; savelookatmouse = lookatmouse; lookatmouse = 0; ret = -1; strcpy(savefld,fld); insert = started = offset = 0; display = 1; while (1) { strcpy(buf,fld); i = (int) strlen(buf); while (i < len) buf[i++] = ' '; buf[len] = 0; if (display) { /* display current value */ driver_put_string(row,col,attr,buf); display = 0; } curkey = driver_key_cursor(row+insert,col+offset); /* get a keystroke */ if (curkey == 1047) curkey = 47; /* numeric slash */ switch (curkey) { case FIK_ENTER: case FIK_ENTER_2: ret = 0; goto inpfld_end; case FIK_ESC: goto inpfld_end; case FIK_RIGHT_ARROW: if (offset < len-1) ++offset; started = 1; break; case FIK_LEFT_ARROW: if (offset > 0) --offset; started = 1; break; case FIK_HOME: offset = 0; started = 1; break; case FIK_END: offset = (int) strlen(fld); started = 1; break; case FIK_BACKSPACE: case 127: /* backspace */ if (offset > 0) { j = (int) strlen(fld); for (i = offset-1; i < j; ++i) fld[i] = fld[i+1]; --offset; } started = display = 1; break; case FIK_DELETE: /* delete */ j = (int) strlen(fld); for (i = offset; i < j; ++i) fld[i] = fld[i+1]; started = display = 1; break; case FIK_INSERT: /* insert */ insert ^= 0x8000; started = 1; break; case FIK_F5: strcpy(fld,savefld); insert = started = offset = 0; display = 1; break; default: if (nonalpha(curkey)) { if (checkkey && (ret = (*checkkey)(curkey)) != 0) goto inpfld_end; break; /* non alphanum char */ } if (offset >= len) break; /* at end of field */ if (insert && started && strlen(fld) >= (size_t)len) break; /* insert & full */ if ((options & INPUTFIELD_NUMERIC) && (curkey < '0' || curkey > '9') && curkey != '+' && curkey != '-') { if (options & INPUTFIELD_INTEGER) break; /* allow scientific notation, and specials "e" and "p" */ if ( ((curkey != 'e' && curkey != 'E') || offset >= 18) && ((curkey != 'p' && curkey != 'P') || offset != 0 ) && curkey != '.') break; } if (started == 0) /* first char is data, zap field */ fld[0] = 0; if (insert) { j = (int) strlen(fld); while (j >= offset) { fld[j+1] = fld[j]; --j; } } if ((size_t)offset >= strlen(fld)) fld[offset+1] = 0; fld[offset++] = (char)curkey; /* if "e" or "p" in first col make number e or pi */ if ((options & (INPUTFIELD_NUMERIC | INPUTFIELD_INTEGER)) == INPUTFIELD_NUMERIC) { /* floating point */ double tmpd; int specialv; char tmpfld[30]; specialv = 0; if (*fld == 'e' || *fld == 'E') { tmpd = exp(1.0); specialv = 1; } if (*fld == 'p' || *fld == 'P') { tmpd = atan(1.0) * 4; specialv = 1; } if (specialv) { if ((options & INPUTFIELD_DOUBLE) == 0) roundfloatd(&tmpd); sprintf(tmpfld,"%.15g",tmpd); tmpfld[len-1] = 0; /* safety, field should be long enough */ strcpy(fld,tmpfld); offset = 0; } } started = display = 1; } } inpfld_end: lookatmouse = savelookatmouse; return(ret); } int field_prompt( char *hdg, /* heading, \n delimited lines */ char *instr, /* additional instructions or NULL */ char *fld, /* the field itself */ int len, /* field length (declare as 1 larger for \0) */ int (*checkkey)(int) /* routine to check non data keys, or NULL */ ) { char *charptr; int boxwidth,titlelines,titlecol,titlerow; int promptcol; int i,j; char buf[81]; helptitle(); /* clear screen, display title */ driver_set_attr(1,0,C_PROMPT_BKGRD,24*80); /* init rest to background */ charptr = hdg; /* count title lines, find widest */ i = boxwidth = 0; titlelines = 1; while (*charptr) { if (*(charptr++) == '\n') { ++titlelines; i = -1; } if (++i > boxwidth) boxwidth = i; } if (len > boxwidth) boxwidth = len; i = titlelines + 4; /* total rows in box */ titlerow = (25 - i) / 2; /* top row of it all when centered */ titlerow -= titlerow / 4; /* higher is better if lots extra */ titlecol = (80 - boxwidth) / 2; /* center the box */ titlecol -= (90 - boxwidth) / 20; promptcol = titlecol - (boxwidth-len)/2; j = titlecol; /* add margin at each side of box */ if ((i = (82-boxwidth)/4) > 3) i = 3; j -= i; boxwidth += i * 2; for (i = -1; i < titlelines+3; ++i) /* draw empty box */ driver_set_attr(titlerow+i,j,C_PROMPT_LO,boxwidth); g_text_cbase = titlecol; /* set left margin for putstring */ driver_put_string(titlerow,0,C_PROMPT_HI,hdg); /* display heading */ g_text_cbase = 0; i = titlerow + titlelines + 4; if (instr) { /* display caller's instructions */ charptr = instr; j = -1; while ((buf[++j] = *(charptr++)) != 0) if (buf[j] == '\n') { buf[j] = 0; putstringcenter(i++,0,80,C_PROMPT_BKGRD,buf); j = -1; } putstringcenter(i,0,80,C_PROMPT_BKGRD,buf); } else /* default instructions */ putstringcenter(i,0,80,C_PROMPT_BKGRD, "Press ENTER when finished (or ESCAPE to back out)"); return input_field(0,C_PROMPT_INPUT,fld,len, titlerow+titlelines+1,promptcol,checkkey); } /* thinking(1,message): if thinking message not yet on display, it is displayed; otherwise the wheel is updated returns 0 to keep going, -1 if keystroke pending thinking(0,NULL): call this when thinking phase is done */ int thinking(int options,char *msg) { static int thinkstate = -1; char *wheel[] = {"-","\\","|","/"}; static int thinkcol; static int count = 0; char buf[81]; if (options == 0) { if (thinkstate >= 0) { thinkstate = -1; driver_unstack_screen(); } return(0); } if (thinkstate < 0) { driver_stack_screen(); thinkstate = 0; helptitle(); strcpy(buf," "); strcat(buf,msg); strcat(buf," "); driver_put_string(4,10,C_GENERAL_HI,buf); thinkcol = g_text_col - 3; count = 0; } if ((count++)<100) { return 0; } count = 0; driver_put_string(4,thinkcol,C_GENERAL_HI,wheel[thinkstate]); driver_hide_text_cursor(); /* turn off cursor */ thinkstate = (thinkstate + 1) & 3; return (driver_key_pressed()); } /* savegraphics/restoregraphics: video.asm subroutines */ unsigned long swaptotlen; unsigned long swapoffset; BYTE *swapvidbuf; int swaplength; #define SWAPBLKLEN 4096 /* must be a power of 2 */ U16 memhandle = 0; BYTE suffix[10000]; void discardgraphics() /* release expanded/extended memory if any in use */ { #ifndef XFRACT MemoryRelease(memhandle); memhandle = 0; #endif } /*VIDEOINFO *g_video_table; /* temporarily loaded fractint.cfg info */ int g_video_table_len; /* number of entries in above */ int showvidlength() { int sz; sz = (sizeof(VIDEOINFO)+sizeof(int))*MAXVIDEOMODES; return(sz); } int g_cfg_line_nums[MAXVIDEOMODES] = { 0 }; /* load_fractint_config * * Reads fractint.cfg, loading videoinfo entries into g_video_table. * Sets the number of entries, sets g_video_table_len. * Past g_video_table, g_cfg_line_nums are stored for update_fractint_cfg. * If fractint.cfg is not found or invalid, issues a message * (first time the problem occurs only, and only if options is * zero) and uses the hard-coded table. */ void load_fractint_config(void) { FILE *cfgfile; VIDEOINFO vident; int linenum; long xdots, ydots; int i, j, keynum, ax, bx, cx, dx, dotmode, colors; char *fields[11]; int textsafe2; char tempstring[150]; int truecolorbits; findpath("fractint.cfg",tempstring); if (tempstring[0] == 0 /* can't find the file */ || (cfgfile = fopen(tempstring,"r")) == NULL) /* can't open it */ { goto bad_fractint_cfg; } linenum = 0; while (g_video_table_len < MAXVIDEOMODES && fgets(tempstring, 120, cfgfile)) { if (strchr(tempstring,'\n') == NULL) { /* finish reading the line */ while (fgetc(cfgfile) != '\n' && !feof(cfgfile)); } ++linenum; if (tempstring[0] == ';') { continue; /* comment line */ } tempstring[120] = 0; tempstring[(int) strlen(tempstring)-1] = 0; /* zap trailing \n */ i = j = -1; /* key, mode name, ax, bx, cx, dx, dotmode, x, y, colors, comments, driver */ for (;;) { if (tempstring[++i] < ' ') { if (tempstring[i] == 0) { break; } tempstring[i] = ' '; /* convert tab (or whatever) to blank */ } else if (tempstring[i] == ',' && ++j < 11) { #if defined(_WIN32) _ASSERTE(j >= 0 && j < 11); #endif fields[j] = &tempstring[i+1]; /* remember start of next field */ tempstring[i] = 0; /* make field a separate string */ } } keynum = check_vidmode_keyname(tempstring); sscanf(fields[1],"%x",&ax); sscanf(fields[2],"%x",&bx); sscanf(fields[3],"%x",&cx); sscanf(fields[4],"%x",&dx); dotmode = atoi(fields[5]); xdots = atol(fields[6]); ydots = atol(fields[7]); colors = atoi(fields[8]); if (colors == 4 && strchr(strlwr(fields[8]),'g')) { colors = 256; truecolorbits = 4; /* 32 bits */ } else if (colors == 16 && strchr(fields[8],'m')) { colors = 256; truecolorbits = 3; /* 24 bits */ } else if (colors == 64 && strchr(fields[8],'k')) { colors = 256; truecolorbits = 2; /* 16 bits */ } else if (colors == 32 && strchr(fields[8],'k')) { colors = 256; truecolorbits = 1; /* 15 bits */ } else { truecolorbits = 0; } textsafe2 = dotmode / 100; dotmode %= 100; if (j < 9 || keynum < 0 || dotmode < 0 || dotmode > 30 || textsafe2 < 0 || textsafe2 > 4 || xdots < MINPIXELS || xdots > MAXPIXELS || ydots < MINPIXELS || ydots > MAXPIXELS || (colors != 0 && colors != 2 && colors != 4 && colors != 16 && colors != 256) ) { goto bad_fractint_cfg; } g_cfg_line_nums[g_video_table_len] = linenum; /* for update_fractint_cfg */ memset(&vident, 0, sizeof(vident)); strncpy(&vident.name[0], fields[0], NUM_OF(vident.name)); strncpy(&vident.comment[0], fields[9], NUM_OF(vident.comment)); vident.name[25] = vident.comment[25] = 0; vident.keynum = keynum; vident.videomodeax = ax; vident.videomodebx = bx; vident.videomodecx = cx; vident.videomodedx = dx; vident.dotmode = truecolorbits * 1000 + textsafe2 * 100 + dotmode; vident.xdots = (short)xdots; vident.ydots = (short)ydots; vident.colors = colors; /* if valid, add to supported modes */ vident.driver = driver_find_by_name(fields[10]); if (vident.driver != NULL) { if (vident.driver->validate_mode(vident.driver, &vident)) { /* look for a synonym mode and if found, overwite its key */ int m; int synonym_found = FALSE; for (m = 0; m < g_video_table_len; m++) { VIDEOINFO *mode = &g_video_table[m]; if ((mode->driver == vident.driver) && (mode->colors == vident.colors) && (mode->xdots == vident.xdots) && (mode->ydots == vident.ydots) && (mode->dotmode == vident.dotmode)) { if (0 == mode->keynum) { mode->keynum = vident.keynum; } synonym_found = TRUE; break; } } /* no synonym found, append it to current list of video modes */ if (FALSE == synonym_found) { add_video_mode(vident.driver, &vident); } } } } fclose(cfgfile); return; bad_fractint_cfg: g_bad_config = -1; /* bad, no message issued yet */ } void bad_fractint_cfg_msg() { stopmsg(0, "File FRACTINT.CFG is missing or invalid.\n" "See Hardware Support and Video Modes in the full documentation for help.\n" "I will continue with only the built-in video modes available."); g_bad_config = 1; /* bad, message issued */ } int check_vidmode_key(int option,int k) { int i; /* returns g_video_table entry number if the passed keystroke is a */ /* function key currently assigned to a video mode, -1 otherwise */ if (k == 1400) /* special value from select_vid_mode */ return(MAXVIDEOMODES-1); /* for last entry with no key assigned */ if (k != 0) { if (option == 0) { /* check resident video mode table */ for (i = 0; i < MAXVIDEOMODES; ++i) { if (g_video_table[i].keynum == k) return(i); } } else { /* check full g_video_table */ for (i = 0; i < g_video_table_len; ++i) { if (g_video_table[i].keynum == k) return(i); } } } return(-1); } int check_vidmode_keyname(char *kname) { /* returns key number for the passed keyname, 0 if not a keyname */ int i,keyset; keyset = 1058; if (*kname == 'S' || *kname == 's') { keyset = 1083; ++kname; } else if (*kname == 'C' || *kname == 'c') { keyset = 1093; ++kname; } else if (*kname == 'A' || *kname == 'a') { keyset = 1103; ++kname; } if (*kname != 'F' && *kname != 'f') return(0); if (*++kname < '1' || *kname > '9') return(0); i = *kname - '0'; if (*++kname != 0 && *kname != ' ') { if (*kname != '0' || i != 1) return(0); i = 10; ++kname; } while (*kname) if (*(kname++) != ' ') return(0); if ((i += keyset) < 2) i = 0; return(i); } void vidmode_keyname(int k,char *buf) { /* set buffer to name of passed key number */ *buf = 0; if (k > 0) { if (k > 1103) { *(buf++) = 'A'; k -= 1103; } else if (k > 1093) { *(buf++) = 'C'; k -= 1093; } else if (k > 1083) { *(buf++) = 'S'; k -= 1083; } else k -= 1058; sprintf(buf,"F%d",k); } }