home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 239_01 / clairol.c < prev    next >
Text File  |  1987-07-30  |  12KB  |  444 lines

  1.  
  2.  
  3. #include <setjmp.h>
  4. #include <signal.h>
  5. #include "ciao.h"
  6.  
  7.  
  8. /*
  9. **  clairol()  - modify screen colors or monochrome attributes "on the fly"
  10. **               popout window, updates previous screen on exit
  11. **               to reflect the newly selected values
  12. **
  13. **               returns on Control-C, resets to SIG_DFL, restores screen
  14. */
  15.  
  16.      /* Note:  Users who select a PLAIN screen create ambiguity */
  17.      /*        between the various message levels.  The NEXT    */
  18.      /*        time clairol() is called, the ambiguous colors   */
  19.      /*        default to the lower message level.  For example */
  20.      /*        if Normal and Bold have the same value on entry, */
  21.      /*        and the user changes the value of EITHER, BOTH   */
  22.      /*        Normal and Bold bytes in the screen buffer will  */
  23.      /*        be reset to the NEW NORMAL value.  This is       */
  24.      /*        because INFORMATION HAS BEEN LOST concerning the */
  25.      /*        meaning of the message levels, in the step where */
  26.      /*        user selected a PLAIN screen.                    */
  27.      /*                                                         */
  28.      /*        You should test the ambiguity flag on exit from  */
  29.      /*        clairol(), and take whatever corrective action   */
  30.      /*        is needed thereafter.                            */
  31.      /*                                                         */
  32.      /*        In cases where your program cannot tolerate the  */
  33.      /*        ambiguity a user MIGHT create (the possibility   */
  34.      /*        is there!), you should use video registers 4     */
  35.      /*        through 15, which clairol() does not alter, and  */
  36.      /*        to which users have no access; or else simply    */
  37.      /*        don't call clairol()...!  Clairol() gives the    */
  38.      /*        user permission to change things you may not     */
  39.      /*        want to be changed, in other words.              */
  40.  
  41.  
  42. #define MONOCHROME 7
  43.  
  44. int ambiguity = 0;
  45.  
  46. static void test_ambiguity()
  47. {
  48.      register int i, j;
  49.  
  50.      for ( ambiguity = i = 0; i < 3; i++ )
  51.      {
  52.          for ( j = i + 1; j < 4; j++ )
  53.          {
  54.              ambiguity |= vid[i] == vid[j]; 
  55.          }
  56.      }
  57. }
  58.  
  59.  
  60.  
  61. static jmp_buf remark;
  62. static int ch, tx, ty, which, eaSave, edSave, icon, flipflop,
  63.            nrmSave, bldSave, empSave, ntcSave;
  64.  
  65.  
  66. static void ControlC()
  67. {
  68.       longjmp(remark,-1); 
  69. }
  70.  
  71.  
  72. static void valSave()
  73. {
  74.       test_ambiguity();         /* detect plain screen */
  75.  
  76.       nrmSave = vid[0] & 0xFF;  /* normal       Vid_init() defines only these */
  77.       bldSave = vid[1] & 0xFF;  /* bold         four values for color text.   */
  78.       empSave = vid[2] & 0xFF;  /* emphasis     Programs may alter all 16     */
  79.       ntcSave = vid[3] & 0xFF;  /* notice       values of vid[], of course.   */
  80.  
  81.       eaSave  = vid[10] & 0xFF;
  82.       edSave  = vid[13] & 0xFF;
  83.       vid[10] = 0x0F;
  84.       vid[13] = 0x07;
  85. }
  86.  
  87.  
  88. static void reset()
  89. {
  90.       setwindow( tx, ty, tx + 3, ty + 5 );
  91.       wputs("^φ");
  92.       clrwindow();
  93.       setwindow( tx, ty, tx + 14, ty + 5 );
  94.       gotoxy(4,1);
  95.       wputs("^0Normal    ^φ");
  96.       gotoxy(4,2);
  97.       wputs("^1Bold      ^φ");
  98.       gotoxy(4,3);
  99.       wputs("^2Emphasis  ^φ");
  100.       gotoxy(4,4);
  101.       wputs("^3Attention!^φ");
  102. }
  103.  
  104.  
  105. static void position( line ) int line;
  106. {
  107.       reset();
  108.       gotoxy( 1,0 + line );
  109.       wink( 24 );
  110.       gotoxy( 2,1 + line );
  111.       wink( 26 );
  112.       gotoxy( 1,2 + line );
  113.       wink( 25 );
  114.       gotoxy( 0,1 + line );
  115.       wink( 27 );
  116.       gotoxy( 1,1 + line );
  117.  
  118.       wprintf("^Ω%c^φ",icon);;
  119. }
  120.  
  121.  
  122. static void normPos()
  123. {
  124.       position(0);
  125. }
  126.  
  127.  
  128. static void boldPos()
  129. {
  130.       position(1);
  131. }
  132.  
  133.  
  134. static void emphPos()
  135. {
  136.       position(2);
  137. }
  138.  
  139.  
  140. static void notePos()
  141. {
  142.       position(3);
  143. }
  144.  
  145.  
  146. static void pause()
  147. {
  148.       register int n;
  149.       for (n = 380; n; n--) if (kbhit()) break;
  150. }
  151.  
  152.  
  153. static void waitforuser()
  154. {
  155.       int flag;
  156.       flag = 0;
  157.       while (1)
  158.       {
  159.           icon = flag? 'K':'?'; normPos(); pause();
  160.           icon = flag? 'E':'A'; boldPos(); pause();
  161.           icon = flag? 'Y':'N'; emphPos(); pause();
  162.           icon = flag?  19:'Y'; notePos(); pause();
  163.           if (kbhit()) break;
  164.           else flag ^= 1;
  165.       }
  166.       while (kbhit()) getch();
  167.       icon = '?';
  168. }
  169.  
  170.  
  171. static void help()
  172. {
  173.       int k;
  174.       static char *p, *msg[] = { "re", "ob", "in" };
  175.  
  176.       if (vid_mode == MONOCHROME) p = msg[0]; /* absolute */
  177.       else p = flipflop? msg[1]: msg[2];
  178.  
  179.       wputs("^φ");
  180.       clrwindow();
  181.       wputs("^ΩF10^φ  help\n");
  182.       wprintf("^Ω%c%c%c%c^φ select\n",27,24,25,26);
  183.       wputs("^ΩF1^φ   bright\n");
  184.       wputs("^ΩF2^φ   blink\n");
  185.       wprintf("^ΩF9^φ   %sverse\n", p);
  186.       wputs("^ΩESC^φ  done!");
  187.       for (k = 20; k; k-- ) pause();
  188.       if (kbhit()) ch = keyin( noop ); else ch = '?';
  189.       clrwindow();
  190. }
  191.  
  192.  
  193.  
  194.  
  195. /*  The Monochrome Adapter case is simple... */
  196.  
  197.  
  198. static void mono()
  199. {
  200.       int ix, hibyte, lobyte, hibit, lobit;
  201.  
  202.       ix = which;
  203.       lobyte = vid[ ix ] & 0x07;  /* foreground color? */
  204.  
  205.       /* preserve status of blink and bright bits */
  206.  
  207.       lobit  = vid[ ix ] & 0x08;  /* intensity bit?    */
  208.       hibit  = vid[ ix ] & 0x80;  /* blink bit?        */
  209.  
  210.       hibyte = 0;
  211.       if (lobyte == 0) /* turn off reverse, turn on underline */
  212.       {
  213.              lobyte = 0x01;
  214.       }
  215.       else if (lobyte == 1) /* turn off underline, turn on normal */
  216.       {
  217.              lobyte = 0x07;
  218.       }
  219.       else /* turn off normal, turn on reverse */
  220.       {
  221.              lobyte = 0x00;
  222.              hibyte = 0x70;
  223.       }
  224.  
  225.       vid[ ix ] = hibyte | hibit | lobyte | lobit;
  226. }
  227.  
  228.  
  229.  
  230. /* The Color/Graphics Adapter case is even simpler...! */
  231.  
  232.  
  233. static void cgaright()
  234. {
  235.       int ix, hibyte, lobyte, hibit, lobit;
  236.  
  237.       ix = which;
  238.       lobyte = vid[ ix ] & 0x07;  /* foreground color? */
  239.       hibyte = vid[ ix ] & 0x70;  /* background color? */
  240.  
  241.       /* preserve status of blink and bright bits */
  242.  
  243.       lobit  = vid[ ix ] & 0x08;  /* intensity bit?    */
  244.       hibit  = vid[ ix ] & 0x80;  /* blink bit?        */
  245.  
  246.       if (flipflop)
  247.       {
  248.           hibyte += 0x10;
  249.           if (hibyte > 0x70) hibyte = 0;
  250.       }
  251.       else
  252.       {
  253.           ++lobyte;
  254.           if (lobyte > 7) lobyte = 0;
  255.       }
  256.       vid[ ix ] = hibyte | hibit | lobyte | lobit;
  257. }
  258.  
  259.  
  260. static void cgaleft()
  261. {
  262.       int ix, hibyte, lobyte, hibit, lobit;
  263.  
  264.       ix = which;
  265.       lobyte = vid[ ix ] & 0x07;  /* foreground color? */
  266.       hibyte = vid[ ix ] & 0x70;  /* background color? */
  267.  
  268.       /* preserve status of blink and bright bits */
  269.  
  270.       lobit  = vid[ ix ] & 0x08;  /* intensity bit?    */
  271.       hibit  = vid[ ix ] & 0x80;  /* blink bit?        */
  272.  
  273.       if (flipflop)
  274.       {
  275.           hibyte -= 0x10;
  276.           if (hibyte < 0) hibyte = 0x70;
  277.       }
  278.       else
  279.       {
  280.           --lobyte;
  281.           if (lobyte < 0) lobyte = 7;
  282.       }
  283.       vid[ ix ] = hibyte | hibit | lobyte | lobit;
  284. }
  285.  
  286.  
  287.  
  288.  
  289. static void inquire()
  290. {
  291.       unsigned bl, bt, flip;
  292.  
  293.       flipflop = which = 0;
  294.       while (ch != 27)
  295.       {
  296.             position( which );
  297.             ch = keyin( noop );
  298.             switch ( ch )
  299.             {
  300.                case  27:
  301.                {
  302.                     return;
  303.                }
  304.                case 187:   /* F1?  bright */
  305.                {
  306.                     vid[ which ] ^= 0x08;  /* toggle intensity bit */
  307.                     break;
  308.                }
  309.                case 188:   /* F2?  blink */
  310.                {
  311.                     vid[ which ] ^= 0x80;  /* toggle blink bit */
  312.                     break;
  313.                }
  314.                case 195:   /* F9?  reverse, or obverse/inverse */
  315.                {
  316.                     if (vid_mode == MONOCHROME)
  317.                     {
  318.                          flip = vid[ which ] & 0x07;  /* read foreground bits */
  319.                          bl   = vid[ which ] & 0x80;  /* save blink */
  320.                          bt   = vid[ which ] & 0x08;  /* save bright */
  321.                          if (flip)
  322.                          {
  323.                             vid[ which ] = 0x70 | bl | bt;
  324.                          }
  325.                          else
  326.                          {
  327.                             vid[ which ] = 0x07 | bl | bt;
  328.                          }
  329.                     }
  330.                     else
  331.                     {
  332.                          flipflop ^= 1;  /* foreground or background */
  333.                     }
  334.                     icon = (flipflop? 'b':'?');
  335.                     break;
  336.                }
  337.                case 196:   /* F10? */
  338.                {
  339.                     help();
  340.                     break;
  341.                }
  342.                case 200:   /* up arrow?    */
  343.                {
  344.                     if (--which < 0) which = 3;
  345.                     break;
  346.                }
  347.                case 203:   /* left arrow?  */
  348.                {
  349.                     if (vid_mode == MONOCHROME) mono();
  350.                     else cgaleft();
  351.                     break;
  352.                }
  353.                case 205:   /* right arrow? */
  354.                {
  355.                     if (vid_mode == MONOCHROME) mono();
  356.                     else cgaright();
  357.                     break;
  358.                }
  359.                case 208:   /* down arrow?  */
  360.                {
  361.                     if (++which > 3) which = 0;
  362.                     break;
  363.                }
  364.             }
  365.       }
  366. }
  367.  
  368.  
  369. static void set_hues_at( x,y ) int x,y;
  370. {
  371.       tx = x;
  372.       ty = y;
  373.       wputs("^φ");
  374.       windowbox( tx, ty, tx + 14, ty + 5 );
  375.       waitforuser(); 
  376.       help();
  377.       inquire();
  378. }
  379.  
  380.  
  381. static void setnewcolors( p ) char far *p;
  382. {
  383.      static int n, test;
  384.  
  385.      /* on entry, p points to first char in saved screen buffer */
  386.  
  387.      n = 2000;
  388.      while (n--)
  389.      {
  390.            p++;                   /* advance to attribute byte */
  391.            test = *p & 0xFF;      /* read old attribute, kill sign extension */
  392.            if (test == nrmSave)   /* update new attribute as indicated */
  393.            {
  394.                 *p = vid[0];
  395.            }
  396.            else if (test == bldSave)
  397.            {
  398.                 *p = vid[1];
  399.            }
  400.            else if (test == empSave)
  401.            {
  402.                 *p = vid[2];
  403.            }
  404.            else if (test == ntcSave)
  405.            {
  406.                 *p = vid[3];
  407.            }
  408.            p++;                   /* advance to next character */  
  409.      }
  410. }
  411.  
  412.  
  413. void clairol()
  414. {
  415.       char far *screen;
  416.       union REGS x;
  417.  
  418.       valSave();
  419.       screen = savescreen( &x );      /* get copy of original screen */
  420.       hidecursor();
  421.  
  422.       signal(SIGINT,ControlC);
  423.       if (setjmp(remark) != 0 ) 
  424.       {
  425.            vid[0] = nrmSave;          /* recover from user bailout */
  426.            vid[1] = bldSave;
  427.            vid[2] = empSave;
  428.            vid[3] = ntcSave;
  429.       }
  430.       else set_hues_at( 32,8 );
  431.  
  432.       signal(SIGINT,SIG_DFL);
  433.       while (kbhit()) getch();
  434.       vid[10] = eaSave;
  435.       vid[13] = edSave;
  436.       wputs("^0");                  /* set video attribute to new normal */
  437.       setnewcolors( screen );       /* update copy of original screen    */
  438.       restorescreen( screen, &x );  /* restore updated original screen   */
  439. }
  440.  
  441.  
  442. /* eof: clairol.c */
  443.  
  444.