home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / windows / c / uw260 / uw_tut9.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-24  |  27.2 KB  |  760 lines

  1. /****************************************************************************/
  2. /* UW_TUT9.C                                                                */
  3. /*                                                                          */
  4. /* NOTE: THIS FILE IS PUBLIC DOMAIN AND MAY BE MODIFIED AND USED AT WILL    */
  5. /*                                                                          */
  6. /* In this tutorial we show how easy it is to run in graphics mode, instead */
  7. /* of the 80x25 text mode we have been using.                               */
  8. /*                                                                          */
  9. /*                                                         Dr. Boyd Gafford */
  10. /*                                                         Kevin Huck       */
  11. /*                                                         EnQue Software   */
  12. /*                                                         09/16/92         */
  13. /****************************************************************************/
  14. #include <stdio.h>
  15. #include <fcntl.h>
  16. #include <io.h>
  17. #ifndef __TURBOC__
  18. #include <sys\types.h>
  19. #endif
  20. #include <sys\stat.h>
  21. #include <time.h>
  22. #include <ctype.h>
  23. #include <bios.h>
  24. #ifdef __ZTC__
  25.   #include <fg.h>                         /* include Zortech graphics       */
  26. #else
  27. #ifdef M_I86
  28.   #include <graph.h>                      /* include Microsoft graphics     */
  29. #endif
  30. #endif
  31. #ifdef __TURBOC__
  32.   #include <graphics.h>                   /* include Borland graphics       */
  33. #endif
  34. #include "uw.h"                           /* include the necessary headers  */
  35.  
  36.  
  37. #define MAX_CUST 50
  38.  
  39. typedef struct cust
  40. {
  41.   int status;
  42.   int cust_no;
  43.   char business[34];
  44.   char name[34];
  45.   char addr[34];
  46.   char city[34];
  47.   char state[4];
  48.   char zip[10];
  49.   char phone[16];
  50.   char fax[16];
  51.   char date[10];
  52.   char memo[34];
  53.   char unused[26];                                /* round out to 256 bytes */
  54. } CUST;
  55.  
  56. /*------------------------ global window variables -------------------------*/
  57. WINDOW  Desk_wn, Window1;
  58. CUST    Customers[MAX_CUST];
  59. char    Fname[33];
  60.  
  61. MENU    Top_menu, *Top_mnp = &Top_menu;
  62. MENU    Files_menu, Edit_menu, Print_menu;
  63. MENU    *Drop_mnps[3];
  64.  
  65. PRINT   Print;
  66.  
  67. /*-------------------------------- prototypes ------------------------------*/
  68. void init_g(void);
  69. void end_g(void);
  70. int disp_time(void);
  71. void disp_cust(CUST *cp, WINDOW *wnp);
  72. int file_load(CUST *customers);
  73. int file_save(CUST *customers);
  74. int get_fname(char *fname);
  75. void print_cust(CUST *cp, PRINT *p);
  76. void g_ch( int c, int r, uchar v );
  77.  
  78. /*********/
  79. /* ~main */
  80. /*       ********************************************************************/
  81. /*  Demonstrate data entry capability...                                    */
  82. /****************************************************************************/
  83. int main()
  84. {
  85.   int i, ret_val, cust = 0, end_flag = 0, print_stat = 0;
  86.   WINDOW *wnp;
  87.   CUST *cp;
  88.   uchar back_att  = (LIGHTGRAY << 4) | BLACK,
  89.         bdr_att   = (LIGHTGRAY << 4) | BLACK,
  90.         csr_att   = (CYAN << 4) | YELLOW,
  91.         first_att = (LIGHTGRAY << 4) | RED;
  92.   
  93.   wnp = &Window1;                         /* set local window pointer       */
  94. #ifdef __ZTC__
  95.   force_video(16, 80, 25);                /* force Zortech to EGA mode      */
  96. #else
  97.   init_video(80, 25);                     /* init video for 80 x 25 screen  */
  98. #endif
  99.   init_clock(0x3333);                     /* init clock irq at 91 tics/sec  */
  100.   init_mouse();                           /* init mouse if available        */
  101.   
  102.   init_uw_graphics(640, 350, 14, 14, -1, -1, g_ch);
  103.   init_g();
  104.   
  105.   wn_create(0, 0, V_cols-1, V_rows-1, NO_BDR, WN_NORMAL, &Desk_wn);
  106.   link_window(&Desk_wn);
  107.  
  108.   /*------------------------ create the menu system ------------------------*/
  109.   Drop_mnps[0] = &Files_menu;
  110.   Drop_mnps[1] = &Edit_menu;
  111.   Drop_mnps[2] = &Print_menu;
  112.  
  113.   menu_create(0, 0, V_cols - 1, 0, M_HORIZONTAL,
  114.               back_att, bdr_att, csr_att, first_att,
  115.               NO_BDR, WN_NORMAL, Top_mnp);
  116.   item_add( "   Files   ", 1, 3, &Top_menu );
  117.   item_add( "   Edit    ", 2, 3, &Top_menu );
  118.   item_add( "   Print   ", 8, 3, &Top_menu );
  119.  
  120.   menu_create(0, 1, 14, 5, M_VERTICAL,
  121.     back_att, bdr_att, csr_att, first_att,
  122.     SGL_BDR, WN_NORMAL, Drop_mnps[0]);
  123.   item_add( " Load File", 4, 1, &Files_menu );
  124.   item_add( " Save File", 5, 1, &Files_menu );
  125.   item_add( "   Quit   ", 3, 3, &Files_menu );
  126.  
  127.   menu_create(11, 1, 32, 4, M_VERTICAL,
  128.     back_att, bdr_att, csr_att, first_att,
  129.     SGL_BDR, WN_NORMAL, Drop_mnps[1]);
  130.   item_add( " Clear Current", 6, 7, &Edit_menu );
  131.   item_add( " Clear All    ", 7, 7, &Edit_menu );
  132.  
  133.   menu_create(22, 1, 43, 4, M_VERTICAL,
  134.     back_att, bdr_att, csr_att, first_att,
  135.     SGL_BDR, WN_NORMAL, Drop_mnps[2]);
  136.   item_add( " Print Current", 9, 7, &Print_menu );
  137.   item_add( " Print All    ", 10, 7, &Print_menu );
  138.  
  139.   set_idle_func(disp_time);               /* set background clock function  */
  140.  
  141.   wn_create(5, 5, 75, 20, SLD_BDR, WN_POPUP, wnp);
  142.   wn_color(YELLOW, BLUE, wnp);            /* change the window colors       */
  143.   wn_bdr_color(WHITE, BLUE, wnp);         /* change the border's colors     */
  144.   link_window(wnp);
  145.  
  146.   /*------------- initialize first customer as EnQue Software --------------*/
  147.   cp = &Customers[0];
  148.   strcpy(cp->business, "EnQue Software"); 
  149.   strcpy(cp->name, "Kevin Huck & Boyd Gafford");  
  150.   strcpy(cp->addr, "Rt. 1 Box 116C"); 
  151.   strcpy(cp->city, "Pleasant Hill");  
  152.   strcpy(cp->state, "MO");  
  153.   strcpy(cp->zip, "64080"); 
  154.   strcpy(cp->phone, "(816)987-2515"); 
  155.   strcpy(cp->fax, "(816)987-2515");      
  156.   strcpy(cp->date, "09/11/92");      
  157.   strcpy(cp->memo, "BBS 816-353-0991"); 
  158.  
  159.   /*------------------------ initialize the printer ------------------------*/
  160.   if( init_printer("LPT1", NULL, 2048L, 2048L, &Print) )
  161.     print_stat = 1;
  162.  
  163.   Top_mnp->csr_pos = M_MAX_ENTRIES;    /* set to prevent menu from hiliting */
  164.   menu_set(Top_mnp);          /* on entry, since menu is not active until   */
  165.   Top_mnp->csr_pos = 0;       /* Alt-F, Alt-E, or Alt-P is hit              */
  166.  
  167.   wn_color(LIGHTGRAY, RED, &Desk_wn);
  168.   wn_plst(CENTERED, 3, "Use cursor keypad to select customer", &Desk_wn);
  169.   wn_plst(CENTERED, 4, "or click on cursor buttons at bottom of screen", &Desk_wn);
  170.   wn_plst(CENTERED, 22, "<Up> <Dn>  <PgUp> <PgDn>  <Home> <End>", &Desk_wn);
  171.   wn_color(YELLOW, RED, &Desk_wn);
  172.   while(!end_flag)
  173.   {
  174.     cp = &Customers[cust];
  175.     mv_cs(1,1, wnp);
  176.     wn_printf(wnp, "Customer:%3d", cust+1);
  177.     disp_cust(cp, wnp);
  178.     m_show();
  179.     wait_event();
  180.     m_hide();
  181.     if( Event.is_mouse )                            /* process mouse action */
  182.     {
  183.       if( range(0,Event.m_x,11) && (Event.m_y == 0) )
  184.         Event.key = KEY_ALT_F;
  185.       else if( range(11,Event.m_x,22) && (Event.m_y == 0) )
  186.         Event.key = KEY_ALT_E;
  187.       else if( range(22,Event.m_x,33) && (Event.m_y == 0) )
  188.         Event.key = KEY_ALT_P;
  189.  
  190.       else if( range( 7,Event.m_x,47) && (Event.m_y == 9) )
  191.         Event.key = 'B';
  192.       else if( range( 7,Event.m_x,47) && (Event.m_y == 10) )
  193.         Event.key = 'N';
  194.       else if( range( 7,Event.m_x,47) && (Event.m_y == 11) )
  195.         Event.key = 'A';
  196.       else if( range( 7,Event.m_x,47) && (Event.m_y == 12) )
  197.         Event.key = 'C';
  198.       else if( range(50,Event.m_x,59) && (Event.m_y == 12) )
  199.         Event.key = 'S';
  200.       else if( range(61,Event.m_x,71) && (Event.m_y == 12) )
  201.         Event.key = 'Z';
  202.       else if( range( 7,Event.m_x,47) && (Event.m_y == 13) )
  203.         Event.key = 'P';
  204.       else if( range( 7,Event.m_x,47) && (Event.m_y == 14) )
  205.         Event.key = 'F';
  206.       else if( range( 7,Event.m_x,47) && (Event.m_y == 15) )
  207.         Event.key = 'D';
  208.       else if( range( 7,Event.m_x,47) && (Event.m_y == 16) )
  209.         Event.key = 'M';
  210.  
  211.       else if( range( 21,Event.m_x,24) && (Event.m_y == 22) )
  212.         Event.key = KEY_UP;
  213.       else if( range( 26,Event.m_x,29) && (Event.m_y == 22) )
  214.         Event.key = KEY_DN;
  215.       else if( range( 32,Event.m_x,37) && (Event.m_y == 22) )
  216.         Event.key = KEY_PGUP;
  217.       else if( range( 39,Event.m_x,44) && (Event.m_y == 22) )
  218.         Event.key = KEY_PGDN;
  219.       else if( range( 47,Event.m_x,52) && (Event.m_y == 22) )
  220.         Event.key = KEY_HOME;
  221.       else if( range( 54,Event.m_x,58) && (Event.m_y == 22) )
  222.         Event.key = KEY_END;
  223.       else
  224.         Event.key = 0;  
  225.     }
  226.     switch(Event.key)
  227.     {
  228.       /*-------------------------- process menus ---------------------------*/
  229.       case KEY_ALT_Q:                                       /* quit program */
  230.         end_flag = 1;
  231.         break;
  232.       case KEY_ALT_F: case KEY_ALT_E: case KEY_ALT_P:
  233.         m_show();
  234.         if( Event.key == KEY_ALT_F )
  235.           ret_val = menu_system_ll(&Top_menu,&Drop_mnps[0],0,'F',M_EXIT_ON_ESC);
  236.         else if( Event.key == KEY_ALT_E )
  237.           ret_val = menu_system_ll(&Top_menu,&Drop_mnps[0],0,'E',M_EXIT_ON_ESC);
  238.         else
  239.           ret_val = menu_system_ll(&Top_menu,&Drop_mnps[0],0,'P',M_EXIT_ON_ESC);
  240.         switch( ret_val )
  241.         {
  242.           case 3:                                           /* quit program */
  243.             end_flag = 1;
  244.             break;
  245.           case 4:                                           /* load file    */
  246.             file_load(Customers);
  247.             break;
  248.           case 5:                                           /* save file    */
  249.             file_save(Customers);
  250.             break;
  251.           case 6:                                           /* clear one    */
  252.             setmem(cp, sizeof(CUST), 0);
  253.             break;
  254.           case 7:                                           /* clear all    */
  255.             setmem(Customers, sizeof(Customers), 0);
  256.             break;
  257.           case 9:                                           /* print one    */
  258.             if( print_stat )
  259.               print_cust(cp, &Print);
  260.             break;
  261.           case 10:                                          /* print all    */
  262.             if( print_stat )
  263.               for( i = 0; i < MAX_CUST; i++ )
  264.                 if( strlen(Customers[i].name) )             /* not empty?   */
  265.                   print_cust(&Customers[i], &Print);
  266.             break;
  267.         }
  268.         break;
  269.       /*----------------------- process cursor keys ------------------------*/
  270.       case KEY_HOME:
  271.         cust = 0;
  272.         break; 
  273.       case KEY_END:
  274.         cust = MAX_CUST-1;
  275.         break; 
  276.       case KEY_DN: 
  277.         if( cust < MAX_CUST-1 )
  278.           cust++;
  279.         break;
  280.       case KEY_UP: 
  281.         if( cust > 0 )
  282.           cust--;
  283.         break;
  284.       case KEY_PGUP: 
  285.         if( cust >= 10 )
  286.           cust -= 10;
  287.         else
  288.           cust = 0;
  289.         break;
  290.       case KEY_PGDN: 
  291.         if( cust < MAX_CUST-11 )
  292.           cust += 10;
  293.         else
  294.           cust = MAX_CUST-1;
  295.         break;
  296.       /*-------------------- process field edit keys -----------------------*/
  297.       case 'b': case 'B':                         /* get new business name  */
  298.         mv_cs( 11, 3, wnp);
  299.         wn_gets_ll(cp->business, "________________________________",
  300.                                  "********************************",
  301.           swap_nibbles(wnp->att), G_UP_FST_CHAR2 | G_STRIP_END, 32, wnp);
  302.         break;
  303.       case 'n': case 'N':                         /* get new contact name   */
  304.         mv_cs( 11, 4, wnp);
  305.         wn_gets_ll(cp->name, "________________________________",
  306.                              "********************************",
  307.           swap_nibbles(wnp->att), G_UP_FST_CHAR2 | G_STRIP_END, 32, wnp);
  308.         break;
  309.       case 'a': case 'A':                         /* get new address        */
  310.         mv_cs( 11, 5, wnp);
  311.         wn_gets_ll(cp->addr, "________________________________",
  312.                              "********************************",
  313.           swap_nibbles(wnp->att), G_UP_FST_CHAR2 | G_STRIP_END, 32, wnp);
  314.         break;
  315.       case 'c': case 'C':                         /* get new city           */
  316.         mv_cs( 11, 6, wnp);
  317.         wn_gets_ll(cp->city, "________________________________",
  318.                              "********************************",
  319.           swap_nibbles(wnp->att), G_UP_FST_CHAR2 | G_STRIP_END, 32, wnp);
  320.         break;
  321.       case 's': case 'S':                         /* get new state          */
  322.         mv_cs( 51, 6, wnp);
  323.         wn_gets_ll(cp->state, "__", "UU",
  324.           swap_nibbles(wnp->att), G_EXIT_ON_FILL|G_STRIP_END, 2, wnp);
  325.         break;
  326.       case 'z': case 'Z':                         /* get new zip            */
  327.         mv_cs( 60, 6, wnp);
  328.         wn_gets_ll(cp->zip, "_____", "#####",
  329.           swap_nibbles(wnp->att), G_EXIT_ON_FILL|G_STRIP_END, 5, wnp);
  330.         break;
  331.       case 'p': case 'P':                         /* get new phone number   */
  332.         mv_cs( 11, 7, wnp);
  333.         wn_gets_ll(cp->phone, "(___)___-____", " ### ### ####",
  334.           swap_nibbles(wnp->att), G_EXIT_ON_FILL, 14, wnp);
  335.         break;                    
  336.       case 'f': case 'F':                         /* get new fax number     */
  337.         mv_cs( 11, 8, wnp);
  338.         wn_gets_ll(cp->fax, "(___)___-____", " ### ### ####",
  339.           swap_nibbles(wnp->att), G_EXIT_ON_FILL, 14, wnp);
  340.         break;
  341.       case 'd': case 'D':                         /* get new date           */
  342.         mv_cs( 11, 9, wnp);
  343.         wn_gets_ll(cp->date, "__/__/__", "## ## ##", swap_nibbles(wnp->att),
  344.           G_EXIT_ON_FILL, 8, wnp);
  345.         break;
  346.       case 'm': case 'M':                         /* get new memo field     */
  347.         mv_cs( 11, 10, wnp);
  348.         wn_gets_ll(cp->memo, "________________________________",
  349.                              "********************************",
  350.           swap_nibbles(wnp->att), G_STRIP_END, 32, wnp);
  351.         break;
  352.  
  353.     }
  354.   }
  355.  
  356.   unlink_window(wnp);                     /* remove the window from screen  */
  357.   wn_destroy(wnp);
  358.   set_idle_func(NULL);                    /* remove background function     */
  359.   unlink_window(&Desk_wn);                /* remove the window from screen  */
  360.   wn_destroy(&Desk_wn);
  361.   end_clock();
  362.   end_video();                            /* clean up before we exit        */
  363.   end_printer(&Print);
  364.   end_mouse();
  365.   end_g();
  366.   return(1);
  367. }
  368. /*** end of main ***/
  369.  
  370. /**************/
  371. /* ~disp_time */
  372. /*            ***************************************************************/
  373. /*  This routine is called in the background by wait_event and will display */
  374. /*  the time once per second.  Notice the use of the global variables       */
  375. /*  Uw_timers.  There is an array of four "countdown" timers that are user  */
  376. /*  accessible.  Each "timer tic" will decrement the counts by one, until   */
  377. /*  0 is reached.  By "reloading" the timer with "Tics_per_sec", we only    */
  378. /*  display the time of day once per second.  "Tics_per_sec" is set         */
  379. /*  by init_clock.                                                          */
  380. /****************************************************************************/
  381. int disp_time(void)
  382. {
  383.   time_t t;
  384.   print_in_bkgrnd();                            /* call this to print       */
  385.   if( !Uw_timers[0] )                           /* has one second passed?   */
  386.   {
  387.     Uw_timers[0] = Tics_per_sec;                /* if so, reload timer      */
  388.     t = time(NULL);                             /* get time                 */
  389.     mv_cs(55, V_rows-1, &Desk_wn);              /* move window cursor       */
  390.     wn_st_qty(ctime(&t), 24, &Desk_wn);         /* output 24 characters     */
  391.     return(1);
  392.   }
  393.   return(0);
  394. }
  395. /*** end of disp_time ***/
  396.  
  397. /**************/
  398. /* ~disp_cust */
  399. /*            ***************************************************************/
  400. /*  This routine displays a customer in the desired window...               */
  401. /****************************************************************************/
  402. void disp_cust(CUST *cp, WINDOW *wnp)
  403. {
  404.   int r = 3;
  405.  
  406.   mv_cs( 1, r++, wnp );
  407.   wn_printf( wnp, "Business: %-32s", cp->business);
  408.   mv_cs( 1, r++, wnp );
  409.   wn_printf( wnp, "Name    : %-32s", cp->name );
  410.   mv_cs( 1, r++, wnp );
  411.   wn_printf( wnp, "Address : %-32s", cp->addr );
  412.   mv_cs( 1, r++, wnp );
  413.   wn_printf( wnp, "City    : %-32s State: %2s  Zip: %5s",
  414.     cp->city, cp->state, cp->zip );
  415.   wn_cleol(wnp);                                    /* clear to end of line */
  416.   mv_cs( 1, r++, wnp );
  417.   wn_printf( wnp, "Phone   : %-16s", cp->phone );
  418.   mv_cs( 1, r++, wnp );
  419.   wn_printf( wnp, "Fax     : %-16s", cp->fax );
  420.   mv_cs( 1, r++, wnp );
  421.   wn_printf( wnp, "Date    : %-10s", cp->date );
  422.   mv_cs( 1, r++, wnp );
  423.   wn_printf( wnp, "Memo    : %-32s", cp->memo );
  424. }
  425. /*** end of disp_cust ***/
  426.  
  427. /**************/
  428. /* ~file_load */
  429. /*            ***************************************************************/
  430. /*  This routine loads a file from disk into the customer array...          */
  431. /****************************************************************************/
  432. int file_load(CUST *customers)
  433. {
  434.   FILE *fp;
  435.   
  436.   if( get_fname(Fname) )
  437.   {
  438.     if( (fp = fopen(Fname, "rb")) != NULL )
  439.     {
  440.       fread(customers, sizeof(CUST), MAX_CUST, fp);
  441.       fclose(fp);
  442.       tone(1024,10);
  443.       return(1);
  444.     }
  445.   }
  446.   return(0);
  447. }
  448. /*** end of file_load ***/
  449.  
  450. /**************/
  451. /* ~file_save */
  452. /*            ***************************************************************/
  453. /*  This routine saves a file to disk from the customer array...            */
  454. /****************************************************************************/
  455. int file_save(CUST *customers)
  456. {
  457.   FILE *fp;
  458.   
  459.   if( get_fname(Fname) )
  460.   {
  461.     if( (fp = fopen(Fname, "wb")) != NULL )
  462.     {
  463.       fwrite(customers, sizeof(CUST), MAX_CUST, fp);
  464.       fclose(fp);
  465.       tone(1024,10);
  466.       return(1);
  467.     }
  468.   }
  469.   return(0);
  470. }
  471. /*** end of file_load ***/
  472.  
  473. /**************/
  474. /* ~get_fname */
  475. /*            ***************************************************************/
  476. /*  This routine prompts the user for a filename using a popup window...    */
  477. /****************************************************************************/
  478. int get_fname(char *fname)
  479. {
  480.   int ret_val = 1;
  481.   WINDOW wn;
  482.   
  483.   wn_create(20, 8, 60, 10, SLD_BDR, WN_POPUP, &wn);
  484.   wn_set(&wn);
  485.   wn_plst(4, 0, "Enter filename:", &wn);
  486.   if( wn_gets_ll(fname, "____________", "************",
  487.       swap_nibbles(wn.att), G_STRIP_END, 12, &wn) == KEY_ESC )
  488.     ret_val = 0;
  489.   wn_destroy(&wn);
  490.   return(ret_val);
  491. }
  492. /*** end of get_fname ***/
  493.  
  494. /***************/
  495. /* ~print_cust */
  496. /*             **************************************************************/
  497. /*  This routine prints a customer in the desired window...                 */
  498. /****************************************************************************/
  499. void print_cust(CUST *cp, PRINT *p)
  500. {
  501.   print_printf( p, "Business: %-32s\r\n", cp->business);
  502.   print_printf( p, "Name    : %-32s\r\n", cp->name );
  503.   print_printf( p, "Address : %-32s\r\n", cp->addr );
  504.   print_printf( p, "City    : %-32s State: %2s  Zip: %5s\r\n",
  505.     cp->city, cp->state, cp->zip );
  506.   print_printf( p, "Phone   : %-16s\r\n", cp->phone );
  507.   print_printf( p, "Fax     : %-16s\r\n", cp->fax );
  508.   print_printf( p, "Date    : %-10s\r\n", cp->date );
  509.   print_printf( p, "Memo    : %-32s\r\n", cp->memo );
  510.   print_char(12,p);                                     /* print form feed  */
  511. }
  512. /*** end of print_cust ***/
  513.  
  514. /***********/
  515. /* ~init_g */
  516. /*         ******************************************************************/
  517. /*  simple generic init graphics routine...                                 */
  518. /****************************************************************************/
  519. void init_g(void)
  520. {
  521. #ifdef __TURBOC__
  522.   int    g_driver;                          /* the graphics device driver   */
  523.   int    g_mode;                            /* the graphics mode value      */
  524.   int    err_code;                          /* reports any graphics errors  */
  525.  
  526.   registerbgidriver(EGAVGA_driver);
  527.   g_driver = EGA;                           /* request EGA 640x350          */
  528.   g_mode = EGAHI;
  529.   initgraph( &g_driver, &g_mode, "" );
  530.   err_code = graphresult();                 /* read result of init          */
  531.   if( err_code != grOk )
  532.   {                                         /* error during init            */
  533.     printf("Graphics System Error: %s\n", grapherrormsg(err_code));
  534.     exit( 1 );
  535.   }
  536. #endif
  537. #ifdef __ZTC__
  538. #else
  539. #ifdef M_I86
  540.   _setvideomode(_ERESCOLOR);
  541. #endif
  542. #endif
  543. }
  544. /*** end of init_g ***/
  545.  
  546. /**********/
  547. /* ~end_g */
  548. /*        *******************************************************************/
  549. /*  simple generic end graphics routine...                                  */
  550. /****************************************************************************/
  551. void end_g(void)
  552. {
  553. #ifdef __TURBOC__
  554.   closegraph();
  555. #endif
  556. #ifdef __ZTC__
  557. #else
  558. #ifdef M_I86
  559.   _setvideomode(_DEFAULTMODE);
  560. #endif
  561. #endif
  562. }
  563. /*** end of end_g ***/
  564.  
  565. /*------------ now for a sample graphics function that's FAST! -------------*/
  566. #ifdef M_I86
  567. #define asm __asm
  568. #endif
  569. #ifdef __TURBOC__
  570. #pragma inline
  571. #endif
  572.  
  573. /*********/
  574. /* ~g_ch */
  575. /*       ********************************************************************/
  576. /*  This routine writes a character "c" at "x", "y" on an EGA/VGA graphics  */
  577. /*  screen...                                                               */
  578. /*  IMPORTANT: Global data cannot be accessed in this routine past the      */
  579. /*    marked area as the ds register is used to point to the video buffer...*/
  580. /****************************************************************************/
  581. void g_ch( int c, int r, uchar v )
  582. {
  583.     uchar far *s;
  584.     int  bk_flag = 0, fg_flag = 0, bpr;
  585.     bpr = Bytes_per_row;
  586.  
  587.     if( G_opt )
  588.     {
  589.         s = Screen + (r * (V_cols * 2)) + (c * 2);
  590.         if( *s++ == (uchar) v )
  591.         {
  592.             if( *s == (uchar) ((Bkgnd << 4) | Fgnd) )
  593.                 return;
  594.             if( (uchar) (*s & 0x0f) == Fgnd )
  595.                 bk_flag = 1;
  596.             if( (uchar) (*s >> 4) == Bkgnd )
  597.                 fg_flag = 1;
  598.         }
  599.     }
  600.     c = c * 8;                                       /* font must always be 8 bits wide                */
  601.     r = r * Font_spacing;                        /* font heigth is variable                                */
  602.  
  603. #if defined(__TURBOC__) || defined(M_I86)
  604.     asm push di
  605.     asm push si
  606.     asm push ds
  607.  
  608. /*-------------------- calculate first pixel address -----------------------*/
  609.  
  610.     asm mov  ax,r                   /* y address                              */
  611.     asm mov  bx,c                                        /* x address                              */
  612.  
  613.     asm mov  cl,bl                                    /* cl = low-order byte of x                                */
  614.     asm push dx                                            /* preserve dx                                                        */
  615.     asm mov  dx,80                                    /* ax = y * bytes per line                                */
  616.     asm mul  dx
  617.     asm pop  dx
  618.  
  619.     asm shr  bx,1
  620.     asm shr  bx,1
  621.     asm shr  bx,1                                      /* bx = x/8                                                               */
  622.     asm add  bx,ax                                    /* bx = y*bytes per line + x/8                      */
  623.     asm add  bx,Goff                                /* add byte offset into video buffer            */
  624.     asm mov  ax,Gseg                                /* get segment for video buffer                        */
  625.  
  626.     asm mov  es,ax                                    /* es:bx = byte address of pixel                    */
  627.  
  628.     asm push es                                            /* preserve video buffer segment          */
  629.     asm mov  si,bx                                    /* si = video buffer offset               */
  630.  
  631.     asm mov  cx,Font_rows                        /* cx = scan lines for current font       */
  632.     asm mov  bl,Fgnd                                /* get foreground and background colors   */
  633.     asm mov  bh,Bkgnd
  634.     asm push bx                                            /* save them for later                                        */
  635.  
  636. /*-------------- set up character defintion table addressing ---------------*/
  637. /*-------------- CANNNOT USED GLOBAL DATA PAST THIS POINT ------------------*/
  638.  
  639.     asm xor  ax,ax
  640.     asm mov  ds,ax                                    /* ds = absolute zero                     */
  641.  
  642.     asm mov  al,v                                        /* al = character code                    */
  643.     asm mov  bx,43h*4                                /* ds:bx -> int 43h vector                */
  644.     asm les  di,ds:[bx]             /* es:di -> start of character table      */
  645.     asm mul  cl                                            /* ax = offset into char def table        */
  646.                                                                     /* (Font_rows X char code)                */
  647.     asm add  di,ax                                    /* di = address of char def               */
  648.  
  649.     asm pop  bx                                            /* get foreground, background colors            */
  650.     asm pop  ds                                            /* ds:si -> video buffer (from ds)        */
  651.  
  652. /*----------------- set up Graphics Controller registers -------------------*/
  653.  
  654.     asm mov  dx,3CEh                                /* Graphics Controller address reg port   */
  655.  
  656.     asm mov  ax,0A05h                                /* al = Mode register number              */
  657.                                                                     /* ah = Write Mode 2 (bits 0-1)           */
  658.                                                                     /*      Read  Mode 1 (bit  4)             */
  659.     asm out  dx,ax
  660.  
  661.     asm mov  ah,18h                                    /* ah = Read-Modify-Write bits            */
  662.     asm mov  al,0                                        /* al = Data Rotate/Funtion Select reg    */
  663.     asm out  dx,ax
  664.  
  665.     asm mov  ax,0007                                /* ah = Color Don't Care bits             */
  666.                                                                     /* al = Color Don't Cate reg number       */
  667.     asm out  dx,ax                                    /* "don't care" for all bit planes        */
  668.  
  669.  
  670. /*---------------------- output byte aligned character ---------------------*/
  671.     asm shr  cx,1                                        /* output two bytes per loop for speed        */
  672.     asm mov  al,8                                      /* al = Bit Mask register number          */
  673.  
  674.     asm out  dx,al
  675.     asm inc  dx
  676.  
  677.     asm cmp  word ptr bk_flag,1
  678.     asm je   l1
  679.     asm cmp  word ptr fg_flag,1
  680.     asm je   l2
  681.     asm jmp  l3
  682.  
  683. /*---------------------------- background only -----------------------------*/
  684. l1:
  685.     asm mov  ax,es:[di]                            /* ah = pattern for next row of pixels    */
  686.     asm add  di,2                                        /* es:di -> next word in char def table   */
  687.  
  688.     asm not     al
  689.     asm out  dx,al
  690.     asm and  [si],bh                /* update background pixels               */
  691.     asm add  si,bpr
  692.  
  693.     asm mov  al,ah
  694.  
  695.     asm not     al
  696.     asm out  dx,al
  697.     asm and  [si],bh                  /* update background pixels               */
  698.     asm add  si,bpr
  699.     asm loop l1
  700.  
  701.     asm jmp  egaend
  702.  
  703.  
  704. /*----------------------------- foreground only ----------------------------*/
  705. l2:
  706.     asm mov  ax,es:[di]                            /* ah = pattern for next row of pixels    */
  707.     asm add  di,2                                        /* es:di -> next word in char def table   */
  708.  
  709.     asm out  dx,al                                     /* update Bit Mask register               */
  710.     asm and  [si],bl                                /* update foreground pixels               */
  711.     asm add  si,bpr
  712.  
  713.     asm mov  al,ah
  714.  
  715.     asm out  dx,al                                     /* update Bit Mask register               */
  716.     asm and  [si],bl                                /* update foreground pixels               */
  717.     asm add  si,bpr
  718.     asm loop l2
  719.  
  720.     asm jmp egaend
  721.  
  722. /*-------------------------- background & foreground -----------------------*/
  723. l3:
  724.     asm mov  ax,es:[di]                            /* ah = pattern for next row of pixels    */
  725.     asm add  di,2                                        /* es:di -> next word in char def table   */
  726.  
  727.     asm cmp  al,0
  728.     asm je   bkgnd1
  729.     asm out  dx,al                                     /* update Bit Mask register               */
  730.     asm and  [si],bl                                /* update foreground pixels               */
  731. bkgnd1:
  732.     asm not     al
  733.     asm out  dx,al
  734.     asm and  [si],bh                /* update background pixels               */
  735.     asm add  si,bpr
  736.  
  737.     asm mov  al,ah
  738.  
  739.     asm cmp  al,0
  740.     asm je   bkgnd2
  741.     asm out  dx,al                                     /* update Bit Mask register               */
  742.     asm and  [si],bl                                /* update foreground pixels               */
  743. bkgnd2:
  744.     asm not     al
  745.     asm out  dx,al
  746.     asm and  [si],bh                /* update background pixels               */
  747.     asm add  si,bpr
  748.     asm loop l3
  749.  
  750. egaend:
  751.     asm pop  ds
  752.     asm pop  si
  753.     asm pop  di
  754. #endif
  755.     return;
  756. }
  757. /*** end of g_ch **/
  758.  
  759. /*** END OF FILE ***/
  760.