/* program to output cursor pos. and intensity etc to file

to run, type:

landg [-x<file size> -l<scale factor> -d( no dither )
                                             <intensity file> <lightness file>] 

or just landg and use the menu

to output info to file : select 'menu' then 'both' */

#include <graph.h>
#include <stdio.h>
#include <signal.h>
#include "az:plane.h"
#include "az:general.h"

#define Y_BASE  75             /* baseline for image and histogram */
#define X_SIDE  50             /* left side of disp. square */

#define MENU 1                 /* for region option */
#define INTENSITY 2            /* for region option */
#define LIGHTNESS 3            /* for region option */
#define BOTH 4                 /* for region option */


char reg_label[5][20] = { "",            /* labels for region */
                          "   menu",
                          "intensity",
                          "lightness",
                          "   both"
                        };

char inv_reg_log[ 5 ] = { FALSE,/*  determines if reg_box is in inverse video */
                          FALSE,   /* menu */
                          FALSE,   /* intensity */
                          FALSE,  /* lightness */
                          TRUE   /* both */
                        };

char menu_flag;      /* true if main menu active */
char move_flag;      /* true if text line cleared when cursor moved */
char hist_flag;      /* true if histogram required */
char int_flag;       /* if true intensity sampled, else lightness sampled */
char both_flag;      /* if true intensity and lightness sampled */
char dith_flag;      /* true if dither required */
char larg_flag;      /* true if expanded display required */

unsigned short fontbuf[FONTSIZE];	/* buffer for largest expected font */
char *fontname = "fmacs:font.visual";
int l, h, w;

int grey;               /* current grey level for text & information regions */

int xl_menu;              /* left x for menu region */
int xr_menu;              /* right x for menu region */
int y_menu;               /* base y for menu region */
int box[ 10 ];            /* y values for menu box */
int nop;                  /* no. of options for menu */

char label[ 10 ][ 40 ] = { "",              /* labels for menu */
                           "        quit",                     /* 1 */
                           "  clear main menu",                /* 2 */
                           "   clear screen",                  /* 3 */
                           " histogram on/off",                /* 4 */
                           "   dither on/off",                 /* 5 */
                           "read lightness file",              /* 7 */
                           "read intensity file"               /* 8 */
                          };

FILE *fp, *flog;

int size_file = 0;            /* size of file */
int size = 0;                 /* size of image */
int scale_size = 1;      /* enlargement factor for displaying image, reduction
                            factor when writing out image */

char int_array[ 256 * 256 ];  /* intensity array */
char lig_array[ 256 * 256 ];  /* lightness array */

int xl_int;            /* x of origin for intensity histogram */
int xl_lig;            /* x of origin for lightness histogram */
int xr_int;            /* x for end of intensity histogram x axis */
int xr_lig;            /* x for end of lightness histogram x axis */
int x_bar_int;         /* x position of intensity histogram bar */
int x_bar_lig;         /* x position of lightness histogram bar */
int hist_space;        /* spacing between histogram axes and bar */

void region();

void read_array();

void sample(), draw_cursor(), clear_cursor(), plot_curs();

void shift();
int intensity(), lightness();

void menu(), setup_menu();
void draw_menu(), draw_box(), clear_box(), clear_menu();
int in_box();

void setup_hist(), draw_hist(), draw_bar(), redraw_bars(), reset(),clear_hist();
extern stop();
char write_file();

main(argc,argv)
char **argv;
int argc;
{
   char header_flag = TRUE; /* true if file contains header */
   char arg_flag = FALSE;   /* true if command line arguments given */
   char c;


   signal( SIGINT, stop );

   dith_flag = TRUE;         /* FLAG DEFAULTS */
   larg_flag = FALSE;

   if ( argc > 1 ) { /* command line arguments given */
      argv++;
      arg_flag = TRUE;

      while( ( argc > 0 ) && ( (*argv)[0] == '-' ) )
      {
         switch( (*argv)[1] ) {

            case 'x':
               sscanf( *argv + 2, "%d", &size_file);
               header_flag = FALSE;
               break;

            case 'd':      /* no dither */
               dith_flag = FALSE;
               break;

            case 'l': 
               larg_flag = TRUE;
               sscanf( *argv+2, "%d", &scale_size );
               break;

            default:
               error( "bad option");
               break;
         } 
  
         argc--;
         argv++;
      }               
   }       

   l = readfont(fontname, fontbuf, FONTSIZE, &h, &w);

   grey = P_WHITE;

   offset(0,0);
   sterm( 5 );

   setup_map();
   clear_screen();
   setup_text();
   setup_menu();

   /* default - intensity & menu on */

   hist_flag = TRUE;          /*   DEFAULT VALUES  */
   int_flag = FALSE;
   menu_flag = FALSE;  
   both_flag = TRUE;

   setup_hist();

   if ( arg_flag ) {
      menu_flag = FALSE;         /* menu off */
      inv_reg_log[ MENU ] = FALSE;
      hist_flag = TRUE;
   }

   draw_region( grey );

   if ( --argc> 0 ) /* open intensity file if any */
   {
      if ( ( fp = fopen( *(argv++), "r" ) ) == NULL )
      {
         putchar( BEEP );
         error( "can't open picture file" );
      }
      else      /* read and display intensity file */
      {
         if ( header_flag )
            size_file = getc( fp ) & 0377;
       
            display( X_SIDE, Y_BASE, int_array, FALSE );
      }
   }

   if ( --argc> 0 ) /* open intensity file if any */
   {
      if ( ( fp = fopen( *(argv++), "r" ) ) == NULL )
      {
         putchar( BEEP );
         error( "can't open lightness file");
      }
      else      /* read lightness file into array image */
      {
         /* assume there is no header */

         read_array( lig_array );    
      }
   }


   if ( arg_flag ) {   /* to avoid error with command line arg  */
      write_text( "press return to continue " ); /* if command file not used */
      if ( ( c = getchar() ) == EOF )
         clearerr( stdin );  /* clear buffer */
   }

   if ( arg_flag ) {
      clear_text();
      grey = DIM;
      draw_region( grey );
   }

   if ( menu_flag )
      draw_menu();

   if ( hist_flag )
      draw_hist();

   region();
}



void region() /*  middle Mouse Button ( MB ) selects option */
{
   int option;
   int x = 470;  /* initial position for cursor */
   int y = 360;
   char exit_region_flag = FALSE;

   int xb = 325;
   int yb = Y_BASE + 200;
   int int_b = 0;      /* intensity at cyam cursor */
   int lig_b = 0;      /* lightness at cyam cursor */

   int xr = 325;
   int yr = Y_BASE + 100;
   int int_r = 0;      /* intensity at red cursor */
   int lig_r = 0;      /* lightness at red cursor */

   while ( !exit_region_flag )  { 

      enable( P_GREEN );
      cursor( 0, &x, &y);
      if ( (mouse->b & 0377) == 2 ) {

         if ( option = in_reg_box( x, y) ) {
         
            switch ( option ) {

               case 1 :                      /* menu */
                  if ( !menu_flag) {
                     grey = P_WHITE;
                     inv_reg_log[ MENU ] = TRUE;
                     draw_region( grey );  /* since changing grey level */
                     draw_menu();
                     menu_flag = TRUE;
                  }
                  break;

               case 2 :                      /* intensity */  

                  if ( menu_flag ) { /* clear menu & redraw region DIM */  
                     if ( !int_flag || both_flag ) { 
                        int_flag = TRUE;
                        both_flag = FALSE;
                        inv_reg_log[ INTENSITY ] = TRUE;   /* intensity */
                        inv_reg_log[ LIGHTNESS ] = FALSE;  /* lightness */
                        inv_reg_log[ BOTH ] =      FALSE;  /* both */
                     }
                     reset( x, y, xb, yb, &int_b, &lig_b, 
                                  xr, yr, &int_r, &lig_r );
                  }

                  if ( !int_flag || both_flag ) {
                     if ( both_flag ) {
                        both_flag = FALSE;
                        draw_inv_reg( BOTH, grey );
                     }
                     else
                        draw_inv_reg( LIGHTNESS, grey );

                     int_flag = TRUE;
                     draw_inv_reg( INTENSITY, grey );
                     setup_hist();                    /* change axes */

                     if ( hist_flag ) {               /* draw histograms */
                        draw_hist();
                        if ( !menu_flag )
                           redraw_bars( xb, yb, &int_b, &lig_b,
                                        xr, yr, &int_r, &lig_r );
                        else
                           draw_menu();
                     }
                  }
                  break;

               case 3 :                      /* lightness */

                  if ( menu_flag ) { /* clear menu & redraw region DIM */  
                     if ( !int_flag || both_flag ) { 
                        int_flag = FALSE;
                        both_flag = FALSE;
                        inv_reg_log[ MENU ] =      FALSE;  /* menu */
                        inv_reg_log[ INTENSITY ] = FALSE;  /* intensity */
                        inv_reg_log[ LIGHTNESS ] = TRUE;   /* lightness */
                        inv_reg_log[ BOTH ] =      FALSE;  /* both */
                     }
                     reset( x, y, xb, yb, &int_b, &lig_b, 
                                  xr, yr, &int_r, &lig_r );
                  }

                  if ( int_flag || both_flag ) {
                     if ( both_flag ) {
                        both_flag = FALSE;
                        draw_inv_reg( BOTH, grey );
                     }
                     else
                        draw_inv_reg( INTENSITY, grey );

                     int_flag = FALSE;
                     draw_inv_reg( LIGHTNESS, grey );
                     setup_hist();                   /* change axes */

                     if ( hist_flag ) {              /* draw histogram */
                        draw_hist();
                        if ( !menu_flag )
                           redraw_bars( xb, yb, &int_b, &lig_b,
                                        xr, yr, &int_r, &lig_r );
                        else
                           draw_menu();
                     }
                  }
                  break;
      
               case 4 :                      /* both */

                  if ( menu_flag ) { /* clear menu & redraw region DIM */  
                     if ( !int_flag || both_flag ) { 
                        both_flag = TRUE;
                        inv_reg_log[ BOTH ] =      TRUE;  /* both */
                     }
                     reset( x, y, xb, yb, &int_b, &lig_b, 
                                  xr, yr, &int_r, &lig_r );


                     grey = P_WHITE;
                     if ( write_file() )
                     {
                     fprintf( flog, "%d   %d   %d   %d\n", xb, yb, int_b, lig_b);
                     fprintf( flog, "%d   %d   %d   %d\n", xr, yr, int_r, lig_r);
                        fclose( flog );
                        write_text( "file written" );
                     }
                     move_flag = TRUE;
                     grey = DIM;

                  }

                  if ( !both_flag ) {

                     if ( int_flag )
                        draw_inv_reg( INTENSITY, grey );
                     else
                        draw_inv_reg( LIGHTNESS, grey );
                     
                     both_flag = TRUE;
                     draw_inv_reg( BOTH, grey );
                     setup_hist();                   /* change axes */

                     if ( hist_flag ) {              /* draw histograms */
                        draw_hist();
                        if ( !menu_flag )
                           redraw_bars( xb, yb, &int_b, &lig_b,
                                        xr, yr, &int_r, &lig_r );
                        else
                           draw_menu();
                     }
                  }
                  break;


               case 5 :                      /* cyam cursor */

                  if ( menu_flag )
                     reset( x, y, xb, yb, &int_b, &lig_b, 
                                  xr, yr, &int_r, &lig_r );

                  x_bar_int = xl_int + hist_space;
                  x_bar_lig = xl_lig + hist_space;
                  enable(P_CYAM);
                  sample( &xb, &yb, &int_b, &lig_b );
                  break;

               case 6 :                      /* red cursor */

                  if ( menu_flag )
                     reset( x, y, xb, yb, &int_b, &lig_b, 
                                  xr, yr, &int_r, &lig_r );

                  x_bar_int = xl_int + hist_space + 50;
                  x_bar_lig = xl_lig + hist_space + 55;
                  enable(P_RED);
                  sample( &xr, &yr, &int_r, &lig_r );
                  break;

               default:
                  break;
            }

         } 
         else if ( ( menu_flag ) && ( option = in_box( x, y) ) ) {
            
            menu( option );       

            /* draw cursor - while button held */

            enable( P_GREEN );
            draw_cross( x, y); 

            if ( !menu_flag ) /* clear menu, redraw histogram & region DIM */
               reset( x, y, xb, yb, &int_b, &lig_b, 
                            xr, yr, &int_r, &lig_r );
         }     
      } 
      while ( mouse->b == 2 ) /* pause until button released */
         ;
   } /* end of while */  
}  /* end of function */

/* ******************** MOUSE & CURSOR FUNCTIONS *********************** */

void sample( px, py, pint, plig ) /* while mouse->b = 2 cursor moved & displayed
                          intensity and/or lightness calculated and displayed */
                          /* current position is (px,py), intensity = pi */
int *px, *py, *pint, *plig;
{
int old_x, old_y, old_int, old_lig, x_offset, y_offset;

   old_x = *px;   /* stores current position */
   old_y = *py;
   old_int = *pint;   /* stores current intensity */
   old_lig = *plig;   /* stores current lightness */

   /* calculate offset between mouse position and current position */
   x_offset = SCALE( mouse->x ) - old_x;
   y_offset = SCALE( mouse->y ) - old_y;

   while ( (mouse->b & 0377) == 2 ) {

      *px = SCALE( mouse->x ) - x_offset;        /* new position */
      *py = SCALE( mouse->y ) - y_offset; 
      limit( px, py);                      /* restricts cursor to screen */

      draw_cursor( *px, *py);              /* draw cursor at new position */

      if ( (*px != old_x) || (*py != old_y) ) { /* erase old cursor position */
         clear_cursor( old_x, old_y);

         /* calc and display intensity and lightness */

         if ( hist_flag && !menu_flag ) {
            if ( !both_flag ) {

               if ( int_flag ) {                  /* intensity */
                  *pint = intensity( *px, *py);
                  draw_bar( *pint, old_int );
               }
               else {                             /* lightness */   
                  *plig = lightness( *px, *py);
                  draw_bar( *plig, old_lig );
               }
            }
            else {                                /* both */
               int_flag = TRUE;
               *pint = intensity( *px, *py);
               draw_bar( *pint, old_int );
               int_flag = FALSE;
               *plig = lightness( *px, *py);
               draw_bar( *plig, old_lig );
            }
         }

         old_x = *px;
         old_y = *py;
         old_int = *pint;
         old_lig = *plig;
      }
   }
}

         
void draw_cursor( x, y) /* draws cursor */
int x, y;
{
   colour( P_COL );
   plot_curs( x, y);
}

void clear_cursor( x, y) /* clears cursor */
int x, y;
{
   colour( BLACK );
   plot_curs( x, y);
}



void plot_curs( x, y) /* draws cursor shape */
int x, y;
{
int i;

   /* vertical lines */

   line( x, y - 11, x, y - 4 );
   line( x, y + 4, x, y + 11 );

   /* horizontal lines */

   hline( x - 11, x - 4, y );
   hline( x + 4, x + 11, y );
}


/* ************************** MENU FUNCTIONS ******************************* */

void menu( option ) /*  selects option */
int option;
{

   switch ( option ) {

      case 1 :                      /* quit */
         clear_screen();
         exit( 0 );                     
         break;

      case 2 :                      /* clear main menu */  
         menu_flag = FALSE;
         break;

      case 3 :                      /* clear screen */
         clear_screen();
         if ( hist_flag )
            draw_hist();
         draw_menu();
         draw_region( grey );
         break;
      
      case 4 :                      /* histogram on/off */
         hist_flag = !hist_flag;
         if ( hist_flag ) {
            write_text( "histogram on" );
            draw_hist();
            draw_menu();
         }
         else {
            write_text( "histogram off" );
            clear_hist();
            draw_menu();
         }
         move_flag = TRUE;
         break;

      case 5 :                      /* dither on/off */
         dith_flag = !dith_flag;
         if ( dith_flag )
            write_text( "dither on" );
         else
            write_text( "dither off" );
         move_flag = TRUE;
         break;

      case 6 :                      /* read lightness file */
         if ( read_file() ) {
            read_array( lig_array );
         }
         move_flag = TRUE;
         break;

      case 7 :                      /* read intensity file */
         if ( read_file() ) {
            display( X_SIDE, Y_BASE, int_array, FALSE );
         }
         move_flag = TRUE;
         break;

      default:
         break;
   }

} 


void setup_menu() /* initialises variables and box array */
{
   int ht_box, i;

   xl_menu = 485;
   xr_menu = 680;
   y_menu = 100;
   nop = 7;
   ht_box = 30;

   /* define box regions */
    
   for ( i = 0; i < nop + 1; i++) 
      box[ i ] = y_menu + ht_box * i;
}

void draw_menu() /* draws menu */
{
   int base, top;
   int i, y;
   char *text;
   int x_text;

   base = y_menu;
   top = box[ nop ] ;
   x_text = xl_menu + 15;

   /* draw and label menu region */

   clear_menu();
   enable( P_GREY );
   colour( grey );

   /* draw region */

   hline( xl_menu, xr_menu, base);
   hline( xl_menu, xr_menu, top);
   line( xl_menu, base, xl_menu, top);
   line( xr_menu, base, xr_menu, top);

   /* write labels */

   for ( i = 1; i < nop + 1; i++) {
      y = (( box[ i - 1 ] + box[ i ] ) / 2) - 5;
      text = label[i];
      setpos( x_text, y);
      while (*text) gputc(*text++);
   }

   /* draw line for text region */

   hline( 0, XPIXELS, YPIXELS - h - 3 );

}      


int in_box( x, y) /* returns box no. if box inside menu region, else FALSE */ 
int x, y;
{
   int option;
   int bottom, top;

   bottom = box[ 0 ];
   top = box[ nop ];

   /* check if mouse inside region */

   if ( ( x >= xl_menu ) && ( x <= xr_menu ) && 
        ( y >= bottom ) && ( y <= top ) ) {
      
      option = 0;
      do
         option = option + 1;
      while ( y > box[ option ] );
      return( option );
   }
   else
      return( FALSE );
}

void draw_box( option ) /* draws menu box[ option ] */
int option;
{
   int xl, xr, base, top;

   xl = xl_menu + 1;
   xr = xr_menu - 1;
   base = box[ option - 1 ] + 1;
   top = box[ option ] - 1;

   enable( P_GREY );
   colour( DIM );

   hline( xl, xr, base );
   hline( xl, xr, top );
   line( xl, base, xl, top );
   line( xr, base, xr, top );
}

void clear_box( option ) /* clears menu box[ option ] */
int option;
{
   int xl, xr, base, top;

   xl = xl_menu + 1;
   xr = xr_menu - 1;
   base = box[ option - 1 ] + 1;
   top = box[ option ] - 1;

   enable( P_GREY );
   colour( BLACK );

   hline( xl, xr, base );
   hline( xl, xr, top );
   line( xl, base, xl, top );
   line( xr, base, xr, top );
}

void clear_menu() /* clears menu region */
{
   int base, top;

   base = box[ 0 ];
   top = box[ nop ];

   enable( P_ALL );
   colour( BLACK );

   fill( xl_menu, base, xr_menu, top);

   /* clear text line */

   hline( 0, XPIXELS, YPIXELS - h - 3 );
}


/* ********************* INTENSITY & LIGHTNESS FUNCTIONS ******************** */

void shift( x, y, px_image, py_image) /* changes from screen origin to display
                                    image origin */
int x, y;
int *px_image, *py_image;
{
   *px_image = x - X_SIDE;
   *py_image = y - Y_BASE;
}


int intensity( x, y ) /* returns intensity at screen (x,y) */
                      /* uses global size */
int x, y;
{
int intens;
int x_image, y_image;

   /* change from screen to image origin */ 
   shift( x, y, &x_image, &y_image); 

   /* if (x_image,y_image) outside image return zero */
   if ( ( x_image < 0 ) || ( x_image >= size ) || 
        ( y_image < 0 ) || ( y_image >= size ) )
      return(0);
   else {
      y_image = size - 1 - y_image;   /* since picture starts from the top */

      intens = ( *( int_array + size*y_image + x_image) ) & 0377;

      return( intens );
   }
}

int lightness( x, y ) /* returns lightness at screen (x,y) */
                      /* uses global size */
int x, y;
{
int light;
int x_image, y_image;


   /* change from screen to image origin */ 
   shift( x, y, &x_image, &y_image); 
   shift( x, y, &x_image, &y_image); 

   /* if (x_image,y_image) outside image return zero */
   if ( ( x_image < 0 ) || ( x_image >= size ) || 
        ( y_image < 0 ) || ( y_image >= size ) )
      return(0);
   else {
      y_image = size - 1 - y_image;   /* since picture starts from the top */

      light = *( lig_array + size*y_image + x_image); /* for sign extension */

      return( light );
   }
}
/* ********************** HISTOGRAM FUNCTIONS ***************************** */

void setup_hist() /* initialises variables for drawing histograms and bars */
{
   if ( !both_flag ) {                           
      xl_int = xl_lig = 450;
      xr_int = xr_lig = 600;
      hist_space = 50;
   }
   else {
      xl_int = 420;
      xr_int = 510;
      xl_lig = 590;
      xr_lig = 680;
      hist_space = 15;
   }
}

void draw_hist() /* draws axes for histogram */
{
   float scale_factor, y_scaled, y_print;
   int x_left, x_right, x_Yaxis;
   int y_Xaxis, x_text;
   int y_bottom, y_top, y; 
   int y_int;
   char text_switch, *text;

   static int tick = 7;
   static int y_delta = 6;
   static char space[ 20 ] = ""; /* space to store text */

   /* clear space */
   clear_hist();

   enable(P_GREY);
   colour( DIM );

   if ( int_flag || both_flag ) { /* draw axes for intensity histogram
                                                              0 <= y <= 255 */
      x_left = xl_int;
      x_right = xr_int;

      x_Yaxis = xl_int;
      y_Xaxis = Y_BASE;
      y_bottom = y_Xaxis;
      y_top = 260 + y_bottom;

      x_text = x_left - 40;

      /* draw axes */
      hline( x_left, x_right, y_Xaxis);
      line( x_Yaxis, y_bottom, x_Yaxis, y_top);
 
      /* draw ticks and text */

      for( y = 0; y < 261; y += 32) {
      
         hline( x_Yaxis, x_Yaxis - tick, y + y_Xaxis); /* draw tick */
         setpos( x_text, y + y_Xaxis - y_delta);
         text = space;

         if ( y < 10 ) 
            sprintf( text, "  %d", y);
         else {
 
            if ( y < 100 )
               sprintf( text, " %d", y);
            else
               sprintf( text, "%d", y);
            }

         while (*text) gputc(*text++); /* write text */
      } 

      /* label histogram */

      setpos( xl_int + hist_space - w, Y_BASE - 40 );
      text = "intensity"; 
      while (*text) gputc(*text++); /* write text */
   }

   if ( !int_flag || both_flag ) { 

   /* draw axes for lightness histogram  -128 < y < 128 */
   
      x_left = xl_lig;
      x_right = xr_lig;

      x_Yaxis = xl_lig;
      y_Xaxis = Y_BASE + 128;
      y_bottom = y_Xaxis - 140;
      y_top = y_Xaxis + 140;

      x_text = xl_lig - 40 - 2 * w; /* extra space for "-" sign & 0 */

      /* draw axes */
      hline( x_left, x_right, y_Xaxis);
      line( x_Yaxis, y_bottom, x_Yaxis, y_top);
 
      /* draw ticks and text */

      text_switch = TRUE;
      scale_factor = 1.28 / 1.20412;  /* half scale = log10( 16 ) = 1.20412 */

      for( y = -125; y < 126; y += 25 ) {

         text_switch = !text_switch; 

         y_scaled = y * scale_factor;    /* y position on axis  */
         if ( y > 0 )
            y_int = ( y_scaled + 0.5 );
         else
            y_int = ( y_scaled - 0.5 );

         hline( x_Yaxis, x_Yaxis - tick, y_int + y_Xaxis); /* draw tick */

         if ( text_switch ) { /* write text */
            y_print = y / 100.0;
            setpos( x_text, y_int + y_Xaxis - y_delta);
            text = space;

            if ( y >= 0 )
               sprintf( text, " %.2f", y_print );
            else
               sprintf( text, "%.2f", y_print );

            while (*text) gputc(*text++); /* write text */
         }
      } 

      /* label histogram */

      setpos( xl_lig + hist_space - w, Y_BASE - 40 );
      text = "lightness"; 
      while (*text) gputc(*text++); /* write text */
   }
}
   
void draw_bar( ht, old_ht ) /* draws bar of height ht at global x_bar */
                       /* 2 cases : if int_flag TRUE 
                                       prints height below ; for 0 <= ht <= 255 
                                    else
                                       no text & for -128 < ht < 128 */
int ht, old_ht;
{
   static float scale_factor = 1.20412 / 128; /* half scale = 1.20412 */
   float 
   ht_scaled;
   int x_bar;        /* left side of bar */
   int y_axis;       /* bottom of bar */
   int x_text;       /* text x position */
   char *text;

   static int width = 10;              /* width of bar */ 
   static char space[ 10 ] = "";       /* space to store text */
   static char space_lig[ 10 ] = "";   /* space for lightness text */
   static int y_text = Y_BASE - 20;    /* text y position */

   if ( ht != old_ht) {

      if ( int_flag ) { /* draws bar & prints text for 0 <= ht <= 255 */

         x_bar = x_bar_int;
         y_axis = Y_BASE;
         x_text = x_bar -  w;

         /* change text */  

         text = space;
         colour(P_BLACK);
         setpos( x_text, y_text );
         while (*text) gputc(*text++); /* erase old text */

         text = space;
         if ( ht < 10 ) 
            sprintf( text, "  %d", ht);
         else if ( ht < 100 )
            sprintf( text, " %d", ht);
         else
            sprintf( text, "%d", ht);

         colour(P_COL);
         setpos( x_text, y_text );
         text = space;
         while (*text) gputc(*text++); /* write new text */

         /* change bar height */

         if ( ht > old_ht ) {
            colour(P_COL);
            fill( x_bar, old_ht + y_axis,
                  x_bar + width, ht + y_axis);
         }
         else {
            colour(P_BLACK);
            fill( x_bar, ht + y_axis,
                  x_bar + width, old_ht + y_axis);
         }
      }

      else { /* draw bar for -128 < ht < 128 */

         x_bar = x_bar_lig;
         y_axis = Y_BASE + 128;
         x_text = x_bar - 18; /* 2 * w */

         /* clear old text */

         colour( BLACK );
         fill( x_text, y_text, x_text + 45, y_text + 11 );

         /* write new text */

         colour(P_COL);
         setpos( x_text, y_text );
         text = space_lig;
         ht_scaled = ht * scale_factor;
         if ( ht >= 0 )
            sprintf( text, " %.2f", ht_scaled );
         else
            sprintf( text, "%.2f", ht_scaled );

         while (*text) gputc(*text++); /* write text */

         /* change bar height */

         if ( ( ht > 0 ) && ( old_ht > 0 ) )
            if ( ht > old_ht ) {
               colour(P_COL);
               fill( x_bar, old_ht + y_axis,
                     x_bar + width, ht + y_axis);
            }
            else {
               colour(P_BLACK);
               fill( x_bar, ht + y_axis,
                     x_bar + width, old_ht + y_axis);
            }

         else if ( ( ht > 0 ) && ( old_ht > 0 ) )
            if ( ht > old_ht ) {
               colour(P_BLACK);
               fill( x_bar, old_ht + y_axis,
                     x_bar + width, ht + y_axis);
            }
            else {
               colour(P_COL);
               fill( x_bar, ht + y_axis,
                     x_bar + width, old_ht + y_axis);
            }
         else { /* ht & old_ht have opposite signs or one is zero */
            colour(P_BLACK);
            fill( x_bar, old_ht + y_axis,
                  x_bar + width, y_axis);
            colour(P_COL);
            fill( x_bar, ht + y_axis,
                  x_bar + width, y_axis);
         }   
      }
   }
}

void redraw_bars( xb, yb, pint_b, plig_b, xr, yr, pint_r, plig_r ) /* draws red
    and cyam bars for current positions - returns intensities and lightness's */
int xb, yb, *pint_b, *plig_b, xr, yr, *pint_r, *plig_r;
{

   if ( both_flag ) {

      enable( P_CYAM );
      *pint_b = intensity( xb, yb );
      *plig_b = lightness( xb, yb );

      int_flag = TRUE;
      x_bar_int = xl_int + hist_space;
      draw_bar( *pint_b, 0 );

      int_flag = FALSE;
      x_bar_lig = xl_lig + hist_space;
      draw_bar( *plig_b, 0 );

      enable( P_RED );
      *pint_r = intensity( xr, yr );
      *plig_r = lightness( xr, yr );

      int_flag = TRUE;
      x_bar_int = xl_int + hist_space + 50;
      draw_bar( *pint_r, 0 );

      int_flag = FALSE;
      x_bar_lig = xl_lig + hist_space + 55;
      draw_bar( *plig_r, 0 );
   }
   else {
      if ( int_flag ) {
         enable( P_CYAM );
         *pint_b = intensity( xb, yb );
         x_bar_int = xl_int + hist_space;
         draw_bar( *pint_b, 0 );
         enable( P_RED );
         *pint_r = intensity( xr, yr );
         x_bar_int = xl_int + hist_space + 50;
         draw_bar( *pint_r, 0 );
      }
      else {
         enable( P_CYAM );
         *plig_b = lightness( xb, yb );
         x_bar_lig = xl_lig + hist_space;
         draw_bar( *plig_b, 0 );
         enable( P_RED );
         *plig_r = lightness( xr, yr );
         x_bar_lig = xl_lig + hist_space + 55;
         draw_bar( *plig_r, 0 );
      }
   }
}

void reset( x, y, xb, yb, pint_b, plig_b, xr, yr, pint_r, plig_r ) /*
                   used to clear menu and redraw histogram and region DIM */
int x, y, xb, yb, *pint_b, *plig_b, xr, yr, *pint_r, *plig_r;
{
    setup_hist();
    inv_reg_log[ MENU ] = FALSE;
    grey = DIM;
    draw_region( grey );   /* draw region */
    menu_flag = FALSE;
    clear_menu();
    if ( hist_flag ) {
       draw_hist();
       redraw_bars( xb, yb, pint_b, plig_b, 
                    xr, yr, pint_r, plig_r );
    }
    enable( P_GREEN );  /* draw cursor - while button held */
    draw_cross( x, y); 
 }


void clear_hist() /* clears histogram region */
{
   int xl, xr;

   static int base = Y_BASE - 40;
   static int top = Y_BASE + 270;

   enable(P_ALL);
   colour(BLACK);

   xl = 420 - 40 - 2 * w;
   xr = XPIXELS;
   fill( xl, base, xr, top);
}

stop()
{
   fclose( flog );
   exit( 1 );
}


char write_file() /* opens file  */
{
   char filename[ 40 ];
   char answer[ 20 ];
   char statement[ 40 ];

   write_text( "file name : ");
   read_response( filename );

   if ( ( flog = fopen( filename, "w" ) ) == NULL) {
      putchar( BEEP );
      write_text( "can't open file");
      return( FALSE );
   }

   return( TRUE );
}                  
