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

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