home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / BENCHMAR / FASMATH.ZIP / BIOM.ARC / BIOM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-29  |  19.9 KB  |  626 lines

  1. /*
  2.     Biomorph/Mandelbrot Fractal Generator
  3.     C-code    Version 2.0    By Fred Dunlap from Bert Tyler program
  4. */
  5.  
  6. #include <stdio.h>
  7. #include <dos.h>
  8. extern int calcdots_sin(void);
  9. extern int calcdots_b3(void);
  10. extern int calcdots_b5(void);
  11. extern int calcdots_f(void);
  12.  
  13. struct videoinfo {        /* All we need to know about a Video Adapter */
  14.     char    name[40];    /* Adapter name (IBM EGA, etc)        */
  15.     int    videomodeax;    /* begin with INT 10H, AX=(this)    */
  16.     int    videomodebx;    /*        ...and BX=(this)    */
  17.     int    videomodecx;    /*        ...and CX=(this)    */
  18.     int    videomodedx;    /*        ...and DX=(this)    */
  19.     int    dotmode;    /* video access method used by asm code    */
  20.                 /*    1 == BIOS 10H, AH=12,13 (SLOW)    */
  21.                 /*    2 == access like EGA/VGA    */
  22.                 /*    3 == access like MCGA        */
  23.     int    xdots;        /* number of dots across the screen    */
  24.     int    ydots;        /* number of dots down the screen    */
  25.     int    colors;        /* number of colors available        */
  26.     char    comment[40];    /* Comments (UNTESTED, etc)        */
  27.     };
  28.  
  29. struct videoinfo videomode[] = {
  30. /*
  31.     Feel free to add your favorite video adapter to the following table.
  32.     Just remember that only the first 50 entries get displayed and
  33.     assigned Function keys.
  34.  
  35. --Adapter/Mode------|---INT 10H---|Dot-|-Resolution-|------Comments-----------
  36. -----Name-----------|-AX--BX-CX-DX|Mode|X-|-Y-|Color|-------------------------
  37. */
  38. "IBM Low-Rez EGA",   0x0d, 0, 0, 0, 2, 320, 200, 16, "Quick, but chunky",
  39. "IBM 16-Color EGA",  0x10, 0, 0, 0, 2, 640, 350, 16, "Slower, but lots nicer",
  40. "IBM 256-Color MCGA",0x13, 0, 0, 0, 3, 320, 200,256, "Quick, LOTS of colors",
  41. "IBM 16-Color VGA",  0x12, 0, 0, 0, 2, 640, 480, 16, "Nice, high resolution",
  42. "IBM 4-Color CGA",   0x05, 0, 0, 0, 1, 320, 200,  4, "BIOS",
  43. "IBM Hi-Rez B&W CGA",0x06, 0, 0, 0, 1, 640, 200,  2, "BIOS",
  44. "IBM B&W EGA",       0x0f, 0, 0, 0, 2, 640, 350,  2, "(Monochrome EGA)",
  45. "IBM B&W VGA",       0x11, 0, 0, 0, 2, 640, 480,  2, "(Monochrome VGA)",
  46. "END",                  3, 0, 0, 0, 0,   0,   0,  0, "Marks END of the List"
  47.     };
  48.  
  49. int    maxvideomode;        /* size of the above list */
  50. int    adapter;        /* Video Adapter chosen from above list    */
  51.  
  52. char *fkeys[] = {        /* Function Key names for display table */
  53.     "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10",
  54.     "SF1","SF2","SF3","SF4","SF5","SF6","SF7","SF8","SF9","SF10",
  55.     "CF1","CF2","CF3","CF4","CF5","CF6","CF7","CF8","CF9","CF10",
  56.     "AF1","AF2","AF3","AF4","AF5","AF6","AF7","AF8","AF9","AF10",
  57.     "END"};
  58. char *accessmethod[] = {" ","B"," "," "}; /* BIOS access indicator */
  59.  
  60. #define MAXHISTORY    80        /* save this many historical rcds */
  61.  
  62. double    history[MAXHISTORY][4];    /* for historical (HOME Key) purposes */
  63.  
  64. /*
  65.    the following variables are out here only so
  66.    that the assembler routine can get at them easily
  67. */
  68.     int    dotmode;            /* video access method      */
  69.                         /* 1 == use the BIOS (ugh)  */
  70.                         /* 2 == access like EGA/VGA */
  71.                         /* 3 == access like MCGA    */
  72.     int    xdots, ydots;            /* # of dots on the screen  */
  73.     int    colors;                /* maximum colors available */
  74.     int    maxit;                /* try this many iterations */
  75.     int    ixmin, ixmax, iymin, iymax;    /* corners of the zoom box  */
  76.  
  77.     double    delx, dely;            /* screen pixel increments */
  78.     double    xmin, xmax, ymin, ymax;        /* screen corner values */
  79.     double    c_r, c_i;
  80.     double    limit;
  81.  
  82. /********************************************************************/
  83. /**                    module level variables                      **/
  84. /********************************************************************/
  85.     static int new_argc;
  86.     static int far *it_took = 0l;
  87.     static char *new_argv[20];
  88.     static int time_delay = -1;
  89.  
  90.     static int    type = 0;    /* Fractal type */
  91.                         /* 0 = Mandelbrot */
  92.                         /* 1 = cube biomorph */
  93.                         /* 2 = ^5 biomorph */
  94.                         /* 3 = sin biomorph */
  95.     static struct {
  96.         double    xmin;        double    xmax;
  97.         double    ymin;        double    ymax;
  98.         double    c_r;
  99.         double    c_i;
  100.         double    limit;
  101.         int        maxit;
  102.     } defaults[] = {
  103.        /* xmin   xmax   ymin   ymax    c_r    c_i limit  max iterations */
  104.         { -2.0,   1.0,  -1.5,   1.5,   0.0,   0.0,  4.0, 150},  /* Mandelbrot c_r and c_i aren't used */
  105.         {-16.0,  16.0, -10.0,  10.0,   0.5,   0.0, 10.0, 150},  /* biom cubed */
  106.         { -8.0,   8.0,  -5.0,   5.0,   0.7,   0.3,  5.0, 150},  /* biom ^5 */
  107.         {-14.0,  14.0, -10.0,  10.0,   0.1,   0.1, 10.0, 150}}; /* biom sin+squared */
  108.  
  109.  
  110. /*.FUNCTION        *********************************************************
  111. * Name:       scan_for_switches                       Fred Dunlap   09/21/89
  112. * Purpose:    Scans through argv looking for switches.  If it finds one it
  113. *             removes it from new_argv. The args that are not switches are
  114. *             left in new_argv.
  115. *
  116. * Inputs:     argc and argv.
  117. *
  118. * Outputs:    number of errors in the switches found
  119. *             initialized new_argc and new_argv.
  120. *
  121. * Called by:  main
  122. ****************************************************************************/
  123. scan_for_switches(int argc, char *argv[])
  124. {
  125. /* supported switches:
  126.     -Fx           x is 1-9 for video mode.
  127.     -x            x is 1-4 for fractal set.
  128.     -Tssss:oooo ssss:oooo is seg and offset of int variable to write 18.2th seconds into
  129.     -Dxx        xx is delay time after draw before exit (unless key hit). */
  130.     int    error = 0;
  131.     int    i;
  132.     new_argc = 0;
  133.     while (argc) {
  134.         i = strlen(argv[0]);
  135.         if (*argv[0] == '-' && (i == 2 || 
  136.                                 i == 11 && argv[0][6] == ':' && argv[0][1] == 'T' ||
  137.                                 i == 4 && toupper(argv[0][1]) == 'D' ||
  138.                                 i == 3 && toupper(argv[0][1]) == 'F')) {
  139.             if (i == 2) {
  140.                 /* type switch */
  141.                 i = argv[0][1];
  142.                 if (i > '0' && i < '5')
  143.                     type = i - '1';
  144.                 else
  145.                     error += 1;
  146.             } else if (i == 3) {
  147.                 i = argv[0][2];
  148.                 if (i > '0' && i < '9') {
  149.                     adapter = i - '1';
  150.                 } else
  151.                     error += 1;
  152.             } else if (i == 4) {
  153.                 time_delay = atoi(argv[0]+2);
  154.                 time_delay *= 18;
  155.             } else if (i == 11) {
  156.                 if (sscanf(argv[0]+2,"%p", &it_took) != 3) {
  157.                     /* Microsoft C supports the %p but assigns THREE things.
  158.                        I would assume other compilers won't do this and this
  159.                        will need modifing. */
  160.                     error += 1;
  161.                     it_took = 0l;
  162.                 }
  163.             } else {
  164.             } /* time address */
  165.         } else
  166.             new_argv[new_argc++] = argv[0];
  167.         argc -= 1;
  168.         argv++;
  169.     }
  170.     return error;
  171. } /* end scan_for_switches */
  172.  
  173. /*.FUNCTION        *********************************************************
  174. * Name:                                               Fred Dunlap   09/21/89
  175. * Purpose:    
  176. *             
  177. *             
  178. * Inputs:     
  179. *             
  180. *
  181. * Outputs:    
  182. *
  183. * Called by:  
  184. ****************************************************************************/
  185. get_initial_mode()
  186. {
  187.     int    i, j, kbdchar;            /* keyboard key-hit value */
  188. printf("Biom   V2   by Fred Dunlap from a Bert Tyler program.\n");
  189. printf("This program (BIOM) can be started with options on the command line.\n");
  190. printf("The options are numbers specifing: limit Cr Ci xmin xmax ymin ymax.\n");
  191. printf("The useful keys you can hit while this program is running are:\n");
  192. printf("  PgUp/PgDn         Shrink/Expand the Zoom Box\n");
  193. printf("  Cursor Keys       Move the Zoom Box Left, Right, Up, or Down (Panning)\n");
  194. printf("  Ctrl-Cursor-Keys  Pan as above, but quickly (may require an Enhanced KBD)\n");
  195. printf("  End or Enter      Redraw (full screen) the area inside the Zoom Box \n");
  196. printf("  F1,F2,F3,F4...    Select a new Video Mode   (-Fx on the command line)\n");
  197. printf("  Home              Redraw Previous screen (you can 'back out' recursively)\n");
  198. printf("  Tab               Display the Screen or Zoom-Box X and Y Coordinates\n");
  199. printf("  Insert            Restart the program (at this screen)\n");
  200. printf("  Delete or Esc     Stop the program and return.\n");
  201. printf("  1                 Mandelbrot set fractal.   (-1 on the command line)\n");
  202. printf("  2                 Biomorph z^3 + c.         (-2 on the command line)\n");
  203. printf("  3                 Biomorph z^5 + c.         (-3 on the command line)\n");
  204. printf("  4                 Biomorph sin(z) +z^2 + c. (-4 on the command line)\n");
  205. printf("Hitting any key while the program is drawing will stop the drawing immediately\n");
  206. printf("to perform the function.   This means you can begin Zooming and Panning (or\n");
  207. printf("anything else) as soon as you see something interesting.  If you haven't yet\n");
  208. printf("hit a key when the screen is finished, the program will beep and wait for you.\n");
  209. printf("\n");
  210. printf("Please Select your Video Mode by hitting a Function Key (F1, F2, F3, F4,...) \n");
  211. printf("    (Or hit the <ENTER> key to see a complete list of supported Video modes) \n");
  212.  
  213. j = maxvideomode;                /* init for video modes scan */
  214. for (;;) {                    /* wait for valid Fn Key */
  215.     kbdchar = getakey();
  216.     if (kbdchar >= 1059 && kbdchar < 1069    /* F1 - F10 */
  217.      && kbdchar < 1059 + maxvideomode) {
  218.         adapter = kbdchar - 1059;    /* use this adapter initially */
  219.         break;
  220.         }
  221.     if (kbdchar >= 1084 && kbdchar < 1114    /* SF1 - AF10 */
  222.      && kbdchar < 1074 + maxvideomode) {
  223.         adapter = kbdchar - 1074;    /* use this adapter initially */
  224.         break;
  225.         }
  226.     if (kbdchar >= 1120 && kbdchar < 1130    /* Alt-1 thru Alt-0 */
  227.      && kbdchar < 1080 + maxvideomode) {
  228.         adapter = kbdchar - 1080;    /* use this adapter initially */
  229.         break;
  230.         }
  231.     if (kbdchar == 1000) exit(0);        /* Control-C */
  232.     if (kbdchar == 27)   exit(0);        /* exit to DOS on Escape Key */
  233.     if (kbdchar == 1083) exit(0);        /* exit to DOS on Delete Key */
  234.     if (kbdchar == 13) {            /* <ENTER> key: display adapter list */
  235.         j += 14;            /* display next page */
  236.         if (j >= maxvideomode) j = 0;    /* (or 1st page)     */
  237.         printf("\n\n\nThe current list of supported Video Adapters and Modes includes:\n\n");
  238.         printf("      %-20s   Resolution Colors   %-30s\n\n",
  239.             "Video Adapter & Mode", "     Comments");
  240.         for (i = j; i < maxvideomode && i < j + 14; i++) {
  241.             printf("%-5s %-20s%6d x%4d%5d %1s   %-30s\n",fkeys[i],
  242.                 videomode[i].name,
  243.                 videomode[i].xdots,
  244.                 videomode[i].ydots,
  245.                 videomode[i].colors,
  246.                 accessmethod[videomode[i].dotmode],
  247.                 videomode[i].comment
  248.                 );
  249.             }
  250.         for (; i < j+15; i++) printf("\n");
  251. printf("    (Hit the <ENTER> key to see another page of supported Video modes) \n\n");
  252. printf("Please Select your Video Mode by hitting a Function Key (F1, F2, F3, F4,...) \n");
  253. printf("    (Notation:  F1, SF1, CF1, AF1 == Normal-, Shift-, Control- or Alt-F1) \n");
  254. printf("    'B' after #-of-colors means video access is via the BIOS (s-l-o-w-l-y)\n");
  255. printf("The program will begin with the full set as a starting point. ");
  256.         }
  257.     }
  258. }
  259.  
  260. /*.FUNCTION        *********************************************************
  261. * Name:                                               Fred Dunlap   09/21/89
  262. * Purpose:    
  263. *             
  264. *             
  265. * Inputs:     
  266. *             
  267. *
  268. * Outputs:    
  269. *
  270. * Called by:  
  271. ****************************************************************************/
  272. set_defaults()
  273. {
  274.     maxit = defaults[type].maxit;            /* max iterations */
  275.     limit = defaults[type].limit;
  276.     c_i   = defaults[type].c_i;
  277.     c_r   = defaults[type].c_r;
  278.     xmax  = defaults[type].xmax;
  279.     xmin  = defaults[type].xmin;
  280.     ymax  = defaults[type].ymax;
  281.     ymin  = defaults[type].ymin;
  282. }
  283.  
  284.  
  285. /*.FUNCTION        *********************************************************
  286. * Name:                                               Fred Dunlap   09/21/89
  287. * Purpose:    
  288. *             
  289. *             
  290. * Inputs:     
  291. *             
  292. *
  293. * Outputs:    
  294. *
  295. * Called by:  
  296. ****************************************************************************/
  297. main(argc,argv)
  298. int argc;
  299. char *argv[];
  300. {
  301.     double    atof();
  302.     unsigned int start_time, delta_time;
  303.     int    xstep, ystep;            /* zoom-box increment values */
  304.     int    axmode, bxmode, cxmode, dxmode;    /* video mode (BIOS ##) */
  305.     int    historyptr;            /* pointer into history tbl */
  306.     int    zoomoff;            /* = 0 when zoom is disabled */
  307.     int    kbdchar;            /* keyboard key-hit value */
  308.     int    more, kbdmore;            /* continuation variables */
  309.     int    i,j;                /* temporary loop counters */
  310.     union REGS regs;
  311.  
  312. adapter = -1;
  313.  
  314. scan_for_switches(argc,argv);
  315. if (kbhit())
  316.     getch();
  317.  
  318.  
  319. for (maxvideomode = 0;                /* get size of adapter list */
  320.     strcmp(videomode[maxvideomode].name,"END") != 0
  321.         && maxvideomode < 50;    /* that's all the Fn keys we got! */
  322.     maxvideomode++);
  323.  
  324.  
  325. restart:                /* insert key re-starts here */
  326. set_defaults();
  327.  
  328.  
  329. if (new_argc > 1) {
  330.     limit = atof(new_argv[1]);
  331.     if (limit == 0.0)
  332.         limit = 10.0;
  333. }
  334.  
  335. if (new_argc > 2)
  336.     c_r = atof(new_argv[2]);
  337.  
  338. if (new_argc > 3)
  339.     c_i = atof(new_argv[3]);
  340.  
  341. if (new_argc > 4)
  342.     xmin = atof(new_argv[4]);
  343.  
  344. if (new_argc > 5)
  345.     xmax = atof(new_argv[5]);
  346.  
  347. if (xmax <= xmin)
  348.     xmax = xmin + 10.0;
  349.  
  350. if (new_argc > 6)
  351.     ymin = atof(new_argv[6]);
  352.  
  353. if (new_argc > 7)
  354.     ymax = atof(new_argv[7]);
  355.  
  356. if (ymax <= ymin)
  357.     ymax = ymin + 10.0;
  358.  
  359. setvideomode(3,0,0,0);            /* switch to text mode */
  360.  
  361. if (adapter == -1)
  362.     get_initial_mode();
  363.  
  364. historyptr = 0;                    /* initialize history ptr */
  365. history[0][0] = -1;
  366. zoomoff = 1;                    /* zooming is enabled */
  367.  
  368.  
  369. for (more = 1; more;) {                    /* eternal loop */
  370.  
  371.                         /* collect adapter info */
  372.     axmode  = videomode[adapter].videomodeax; /* video mode (BIOS call) */
  373.     bxmode  = videomode[adapter].videomodebx; /* video mode (BIOS call) */
  374.     cxmode  = videomode[adapter].videomodecx; /* video mode (BIOS call) */
  375.     dxmode  = videomode[adapter].videomodecx; /* video mode (BIOS call) */
  376.     dotmode = videomode[adapter].dotmode;    /* assembler dot read/write */
  377.     xdots   = videomode[adapter].xdots;    /* # dots across the screen */
  378.     ydots   = videomode[adapter].ydots;    /* # dots down the screen   */
  379.     colors  = videomode[adapter].colors;    /* # colors available */
  380.  
  381.     xstep   = xdots / 40;            /* zoom-box increment: across */
  382.     ystep   = ydots / 40;            /* zoom-box increment: down */
  383.     if (xdots == 640 && ydots == 350)    /* zoom-box adjust:  640x350 */
  384.         { xstep = 16; ystep =  9; }
  385.     if (xdots == 720 && ydots == 512)    /* zoom-box adjust:  720x512 */
  386.         { xstep = 20; ystep = 15; }
  387.     if (xdots == 1024 && ydots == 768)    /* zoom-box adjust: 1024x768 */
  388.         { xstep = 32; ystep = 24; }
  389.  
  390.     delx = (xmax - xmin) / (xdots - 1);    /* calculate the stepsizes */
  391.     dely = (ymax - ymin) / (ydots - 1);
  392.  
  393.     if (delx <= 0.0 || dely <= 0.0) {        /* oops.  zoomed too far */
  394.         zoomoff = 0;
  395.         dely = .000000001;  /* !!! s.b. epslon */
  396.         delx = .000000001;
  397.     }
  398. #if 0
  399.     if (zoomoff == 0) {
  400.         xmax = xmaxlx0[xdots-1];        /* re-set xmax and ymax */
  401.         ymin = ly0[ydots-1];
  402.         }
  403. #endif
  404.  
  405.     if (history[0][0] == -1)            /* initialize the history file */
  406.         for (i = 0; i < MAXHISTORY; i++) {
  407.             history[i][0] = xmax;
  408.             history[i][1] = xmin;
  409.             history[i][2] = ymax;
  410.             history[i][3] = ymin;
  411.         }
  412.  
  413.     if (history[historyptr][0] != xmax  ||    /* save any (new) zoom data */
  414.         history[historyptr][1] != xmin  ||
  415.         history[historyptr][2] != ymax  ||
  416.         history[historyptr][3] != ymin) {
  417.         if (++historyptr == MAXHISTORY) historyptr = 0;
  418.         history[historyptr][0] = xmax;
  419.         history[historyptr][1] = xmin;
  420.         history[historyptr][2] = ymax;
  421.         history[historyptr][3] = ymin;
  422.         }
  423.  
  424.     setvideomode( axmode, bxmode, cxmode, dxmode); /* switch video modes */
  425.     regs.x.ax = 0;
  426.     int86( 26, ®s, ®s);
  427.     start_time = regs.x.dx;
  428.     if (regs.h.al == 1)
  429.         regs.x.dx = 0;
  430.  
  431.  
  432.     switch( type) {
  433.         case 0:
  434.             kbdmore = calcdots_f();            /* draw the fractal */
  435.             break;
  436.         case 1:
  437.             kbdmore = calcdots_b3();
  438.             break;
  439.         case 2:
  440.             kbdmore = calcdots_b5();
  441.             break;
  442.         case 3:
  443.             kbdmore = calcdots_sin();
  444.             break;
  445.     }
  446.  
  447.     regs.x.ax = 0;
  448.     int86( 26, ®s, ®s);
  449.     if (regs.h.al == 1 || kbdmore)
  450.         start_time = regs.x.dx;
  451.     delta_time = regs.x.dx - start_time;
  452.     start_time = regs.x.dx;  /* for -Dxx timing */
  453.  
  454.     if (!kbdmore)
  455.         printf("\007");            /* finished!  wake up! */
  456.  
  457.     if (kbdmore)
  458.         time_delay = 0;
  459.  
  460.     if (time_delay >= 0) { /* auto exit timing */
  461.         while( regs.x.dx - start_time < time_delay && !kbhit()) {
  462.             regs.x.ax = 0;
  463.             int86( 26, ®s, ®s);
  464.         }
  465.         if (kbhit())
  466.             time_delay = -1;
  467.         else {
  468.             if (it_took != 0l);
  469.                 *it_took = delta_time;
  470.             setvideomode(3,0,0,0);    /* all done.  return to text mode. */
  471.             exit(0);
  472.         }
  473.     }
  474.  
  475.     ixmin = 0;
  476.     ixmax = xdots-1;        /* initial zoom box */
  477.     iymin = 0;
  478.     iymax = ydots-1;
  479.  
  480.     kbdmore = 1;
  481.     while (kbdmore == 1) {            /* loop through cursor keys */
  482.         kbdchar = getakey();
  483.         switch (kbdchar) {
  484.             case 32:            /* spacebar */
  485.                 kbdmore = 0;
  486.                 break;
  487.             case 1071:            /* home */
  488.                 if (--historyptr < 0)
  489.                     historyptr = MAXHISTORY-1;
  490.                 xmax  = history[historyptr][0];
  491.                 xmin  = history[historyptr][1];
  492.                 ymax  = history[historyptr][2];
  493.                 ymin  = history[historyptr][3];
  494.                 zoomoff = 1;
  495.                 kbdmore = 0;
  496.                 break;
  497.             case 9:                /* tab */
  498.                 printf(" The Current Boundaries are: \n");
  499.                 printf(" Xmin = %16.13f \n",xmin);
  500.                 printf(" Xmax = %16.13f \n",xmax);
  501.                 printf(" Ymin = %16.13f \n",ymin);
  502.                 printf(" Ymax = %16.13f \n",ymax);
  503.                 continue;
  504.                 break;
  505.  
  506.             case '1':
  507.             case '2':
  508.             case '3':
  509.             case '4':
  510.                 type = kbdchar - '1';
  511.                 set_defaults();
  512.                 kbdmore = 0;
  513.                 break;
  514.  
  515.             case 13:            /* Enter */
  516.             case 1079:            /* end */
  517.                 xmax = xmin + delx * ixmax;
  518.                 xmin += delx * ixmin;
  519.                 ymin = ymax - dely * iymax;
  520.                 ymax -= dely * iymin;
  521.                 kbdmore = 0;
  522.                 break;
  523.             case 1082:            /* insert */
  524.                 adapter = -1;
  525.                 goto restart;
  526.                 break;
  527.             case 1000:            /* Control-C */
  528.             case 27:            /* Escape */
  529.             case 1083:            /* delete */
  530.                 more = 0; kbdmore = 0;
  531.                 break;
  532.             case 1075:            /* cursor left */
  533.                 if (zoomoff == 1 && ixmin >= 1)
  534.                     { ixmin -= 1; ixmax -= 1; }
  535.                     break;
  536.             case 1077:            /* cursor right */
  537.                 if (zoomoff == 1 && ixmax < xdots - 1)
  538.                     { ixmin += 1; ixmax += 1; }
  539.                     break;
  540.             case 1072:            /* cursor up */
  541.                 if (zoomoff == 1 && iymin >= 1)
  542.                     { iymin -= 1; iymax -= 1; }
  543.                     break;
  544.             case 1080:            /* cursor down */
  545.                 if (zoomoff == 1 && iymax < ydots - 1)
  546.                     { iymin += 1; iymax += 1; }
  547.                     break;
  548.             case 1115:            /* Ctrl-cursor left */
  549.                 if (zoomoff == 1 && ixmin >= 5)
  550.                     { ixmin -= 5; ixmax -= 5; }
  551.                     break;
  552.             case 1116:            /* Ctrl-cursor right */
  553.                 if (zoomoff == 1 && ixmax < xdots - 5)
  554.                     { ixmin += 5; ixmax += 5; }
  555.                     break;
  556.             case 1141:            /* Ctrl-cursor up */
  557.                 if (zoomoff == 1 && iymin >= 5)
  558.                     { iymin -= 5; iymax -= 5; }
  559.                     break;
  560.             case 1145:            /* Ctrl-cursor down */
  561.                 if (zoomoff == 1 && iymax < ydots - 5)
  562.                     { iymin += 5; iymax += 5; }
  563.                     break;
  564.             case 1073:            /* page up */
  565.                 if (zoomoff == 1 
  566.                   && ixmax - ixmin > 3 * xstep
  567.                   && iymax - iymin > 3 * ystep) {
  568.                     /* 640x350 Zoom-In Klooge:  Adjust the
  569.                        Zoom-Box on the initial Zoom-In */
  570.                     if (xdots == 640 && ydots == 350
  571.                       && iymin == 0  && iymax == ydots-1) {
  572.                         iymin -= 5;
  573.                         iymax += 5;
  574.                         }
  575.                     /* 720x512 Zoom-In Klooge:  Adjust the
  576.                        Zoom-Box on the initial Zoom-In */
  577.                     if (xdots == 720 && ydots == 512
  578.                       && iymin == 0  && iymax == ydots-1) {
  579.                         iymin -= 14;
  580.                         iymax += 14;
  581.                         }
  582.                     ixmin += xstep;    ixmax -= xstep;
  583.                     iymin += ystep;    iymax -= ystep;
  584.                     }
  585.                     break;
  586.             case 1081:            /* page down */
  587.                 if (zoomoff == 1
  588.                  && ixmin >= xstep && ixmax < xdots - xstep
  589.                  && iymin >= ystep && iymax < ydots - ystep) {
  590.                     ixmin -= xstep;    ixmax += xstep;
  591.                     iymin -= ystep;    iymax += ystep;
  592.                     }
  593.                     break;
  594.             default:        /* other (maybe a valid Fn key) */
  595.                 if (kbdchar >= 1059 && kbdchar < 1069
  596.                  && kbdchar < 1059 + maxvideomode) {
  597.                     adapter = kbdchar - 1059;
  598.                     kbdmore = 0;
  599.                     }
  600.                 else if (kbdchar >= 1084 && kbdchar < 1114
  601.                  && kbdchar < 1074 + maxvideomode) {
  602.                     adapter = kbdchar - 1074;
  603.                     kbdmore = 0;
  604.                     }
  605.                 else if (kbdchar >= 1120 && kbdchar < 1130
  606.                  && kbdchar < 1080 + maxvideomode) {
  607.                     adapter = kbdchar - 1080;
  608.                     kbdmore = 0;
  609.                     }
  610.                 else
  611.                     continue;
  612.                 break;
  613.             }
  614.  
  615.         if (zoomoff == 1 && kbdmore == 1) {    /* draw a zoom box? */
  616.             drawbox();            /* (yup) */
  617.             }
  618.         }
  619.  
  620.     }
  621.  
  622. setvideomode(3,0,0,0);            /* all done.  return to text mode. */
  623. exit(0);
  624.  
  625. }
  626.