home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Science / Science.zip / fblnk224.zip / blinkgui.c < prev    next >
C/C++ Source or Header  |  1999-01-28  |  48KB  |  1,596 lines

  1. /*  blinkgui.c for fitsblink */
  2. /*  Jure Skvarc, May 1998  */
  3. /* User interface */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <ctype.h>
  7. #include <math.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include <getopt.h>
  11.  
  12. #include <forms.h>
  13. #include <fitsio.h>
  14.  
  15. #ifdef HPUX
  16. #include <macros.h>
  17. #endif
  18.  
  19. #include "formblink.h"
  20. #include "functs.h"
  21. #include "consts.h"
  22.  
  23. extern STATE state;
  24. extern BLINK_FRAME *frame;
  25. extern OBSERVATORY observatory;
  26.  
  27. extern char *optarg;
  28. extern int optind, opterr, optopt;
  29. /*  Draw given image to the screen  */
  30. void
  31. draw_image(BLINK_FRAME *frame, int n)
  32.  
  33. {
  34.   GC gc = fl_state[fl_get_form_vclass(state.blinker->blinker)].gc[0];
  35.   Window win = FL_ObjWin(state.blinker->blinkW);
  36.  
  37.   XSetFunction(state.disp, gc, GXcopy);
  38.   XCopyArea(state.disp, frame[n].pixmap, win, gc, 0, 0, 
  39.         state.blinker->blinkW->w, state.blinker->blinkW->h,
  40.         state.blinker->blinkW->x, state.blinker->blinkW->y);
  41.   state.doastr = 0;
  42.   fl_set_form_title(state.blinker->blinker, frame[n].name);
  43.   fl_set_button(state.blinker->markersW, frame[n].objshow);
  44. }
  45.  
  46. /*  Draw a magnified image around the x, y position to a zoom window */
  47. void
  48. draw_zoom(BLINK_FRAME *frame, int n, FL_OBJECT *o, int x, int y)
  49.  
  50. {
  51.   int xmin, xmax, ymin, ymax;
  52.   int w, h;
  53.   int xq, yq, xt, yt;
  54.   int z;
  55.   int i, j;
  56.   PIXEL v;
  57.   FITS_IMAGE *im;
  58.   Display *disp;
  59.  
  60.   GC gc = fl_state[fl_get_form_vclass(state.blinker->blinker)].gc[0];
  61.   Window win = FL_ObjWin(o);
  62.   disp = state.disp;
  63.  
  64.   im = &(frame[n].fits);
  65.   if (x >=0 && x < im->width &&
  66.       y >=0 && y < im->height) {  /*  Draw only if the pointer is inside image */
  67.     
  68.     /*  Determine number of pixels in x and y direction  */
  69.     z = state.zoom_width;
  70.     w = o->w / z;
  71.     h = o->h / z;
  72.     /*  Limiting coordinates of the area shown  */
  73.     xmin = max(0, x - w);
  74.     xmax = min(x + w, im->width - 1);
  75.     ymin = max(0, y - h);
  76.     ymax = min(y + h, im->height - 1);
  77.     /*  Do the drawing  */
  78.     yq = o->y;
  79.     yt = y - h / 2;
  80.     for (j = 0; j < h; j++) {
  81.       xq = o->x;
  82.       xt = x - w / 2; 
  83.       for (i = 0; i < w; i++) {
  84.     v = video_point(im, xt++, yt);
  85.     XSetForeground(disp, gc, state.pixel[correct(frame, n, v)]);
  86.     XFillRectangle(disp, win, gc, xq, yq, z, z);
  87.     xq += z;
  88.       }
  89.       yq += z;
  90.       yt++;
  91.     }
  92.     /*  Draw a cross  */
  93.     XSetForeground(disp, gc, fl_get_pixel(FL_RED));
  94.     xt = o->x + w / 2 * z;
  95.     yt = o->y + h / 2 * z;
  96.     w = o->w / 4;
  97.     h = o->h / 4;
  98.     XFillRectangle(disp, win, gc, xt, yt - h, z, h);
  99.     XFillRectangle(disp, win, gc, xt, yt + z, z, h);
  100.     XFillRectangle(disp, win, gc, xt - h, yt, h, z);
  101.     XFillRectangle(disp, win, gc, xt + z, yt, h, z); 
  102.   }
  103. }
  104.  
  105.  
  106. /*  Show offsets for the left image  */
  107. void
  108. show_left_offsets(BLINK_FRAME *frame, int n)
  109.  
  110. {
  111.   char temp[64];
  112.  
  113.   sprintf(temp, "%.2f", frame[n].dx);
  114.   fl_set_input(state.gui->firstdeltaxW, temp);
  115.   sprintf(temp, "%.2f", frame[n].dy);
  116.   fl_set_input(state.gui->firstdeltayW, temp);
  117. }
  118.  
  119. /*  Show offsets for the right image  */
  120. void
  121. show_right_offsets(BLINK_FRAME *frame, int n)
  122.  
  123. {
  124.   char temp[64];
  125.  
  126.   sprintf(temp, "%.2f", frame[n].dx);
  127.   fl_set_input(state.gui->seconddeltaxW, temp);
  128.   sprintf(temp, "%.2f", frame[n].dy);
  129.   fl_set_input(state.gui->seconddeltayW, temp);
  130. }
  131.  
  132. /*  Show information about frame n in the control c  */
  133. void
  134. show_frame_info(BLINK_FRAME *frame, int n, int c)
  135.  
  136. {
  137.   switch (c) {
  138.   case 0:
  139.     fl_set_choice(state.gui->firstnameW, n + 1);
  140.     fl_set_xyplot_data(state.gui->firstgreyW, 
  141.                frame[n].histx, frame[n].histy, frame[n].nhisto, 
  142.                "", "", "");
  143.     fl_set_xyplot_data(state.gui->firstgammaW, 
  144.                frame[n].gamx, frame[n].gamy, frame[n].ngam, 
  145.                "", "", "");
  146.     fl_set_xyplot_xbounds(state.gui->firstgammaW, frame[n].xmin, frame[n].xmax);
  147.     fl_set_xyplot_xbounds(state.gui->firstgreyW, frame[n].xmin, frame[n].xmax);
  148.     show_left_offsets(frame, n);
  149.     if (state.control_num == 0) {
  150.       draw_image(frame, n);
  151.     }
  152.     break;
  153.   case 1:
  154.     fl_set_choice(state.gui->secondnameW, n + 1);
  155.     fl_set_xyplot_data(state.gui->secondgreyW, 
  156.                frame[n].histx, frame[n].histy, frame[n].nhisto, 
  157.                "", "", "");
  158.     fl_set_xyplot_data(state.gui->secondgammaW, 
  159.                frame[n].gamx, frame[n].gamy, frame[n].ngam, 
  160.                "", "", "");
  161.     fl_set_xyplot_xbounds(state.gui->secondgammaW, frame[n].xmin, frame[n].xmax);
  162.     fl_set_xyplot_xbounds(state.gui->secondgreyW, frame[n].xmin, frame[n].xmax);
  163.     show_right_offsets(frame, n);
  164.     if (state.control_num == 1) {
  165.       draw_image(frame, n);
  166.     }
  167.     break;
  168.   }
  169.   fl_set_menu_item_mode(state.blinker->astrometryW, MATCH_STARS, (frame[n].detect) ? FL_PUP_NONE : FL_PUP_GREY);
  170.   fl_set_menu_item_mode(state.blinker->astrometryW, SAVE_STAR_LIST, (frame[n].detect) ? FL_PUP_NONE : FL_PUP_GREY);
  171.   fl_set_menu_item_mode(state.blinker->astrometryW, DO_ASTROMETRY, (frame[n].matched) ? FL_PUP_NONE : FL_PUP_GREY);
  172.   if (state.parameters && fl_form_is_visible(state.parameters->Parameters)) {
  173.     edit_parameters(state.blinker->astrometryW, EDIT_PARAMETERS);
  174.   }
  175. }
  176.  
  177. /*************************************/
  178. /*  Callbacks for the control window */
  179. /*************************************/
  180. void
  181. turnimageC(FL_OBJECT *obj, long val)
  182.  
  183. {
  184.   if (state.frame_used > 0) {
  185.     int n = state.control[val];
  186.     state.control_num = val;
  187.     draw_image(frame, n);
  188.     if (state.parameters && fl_form_is_visible(state.parameters->Parameters)) {
  189.       edit_parameters(state.blinker->astrometryW, EDIT_PARAMETERS);
  190.     }
  191.   }
  192. }
  193.  
  194. /*  Load a FITS image, calculate a histogram and set some parameters in a
  195.  control  */
  196. void 
  197. loadC(FL_OBJECT *obj, long val)
  198.  
  199. {
  200.   const char *fn;
  201.   static char *curdir = "";
  202.   static char *pattern = "*.[fF]*[tT][sS]*";
  203.   static char *name = "";
  204.   int n;
  205.  
  206.   fl_use_fselector(1);
  207.   fl_invalidate_fselector_cache();
  208.   fn = fl_show_fselector("Choose input file", curdir, pattern, name);
  209.   if (fn == NULL) return;
  210.   /*  Save the current directory  */
  211.   curdir = (char *) fl_get_directory();
  212.   /*  Save the current pattern */
  213.   pattern = (char *) fl_get_pattern();
  214.   /*  Get index of the current image  */
  215.   n = state.frame_used;
  216.   (state.frame_used)++;
  217.   if (state.frame_used == state.frame_max) {
  218.     int i;
  219.     state.frame_max += FRAME_MAX;
  220.     if ((frame = (BLINK_FRAME *) 
  221.      realloc(frame, sizeof(BLINK_FRAME) * state.frame_max)) == NULL) {
  222.       fprintf(stderr, "Out of memory, function loadC, variable frame\n");
  223.       exit(1);
  224.     }
  225.     for (i = state.frame_used; i < state.frame_max; i++) {
  226.       frame[i].gamx = NULL;
  227.       frame[i].gamy = NULL;
  228.       frame[i].kg = NULL;
  229.       frame[i].histx = NULL;
  230.       frame[i].histy = NULL;
  231.       frame[i].name = NULL;
  232.       frame[i].fits.image = NULL;
  233.     }
  234.   }
  235.   /*  Release space for the previous name  */
  236.   if (frame[n].name) free(frame[n].name);
  237.   /*  copy filename to the structure  */
  238.   frame[n].name = strdup((char *) fn);
  239.   /*  Load the image into the structure */
  240.   if (!load_frame(frame, n)) {
  241.     state.control[val] = n;
  242.     set_image(frame, n);
  243.     /*  Add image name to choices  */
  244.     fl_addto_choice(state.gui->firstnameW, fl_get_filename());
  245.     fl_addto_choice(state.gui->secondnameW, fl_get_filename());
  246.     /*  Write the file name into the input field,  */
  247.     /*  draw histogram, grey level correction curve, translation and rotation  */
  248.     show_frame_info(frame, n, val);
  249.     if (state.frame_used == 1) {
  250.       show_frame_info(frame, n, 1 - val);
  251.     }
  252.   }
  253.   else {
  254.     state.frame_used--;
  255.   }
  256. }
  257.  
  258. /*  Erase the currently selected filename from the list and release all
  259.     the memory occupied by the image  */
  260. void
  261. eraseC(FL_OBJECT *obj, long val)
  262.  
  263. {
  264.   FL_OBJECT *ch1, *ch2;
  265.   int i, n, m;
  266.  
  267.   ch1 = state.gui->firstnameW;
  268.   ch2 = state.gui->secondnameW;
  269.   n = state.control[val];
  270.   m = n + 1;
  271.   state.freeze = 0;
  272.   fl_hide_object(state.blinker->lockedW);
  273.   fl_hide_object(state.blinker->upW);
  274.   fl_hide_object(state.blinker->downW);
  275.   fl_hide_object(state.blinker->rightW);
  276.   fl_hide_object(state.blinker->leftW);
  277.   fl_hide_object(state.blinker->circleW);
  278.   /*  Erase the filename from both choices  */
  279.   if (fl_get_choice_maxitems(ch1) > 0) {
  280.     fl_delete_choice(ch1, m);
  281.     fl_delete_choice(ch2, m);
  282.     /*  Remove the image from the memory  */
  283.     remove_frame(frame, n);
  284.     if (state.blinknum == n) state.blinknum--;
  285.     if (state.frame_used < 2 && state.blink) {
  286.       /*  Stop blinking  */
  287.       state.blink = 0;
  288.       /* Switch off the Blink button */
  289.       fl_set_button(state.blinker->playW, 0);
  290.     }
  291.     if (fl_get_choice_maxitems(ch1) > 0) {
  292.       state.control[0] = fl_get_choice(ch1) - 1;
  293.       state.control[1] = fl_get_choice(ch2) - 1;
  294.       show_frame_info(frame, state.control[0], 0);
  295.       show_frame_info(frame, state.control[1], 1);
  296.     }
  297.     else {
  298.       /*  The last image was erased */
  299.       /*  Erase histogram, grey level correction curve and images  */
  300.       fl_set_xyplot_data(state.gui->firstgreyW, NULL, NULL, 0, "", "", "");
  301.       fl_set_xyplot_data(state.gui->secondgreyW, NULL, NULL, 0, "", "", "");
  302.       fl_set_xyplot_data(state.gui->firstgammaW, NULL, NULL, 0, "", "", "");
  303.       fl_set_xyplot_data(state.gui->secondgammaW, NULL, NULL, 0, "", "", "");
  304.       fl_winset(FL_ObjWin(state.blinker->blinkW));
  305.       fl_set_form_title(state.blinker->blinker, "(no image)");
  306.       fl_rectf(state.blinker->blinkW->x, state.blinker->blinkW->y,
  307.            state.blinker->blinkW->w, state.blinker->blinkW->h, 
  308.            state.blinker->blinkW->col1);
  309.       fl_rectf(state.blinker->zoom1W->x, state.blinker->zoom1W->y,
  310.            state.blinker->zoom1W->w, state.blinker->zoom1W->h, 
  311.            state.blinker->zoom1W->col1);
  312.       fl_redraw_object(state.blinker->zoom1W);
  313.       fl_rectf(state.blinker->zoom2W->x, state.blinker->zoom2W->y,
  314.            state.blinker->zoom2W->w, state.blinker->zoom2W->h, 
  315.            state.blinker->zoom2W->col1);
  316.       fl_redraw_object(state.blinker->zoom2W);
  317.       /*  Disable Astrometry options  */
  318.       for (i = 1; i < EMPTY_ITEM1; i++) {
  319.     fl_set_menu_item_mode(state.blinker->astrometryW, i, FL_PUP_GREY);
  320.       }
  321.       /*  If the Set parameters window is open, close it  */
  322.       if (state.parameters && fl_form_is_visible(state.parameters->Parameters)) {
  323.     fl_hide_form(state.parameters->Parameters);
  324.       }
  325.     }
  326.   }
  327. }
  328.  
  329. /*  Change control to another image  */
  330. void
  331. nameC(FL_OBJECT *obj, long val)
  332.  
  333. {
  334.   if (state.frame_used > 0) {
  335.     state.control[val] = fl_get_choice(obj) - 1;
  336.     show_frame_info(frame, state.control[val], val);
  337.   }
  338. }
  339.  
  340. /******************************************/
  341. /*  Show the contents of the FITS header  */
  342. /******************************************/
  343. void
  344. fitsC(FL_OBJECT *obj, long val)
  345.  
  346. {
  347.   fitsfile *fptr;
  348.   int status;
  349.   int i;
  350.   char line[81], line1[81];
  351.   int n = state.control[val];
  352.  
  353.   if (state.frame_used == 0) return;
  354.   if (state.browser[val] == NULL) {
  355.     state.browser[val] = create_form_Edit();
  356.   }
  357.   /*  Deactivate FITS button */
  358.   fl_deactivate_object(obj);
  359.   /*  Show the form  */
  360.   fl_show_form(state.browser[val]->Edit, FL_PLACE_FREE_CENTER, FL_FULLBORDER, frame[n].name);
  361.   /*  Open FITS file  */
  362.   status = 0;
  363.   fits_open_file(&fptr, frame[n].name, READONLY, &status);
  364.   i = 1;
  365.   do {
  366.     /*  Read fits header line */
  367.     fits_read_record(fptr, i, line, &status);
  368.     if (!status) {
  369.       /*  Insert it in the browser  */
  370.       fl_addto_browser(state.browser[val]->browseW, line);
  371.       strcpy(line1, line);
  372.     }
  373.     else if (strncmp("END", line1, 3)) {
  374.       do  {
  375.     fits_read_errmsg(line);
  376.     fl_addto_browser(state.browser[val]->browseW, line);
  377.       } while(strlen(line) > 0);
  378.       status = 1;
  379.     }
  380.     i++;
  381.   } while (status == 0);
  382.   /*  close the file  */
  383.   fits_close_file(fptr, &status);
  384.   state.b[val] = 1;
  385. }  
  386.  
  387.  
  388. /***********************/
  389. /*  Histogram          */
  390. /***********************/
  391.  
  392. /*  This should probably remain empty */
  393. void
  394. greyC(FL_OBJECT *obj, long val)
  395.  
  396. {
  397. }
  398.  
  399. void
  400. emptyC(FL_OBJECT *obj, long val)
  401.  
  402. {
  403. }
  404.  
  405. /**************************/
  406. /* Grey level correction  */
  407. /**************************/
  408. void
  409. gammaC(FL_OBJECT *obj, long val)
  410.  
  411. {
  412.   float x, y;
  413.   int i;
  414.   int n, m;
  415.  
  416.   /*  Get the value which has changed  */
  417.   fl_get_xyplot(obj, &x, &y, &i);
  418.   if (i >= 0) {
  419.     n = state.control[val];
  420.     frame[n].gamx[i] = x;
  421.     frame[n].gamy[i] = y;
  422.     if (i > 0) {
  423.       frame[n].kg[i] = (frame[n].gamy[i] - frame[n].gamy[i - 1]) / 
  424.     (frame[n].gamx[i] - frame[n].gamx[i - 1]);
  425.     }
  426.     if (i < frame[n].ngam - 1) {
  427.       frame[n].kg[i + 1] = (frame[n].gamy[i + 1] - frame[n].gamy[i]) / 
  428.     (frame[n].gamx[i + 1] - frame[n].gamx[i]);
  429.     }
  430.     m = state.control[1 - val];
  431.     if (n == m) {
  432.       switch (val) {
  433.       case 0:
  434.     fl_set_xyplot_data(state.gui->secondgammaW, 
  435.                frame[m].gamx, frame[m].gamy, frame[m].ngam, 
  436.                "", "", "");
  437.     break;
  438.       case 1:
  439.     fl_set_xyplot_data(state.gui->firstgammaW, 
  440.                frame[m].gamx, frame[m].gamy, frame[m].ngam, 
  441.                "", "", "");
  442.     break;
  443.       }
  444.     }
  445.     set_image(frame, n);
  446.     if (state.control_num == val || state.control[0] == state.control[1]) {
  447.       draw_image(frame, n);
  448.     }
  449.   }
  450. }
  451.  
  452. void
  453. histadjC(FL_OBJECT *obj, long val)
  454.  
  455. {
  456.   float gmin, gmax;
  457.   int c, step  = 0;
  458.   
  459.   c = fl_mouse_button();
  460.   switch(c) {
  461.   case FL_LEFT_MOUSE:
  462.     step = 100;
  463.     break;
  464.   case FL_MIDDLE_MOUSE:
  465.     step = 1000;
  466.     break;
  467.   case FL_RIGHT_MOUSE:
  468.     step = 10000;
  469.     break;
  470.   }
  471.   switch (val) {
  472.   case 1:
  473.     fl_get_xyplot_xbounds(state.gui->firstgammaW, &gmin, &gmax);
  474.     gmin += step;
  475.     break;
  476.   case 2:
  477.     fl_get_xyplot_xbounds(state.gui->firstgammaW, &gmin, &gmax);
  478.     gmin -= step;
  479.     break;
  480.   case 3:
  481.     fl_get_xyplot_xbounds(state.gui->firstgammaW, &gmin, &gmax);
  482.     gmax -= step;
  483.     break;
  484.   case 4:
  485.     fl_get_xyplot_xbounds(state.gui->firstgammaW, &gmin, &gmax);
  486.     gmax += step;
  487.     break;
  488.   case 5:
  489.     fl_get_xyplot_xbounds(state.gui->secondgammaW, &gmin, &gmax);
  490.     gmin += step;
  491.     break;
  492.   case 6:
  493.     fl_get_xyplot_xbounds(state.gui->secondgammaW, &gmin, &gmax);
  494.     gmin -= step;
  495.     break;
  496.   case 7:
  497.     fl_get_xyplot_xbounds(state.gui->secondgammaW, &gmin, &gmax);
  498.     gmax -= step;
  499.     break;
  500.   case 8:
  501.     fl_get_xyplot_xbounds(state.gui->secondgammaW, &gmin, &gmax);
  502.     gmax += step;
  503.     break;
  504.   }
  505.   if (val < 5 || state.control[0] == state.control[1]) {
  506.     fl_set_xyplot_xbounds(state.gui->firstgammaW, gmin, gmax);
  507.     fl_set_xyplot_xbounds(state.gui->firstgreyW, gmin, gmax);
  508.     frame[state.control[0]].xmin = gmin;
  509.     frame[state.control[0]].xmax = gmax;
  510.   }
  511.   if (val > 4 || state.control[0] == state.control[1]) {
  512.     frame[state.control[1]].xmin = gmin;
  513.     frame[state.control[1]].xmax = gmax;
  514.     fl_set_xyplot_xbounds(state.gui->secondgammaW, gmin, gmax);
  515.     fl_set_xyplot_xbounds(state.gui->secondgreyW, gmin, gmax);
  516.   }
  517. }
  518.  
  519.  
  520. int
  521. cmppixel (const void *a1, const void *b1)
  522.  
  523. {
  524.   int t = (int) *((PIXEL *) a1) - (int) *((PIXEL *) b1);
  525.   if (t > 0)
  526.     return 1;
  527.   else if (t < 0)
  528.     return -1;
  529.   else
  530.     return 0;
  531. }
  532.  
  533. void
  534. invert_display(BLINK_FRAME *frame, int n)
  535.  
  536. {
  537.   int i;
  538.   for (i = 0; i < frame[n].ngam; i++) {
  539.     frame[n].gamy[i] = state.grey_max - frame[n].gamy[i];
  540.     if (i > 0) 
  541.       frame[n].kg[i] = (frame[n].gamy[i] - frame[n].gamy[i - 1]) / 
  542.     (frame[n].gamx[i] - frame[n].gamx[i - 1]);
  543.   }
  544. }
  545.  
  546. /*===========================================================*/
  547. /*  Do automatic adjustment of grey levels for the image n   */
  548. /*===========================================================*/
  549. void
  550. autolevels(int n)
  551.  
  552. {
  553.   int i, l, p, ng;
  554.   int j, m;
  555.   double min, max, d;
  556.   PIXEL *temp, *p1, *p2;
  557.   int step;
  558.  
  559.   /*  Reserve space for a temporary image   */
  560.   l = 50000;
  561.   step = frame[n].fits.width * frame[n].fits.height / l;
  562.   if (step == 0) {
  563.     step = 1;
  564.     l = frame[n].fits.width * frame[n].fits.height;
  565.   }
  566.   temp = (PIXEL *) myalloc(sizeof(PIXEL) * l, "autoC", "temp");
  567.   /*  Copy the image  */
  568.   p1 = frame[n].fits.image;
  569.   p2 = temp;
  570.   for (i = 0; i < l; i++) {
  571.     *p2 = *p1;
  572.     p1 += step;
  573.     p2++;
  574.   }
  575.  
  576.  
  577.   /*  Sort values */
  578.   qsort(temp, l, sizeof(PIXEL), cmppixel);
  579.   ng = frame[n].ngam; 
  580.   p = ng / 2 - 1;
  581. #if 1
  582.   frame[n].gamx[p] = temp[(int) (0.03 * l)];
  583.   frame[n].gamy[p] = 0;
  584.   frame[n].gamx[p + 1] = temp[(int) ((1.0 - state.autolevel_high) * l)];
  585.   frame[n].gamy[p + 1] = state.grey_max;
  586. #else
  587.   /*  Median value  */
  588.   m = temp[l / 2];
  589.   d = 0;
  590.   j = 0;
  591.   for (i = 0; i < l / 2; i++) {
  592.     min = (temp[i] - m);
  593.     d += min * min;
  594.     j++;
  595.   }
  596.   min = sqrt(d / j); 
  597.   d = 0;
  598.   j = 0;
  599.   for (i = l / 2; i < l; i++) {
  600.     max = (temp[i] - m);
  601.     d += max * max;
  602.     j++;
  603.   }
  604.   max = sqrt(d / j); 
  605.   frame[n].gamx[p] = m - 4 * min;
  606.   frame[n].gamy[p] = 0;
  607.   frame[n].gamx[p + 1] = m + 1.0 * max;
  608.   frame[n].gamy[p + 1] = state.grey_max;
  609. #endif
  610.   for(i = 0; i < p; i++) {
  611.     frame[n].gamx[i] = i * (frame[n].gamx[p] - frame[n].low) / p;
  612.     frame[n].gamy[i] = 0;
  613.   }
  614.   p += 2;
  615.   for(i = p; i < ng; i++) {
  616.     frame[n].gamx[i] = frame[n].gamx[p - 1] + (i + 1 - p) * 
  617.       (frame[n].high - frame[n].gamx[p - 1]) / (ng - p);
  618.     frame[n].gamy[i] = state.grey_max;
  619.   }
  620.   for (i = 1; i < ng; i++) {
  621.     frame[n].kg[i] = (frame[n].gamy[i] - frame[n].gamy[i - 1]) / 
  622.       (frame[n].gamx[i] - frame[n].gamx[i - 1]);
  623.   }
  624.   free(temp);
  625.   /*  frame[n].xmin = frame[n].gamx[p - 2] * 0.8;
  626.       frame[n].xmax = frame[n].gamx[p  - 1] * 1.2; */
  627.  
  628.   if (state.inverse) invert_display(frame, n);
  629. }
  630.  
  631. void
  632. autoC(FL_OBJECT *obj, long val)
  633.  
  634. {
  635.   if (state.frame_used > 0) {
  636.     int n = state.control[val];
  637.     
  638.     fl_set_oneliner_font(0, 20); 
  639.     fl_show_oneliner("Adjusting grey levels", 100, 100);
  640.     XFlush(state.disp);
  641.     autolevels(n);
  642.     fl_hide_oneliner();
  643.     set_image(frame, n);
  644.     show_frame_info(frame, n, val);
  645.     if (state.control[0] == state.control[1]) {
  646.       show_frame_info(frame, n, 1 - val);
  647.     }
  648.   }
  649. }
  650.  
  651. /*  Invert the grey level transformation  */
  652. void
  653. invertC(FL_OBJECT *obj, long val)
  654.  
  655. {
  656.   if (state.frame_used > 0) {
  657.     int n = state.control[val];
  658.     invert_display(frame, n);
  659.     set_image(frame, n);
  660.     show_frame_info(frame, n, val);
  661.     if (state.control[0] == state.control[1]) {
  662.       show_frame_info(frame, n, 1 - val);
  663.     }
  664.   }
  665. }
  666.  
  667. /**************************************/
  668. /*   Image translation and rotation  */
  669. /**************************************/
  670. void
  671. deltaxC(FL_OBJECT *obj, long val)
  672.  
  673. {
  674.   if (state.frame_used > 0) {
  675.     int n = state.control[val];
  676.     frame[n].dx = strtod(fl_get_input(obj), NULL);
  677.     show_left_offsets(frame, n);
  678.     show_right_offsets(frame, n);
  679.     set_image(frame, n);
  680.     if (state.control_num == val) {
  681.       draw_image(frame, n);
  682.     }
  683.   }
  684. }
  685.  
  686. void
  687. deltayC(FL_OBJECT *obj, long val)
  688.  
  689. {
  690.   if (state.frame_used > 0) {
  691.     int n = state.control[val];
  692.     frame[n].dy = strtod(fl_get_input(obj), NULL);
  693.     show_left_offsets(frame, n);
  694.     show_right_offsets(frame, n);
  695.     set_image(frame, n);
  696.     if (state.control_num == val) {
  697.       draw_image(frame, n);
  698.     }
  699.   }
  700. }
  701.  
  702. /***********************/
  703. /*  Ending the program */
  704. /***********************/
  705.  
  706. void
  707. quitC(FL_OBJECT *obj, long val)
  708.  
  709. {
  710.   if (fl_show_question("Do you really want to quit?", 1)) {
  711.     fl_finish();
  712.     exit(0);
  713.   }
  714. }
  715.  
  716.  
  717. void
  718. helpC(FL_OBJECT *obj, long val)
  719.  
  720. {
  721.   int m;
  722.   char *a;
  723.  
  724.   m = fl_get_menu(obj);
  725.   switch (m) {
  726.   case 1:
  727.     info();
  728.     break;
  729.   case 2:
  730.     /* readme(obj, 2); */
  731.     if (state.wwwbrowser && state.helpfile) {
  732.       a = (char *) myalloc(sizeof(char) * (strlen(state.wwwbrowser) + 
  733.                        strlen(state.helpfile) + 2), "helpC", "a");
  734.       strcpy(a, state.wwwbrowser);
  735.       strcat(a, " ");
  736.       strcat(a, state.helpfile);
  737.       fl_exe_command(a, 0);
  738.     }
  739.     break;
  740.   }
  741. }
  742.  
  743.  
  744. void
  745. info(void)
  746.  
  747. {
  748.   static FD_info *info;
  749.   char a[30];
  750.  
  751.   if (info == NULL) {
  752.     info = create_form_info();
  753.     sprintf(a, "Fistblink %s", VERSION);
  754.     fl_set_object_label(info->versionW, a);
  755.   }
  756.   /*  Deactivate FITS button */
  757.   fl_deactivate_all_forms();
  758.   /*  Show the form  */
  759.   fl_show_form(info->info, FL_PLACE_MOUSE | FL_FIX_SIZE, FL_FULLBORDER, "");
  760.   fl_do_forms();
  761.   fl_hide_form(info->info);
  762.   fl_activate_all_forms();
  763. }  
  764.  
  765. void
  766. readme(FL_OBJECT *obj, int n)
  767.  
  768. {
  769.  
  770.   /*  The window in not created yet, do it now  */
  771.   if (state.readme == NULL) {
  772.     state.readme = create_form_help();
  773.     fl_set_form_minsize(state.readme->help, 
  774.           state.readme->helpW->w, state.readme->helpW->h);
  775.     /*  Read README file  */
  776.     fl_load_browser(state.readme->readmeW, BLINK_README_FILE);
  777.   }
  778.   /*  Deactivate README item in the menu */
  779.   fl_set_menu_item_mode(obj, n, FL_PUP_GREY);
  780.   /*  Show the form  */
  781.   fl_show_form(state.readme->help, FL_PLACE_FREE_CENTER, FL_FULLBORDER, "README");
  782. }
  783.  
  784. /*  These two remain empty  */
  785. void
  786. zoom1C(FL_OBJECT *obj, long val)
  787.  
  788. {
  789. }
  790.  
  791. void
  792. zoom2C(FL_OBJECT *obj, long val)
  793.  
  794. {
  795. }
  796.  
  797.  
  798.  
  799. /**************************************/
  800. /*  Callbacks for the blinking window */
  801. /**************************************/
  802. void
  803. do_blink(void)
  804.  
  805. {
  806.   float d;
  807.  
  808.   draw_image(frame, state.blinknum);
  809.   d = fl_get_counter_value(state.blinker->deltatW);
  810.   delay((int) (100.0 * d));
  811.   state.blinknum++;
  812.   if (state.blinknum == state.frame_used) state.blinknum = 0;
  813. }
  814.  
  815. /*  Should remain empty  */
  816. void
  817. deltatC(FL_OBJECT *obj, long val)
  818.  
  819. {
  820. }
  821.  
  822. void
  823. blinkC(FL_OBJECT *obj, long val)
  824.  
  825. {
  826. }
  827.  
  828. /*  Move the right image one pixel up */
  829. void
  830. upC(FL_OBJECT *obj, long val)
  831.  
  832. {
  833.   if (state.freeze) {
  834.     /*  Get index of the right image  */
  835.     int n = state.control[1];
  836.     /*  Shift it up for one pixel  */
  837.     frame[n].dy++;
  838.     state.yf++;
  839.     draw_zoom(frame, n, state.blinker->zoom2W, state.xf, state.yf);
  840.     show_right_offsets(frame, n);
  841.     if (state.control[0] == state.control[1]) {
  842.       show_left_offsets(frame, n);
  843.       draw_zoom(frame, n, state.blinker->zoom1W, state.xf, state.yf);
  844.     }
  845.   }
  846. }
  847.  
  848. /*  Move the right image one pixel down */
  849. void
  850. downC(FL_OBJECT *obj, long val)
  851.  
  852. {
  853.   if (state.freeze) {
  854.     /*  Get index of the right image  */
  855.     int n = state.control[1];
  856.     /*  Shift it down for one pixel  */
  857.     frame[n].dy--;
  858.     state.yf--;
  859.     draw_zoom(frame, n, state.blinker->zoom2W, state.xf, state.yf);
  860.     show_right_offsets(frame, n);
  861.     if (state.control[0] == state.control[1]) {
  862.       show_left_offsets(frame, n);
  863.       draw_zoom(frame, n, state.blinker->zoom1W, state.xf, state.yf);
  864.     }
  865.   }
  866. }
  867.  
  868. /*  Move the right image one pixel right */
  869. void
  870. rightC(FL_OBJECT *obj, long val)
  871.  
  872. {
  873.   if (state.freeze) {
  874.     /*  Get index of the right image  */
  875.     int n = state.control[1];
  876.     /*  Shift it right for one pixel  */
  877.     frame[n].dx--;
  878.     state.xf--;
  879.     draw_zoom(frame, n, state.blinker->zoom2W, state.xf, state.yf);
  880.     show_right_offsets(frame, n);
  881.     if (state.control[0] == state.control[1]) {
  882.       show_left_offsets(frame, n);
  883.       draw_zoom(frame, n, state.blinker->zoom1W, state.xf, state.yf);
  884.     }
  885.   }
  886. }
  887.  
  888. /*  Move the right image one pixel left */
  889. void
  890. leftC(FL_OBJECT *obj, long val)
  891.  
  892. {
  893.   if (state.freeze) {
  894.     /*  Get index of the right image  */
  895.     int n = state.control[1];
  896.     /*  Shift it left for one pixel  */
  897.     frame[n].dx++;
  898.     state.xf++;
  899.     draw_zoom(frame, n, state.blinker->zoom2W, state.xf, state.yf);
  900.     show_right_offsets(frame, n);
  901.     if (state.control[0] == state.control[1]) {
  902.       show_left_offsets(frame, n);
  903.       draw_zoom(frame, n, state.blinker->zoom1W, state.xf, state.yf);
  904.     }
  905.   }
  906. }
  907.  
  908. /*  Switch off image shifting mode  */
  909. void
  910. circleC(FL_OBJECT *obj, long val)
  911.  
  912. {
  913.   state.freeze = 0;
  914.   /*  Hide cursors and LOCKED ! sign  */
  915.   fl_hide_object(state.blinker->lockedW);
  916.   fl_hide_object(state.blinker->upW);
  917.   fl_hide_object(state.blinker->downW);
  918.   fl_hide_object(state.blinker->rightW);
  919.   fl_hide_object(state.blinker->leftW);
  920.   fl_hide_object(state.blinker->circleW);
  921.   set_image(frame, state.control[1]);
  922.   if (!fl_get_button(state.blinker->playW) &&
  923.       state.control_num == 1) {
  924.     draw_image(frame, state.control[1]);
  925.   }
  926. }
  927.  
  928. /*=================================*/
  929. /*  Open telescope control window  */
  930. /*=================================*/
  931. void
  932. telescope_controlC(FL_OBJECT *obj, long val)
  933.  
  934. {
  935.   show_telescope_control();
  936. }
  937.  
  938.  
  939. int
  940. freeobj_blinkW_handle(FL_OBJECT *d, int event, FL_Coord mx, FL_Coord my, int key, void *xev)
  941.  
  942. {
  943.   GC gc;
  944.   Window win;
  945.   int w, h, w0, h0, x0, y0;
  946.   float kx, ky;
  947.   static int xp = 0, yp = 0;
  948.   int xmax, ymax;
  949.   int n;
  950.   static int out = 0;
  951.   char temp[20];
  952.   double r, rmin;
  953.   int i, imin;
  954.  
  955.   if ((state.frame_used == 0 && event != FL_DRAW) || out) return 1;
  956.   gc = fl_state[fl_get_form_vclass(state.blinker->blinker)].gc[0];
  957.   win = FL_ObjWin(d);
  958.   fl_winset(win);
  959.   n = state.control[state.control_num];
  960.   /*  Convert mouse coordinates to image coordinates  */
  961.   w = d->w;
  962.   h = d->h;
  963.   xmax = frame[n].fits.width;
  964.   ymax = frame[n].fits.height;
  965.   kx = (float) (xmax - 1) / (w - 1);
  966.   ky = (float) (ymax - 1) / (h - 1);
  967.   if (kx < ky) kx = ky;
  968.   w0 = (xmax - 1) / kx + 0.5;
  969.   h0 = (ymax - 1) / kx + 0.5;
  970.   x0 = d->x + (w - w0) / 2 + 0.5;
  971.   y0 = d->y + (h - h0) / 2 + 0.5;
  972.  
  973.   switch(event) {
  974.   case FL_STEP:
  975.     break;
  976.   case FL_DRAW:
  977.     if (state.bw != w || state.bh != h) {
  978.       int i;
  979.       out = 1;
  980.       fl_addto_form(state.blinker->blinker);
  981.       /*  Delete free object  */
  982.       fl_delete_object(state.blinker->blinkW);
  983.       /*  Add free object again  */
  984.       fl_get_winsize(FL_ObjWin(state.blinker->zoom1W), &w, &h);
  985.       h = state.blinker->zoom1W->y;
  986.       state.blinker->blinkW = 
  987.     fl_add_free(FL_NORMAL_FREE,10,
  988.             state.blinker->racoorW->y + state.blinker->racoorW->h + 5, 
  989.             w - 20, 
  990.             h - (state.blinker->racoorW->y + state.blinker->racoorW->h) - 10,
  991.             "",freeobj_blinkW_handle);
  992.       fl_set_object_boxtype(state.blinker->blinkW, FL_FRAME_BOX);
  993.       fl_end_form();
  994.       state.bw = state.blinker->blinkW->w;
  995.       state.bh = state.blinker->blinkW->h;
  996.       fl_get_winsize(win, &state.blinkwidth, &state.blinkheight);
  997.       /*  Free all of the existing pixmaps  */
  998.       for (i = state.frame_used - 1; i >= 0; i--) {
  999.     XFreePixmap(state.disp, frame[i].pixmap); 
  1000.       }
  1001.       /*  Create pixmaps with new dimensions and draw images into them  */
  1002.       for (i = 0; i < state.frame_used; i++) {
  1003.     frame[i].pixmap = 
  1004.       XCreatePixmap(state.disp, 
  1005.             FL_ObjWin(state.blinker->blinkW), 
  1006.             state.bw, state.bh, 
  1007.             fl_state[fl_get_form_vclass(state.blinker->blinker)].depth);
  1008.     set_image(frame, i); 
  1009.       }
  1010.       out = 0;
  1011.     }
  1012.     
  1013.     /*  redraw the form  */
  1014.     fl_redraw_object(state.blinker->bgroupW);
  1015.     if (state.frame_used > 0) {
  1016.       if (!state.freeze) {
  1017.     draw_zoom(frame, state.control[0], state.blinker->zoom1W, 
  1018.           xp - frame[n].dx + frame[state.control[0]].dx, 
  1019.           yp - frame[n].dy + frame[state.control[0]].dy);
  1020.     draw_zoom(frame, state.control[1], state.blinker->zoom2W, 
  1021.           xp - frame[n].dx + frame[state.control[1]].dx, 
  1022.           yp - frame[n].dy + frame[state.control[1]].dy);
  1023.       }
  1024.       draw_image(frame, n);
  1025.     }
  1026.     break;
  1027.   case FL_MOTION:
  1028.     /*  Determine image coordinates from the screen coordinates of the mouse  */
  1029.     xp = (mx - x0) * kx + frame[n].dx + 0.5;
  1030.     yp = (my - y0) * kx + frame[n].dy + 0.5;
  1031.     if (!state.freeze) {
  1032.       /*  Draw magnified images around mouse position in the window  */
  1033.       draw_zoom(frame, state.control[0], state.blinker->zoom1W, 
  1034.         xp - frame[n].dx + frame[state.control[0]].dx, 
  1035.         yp - frame[n].dy + frame[state.control[0]].dy);
  1036.       draw_zoom(frame, state.control[1], state.blinker->zoom2W, 
  1037.         xp - frame[n].dx + frame[state.control[1]].dx, 
  1038.         yp - frame[n].dy + frame[state.control[1]].dy);
  1039.     }
  1040.     fl_drawmode(GXcopy);
  1041.     XSetForeground(state.disp, gc, fl_get_pixel(state.blinker->xcoorW->col1));
  1042.     sprintf(temp, "%d", xp);
  1043.     fl_rectf(state.blinker->xcoorW->x, state.blinker->xcoorW->y,
  1044.        state.blinker->xcoorW->w, state.blinker->xcoorW->h,
  1045.          state.blinker->xcoorW->col1);
  1046.     fl_set_input(state.blinker->xcoorW, temp);
  1047.     sprintf(temp, "%d", yp);
  1048.     fl_rectf(state.blinker->ycoorW->x, state.blinker->ycoorW->y,
  1049.        state.blinker->ycoorW->w, state.blinker->ycoorW->h,
  1050.          state.blinker->ycoorW->col1);
  1051.     fl_set_input(state.blinker->ycoorW, temp);
  1052.     sprintf(temp, "%u", video_point(&(frame[n].fits), xp, yp));
  1053.     fl_rectf(state.blinker->valueW->x, state.blinker->valueW->y,
  1054.        state.blinker->valueW->w, state.blinker->valueW->h,
  1055.          state.blinker->valueW->col1);
  1056.     fl_set_input(state.blinker->valueW, temp);
  1057.  
  1058.     if (frame[n].fitsfile.wcs) {
  1059.       double ra, dec;
  1060.       int status = 0;
  1061.       fits_pix_to_world(xp + 1, yp + 1, 
  1062.            frame[n].fitsfile.crval1, frame[n].fitsfile.crval2, 
  1063.            frame[n].fitsfile.crpix1, frame[n].fitsfile.crpix2, 
  1064.            frame[n].fitsfile.cdelt1, frame[n].fitsfile.cdelt2, 
  1065.            frame[n].fitsfile.crot,
  1066.            frame[n].fitsfile.ctype,
  1067.            &ra, &dec, &status);
  1068.       if (!status) {
  1069.     int rah, ram, dech, decm, c;
  1070.     double ral, decl;
  1071.     ra /= 15.0;
  1072.     rah = (int) ra;
  1073.     ram = (int) ((ra - rah) * 60);
  1074.     ral = 60.0 * (60.0 * (ra - rah) - ram);
  1075.     if (dec < 0) {
  1076.       c = '-';
  1077.       dec = -dec;
  1078.     }
  1079.     else {
  1080.       c = '+';
  1081.     }
  1082.     dech = (int) dec;
  1083.     decm = (int) ((dec - abs(dech)) * 60);
  1084.     decl = 60.0 * (60.0 * (dec - abs(dech)) - decm);
  1085.     sprintf(temp, "%2d:%02d:%06.3f", rah, ram, ral);
  1086.     fl_rectf(state.blinker->racoorW->x, state.blinker->racoorW->y,
  1087.            state.blinker->racoorW->w, state.blinker->racoorW->h,
  1088.            state.blinker->racoorW->col1);
  1089.     fl_set_input(state.blinker->racoorW, temp);
  1090.     sprintf(temp, "%c%2d:%02d:%05.2f", c, dech, decm, decl);
  1091.     fl_rectf(state.blinker->deccoorW->x, state.blinker->deccoorW->y,
  1092.            state.blinker->deccoorW->w, state.blinker->deccoorW->h,
  1093.            state.blinker->deccoorW->col1);
  1094.     fl_set_input(state.blinker->deccoorW, temp);
  1095.       }
  1096.     }
  1097.     break;
  1098.   case FL_DBLCLICK:
  1099.     /*  Double click inside the image freezes images in zoom windows  */
  1100.     state.freeze = !state.freeze;
  1101.     if (!state.freeze) {
  1102.       circleC(0, 0);
  1103.     }      
  1104.     else {
  1105.       /*  Store coordinates  */
  1106.       state.xf = (mx - x0) * kx + frame[state.control[1]].dx + 0.5;
  1107.       state.yf = (my - y0) * kx + frame[state.control[1]].dy + 0.5;
  1108.       /*  Show cursors and LOCKED ! sign  */
  1109.       fl_show_object(state.blinker->lockedW);
  1110.       fl_show_object(state.blinker->upW);
  1111.       fl_show_object(state.blinker->downW);
  1112.       fl_show_object(state.blinker->rightW);
  1113.       fl_show_object(state.blinker->leftW);
  1114.       fl_show_object(state.blinker->circleW);
  1115.     }      
  1116.     break;
  1117.   case FL_PUSH:
  1118.     if (state.doastr && key == 1) {   /* If in astrometry mode, find the nearest star  */
  1119.       /*  Determine image coordinates from the screen coordinates of the mouse  */
  1120.       xp = (mx - x0) * kx + frame[n].dx + 0.5;
  1121.       yp = (my - y0) * kx + frame[n].dy + 0.5;
  1122.       /* Find the closest star from the star list  */
  1123.       rmin = 1e20;
  1124.       imin = -1;
  1125.       for (i = 0; i < frame[n].imagelist.n; i++) {
  1126.     r = fsqr(frame[n].imagelist.s[i].x - xp) + 
  1127.       fsqr(frame[n].imagelist.s[i].y - yp);
  1128.     if (r < rmin) {
  1129.       rmin = r;
  1130.       imin = i;
  1131.     }
  1132.       }
  1133.       if (rmin > 25) {
  1134.     fl_show_alert("No detected object within circle of r = 5 pixels!", "Try again!", "", 1);
  1135.       }
  1136.       else if ((frame[n].fits.aperture && 
  1137.         showcomet(frame, n, &frame[n].imagelist.s[imin], 0, frame[n].fitsfile.object)) ||
  1138.            (!frame[n].fits.aperture && 
  1139.         showstar(frame, n, &frame[n].imagelist.s[imin], 0, frame[n].fitsfile.object))) {
  1140.     char a[FLEN_VALUE];
  1141.     if (strlen(frame[n].fitsfile.object) > 7) 
  1142.       frame[n].fitsfile.object[8] = '\0';
  1143.     if (strlen(frame[n].fitsfile.object) > 0 && 
  1144.         isalpha(frame[n].fitsfile.object[0])) {
  1145.       sprintf(a, "     %-8s %c%4d %02d %8.5f %11s %11s                      %03d", 
  1146.           frame[n].fitsfile.object, 'C', frame[n].year, frame[n].month,
  1147.           frame[n].day + 
  1148.           (frame[n].hour + 
  1149.            (frame[n].minute + frame[n].second / 60.0) / 60.0) / 24.0,
  1150.           format_ra_mpc(frame[n].imagelist.s[imin].ra),
  1151.           format_dec_mpc(frame[n].imagelist.s[imin].dec), observatory.code);
  1152.     }
  1153.     else {
  1154.       int number = strtol(frame[n].fitsfile.object, NULL, 10);
  1155.       sprintf(a, "%05d         %c%4d %02d %8.5f %11s %11s                      %03d", 
  1156.           number, 'C', frame[n].year, frame[n].month,
  1157.           frame[n].day + 
  1158.           (frame[n].hour + 
  1159.            (frame[n].minute + frame[n].second / 60.0) / 60.0) / 24.0,
  1160.           format_ra_mpc(frame[n].imagelist.s[imin].ra),
  1161.           format_dec_mpc(frame[n].imagelist.s[imin].dec), observatory.code);
  1162.     }
  1163.     edit_mail(state.blinker->astrometryW, SEND_MAIL);
  1164.     fl_addto_browser(state.mail->messageW, a);
  1165.       }
  1166.     }
  1167.     if (key == 3) {   /* Find the nearest star  */
  1168.       /*  Determine image coordinates from the screen coordinates of the mouse  */
  1169.       xp = (mx - x0) * kx + frame[n].dx + 0.5;
  1170.       yp = (my - y0) * kx + frame[n].dy + 0.5;
  1171.       /* Find the closest star from the star list  */
  1172.       rmin = 1e20;
  1173.       imin = -1;
  1174.       for (i = 0; i < frame[n].imagelist.n; i++) {
  1175.     r = fsqr(frame[n].imagelist.s[i].x - xp) + 
  1176.       fsqr(frame[n].imagelist.s[i].y - yp);
  1177.     if (r < rmin) {
  1178.       rmin = r;
  1179.       imin = i;
  1180.     }
  1181.       }
  1182.       if (rmin > 25) {
  1183.       }
  1184.       else {
  1185.     if (frame[n].fits.aperture) {
  1186.       showcomet(frame, n, &frame[n].imagelist.s[imin], 1, frame[n].obj[imin].s);
  1187.     }
  1188.     else {
  1189.       showstar(frame, n, &frame[n].imagelist.s[imin], 1, frame[n].obj[imin].s);
  1190.     }
  1191.       }
  1192.     }
  1193.     break;
  1194.   case FL_RELEASE:
  1195.     break;
  1196.   case FL_MOUSE:  
  1197.     break;
  1198.   case FL_KEYBOARD:
  1199.     break;
  1200.   case FL_ENTER:
  1201.     fl_set_cursor(win, (state.doastr) ? XC_cross : XC_dotbox);
  1202.     break;
  1203.   case FL_LEAVE:
  1204.     fl_reset_cursor(win);
  1205.     XSetForeground(state.disp, gc, fl_get_pixel(state.blinker->xcoorW->col1));
  1206.     fl_rectf(state.blinker->xcoorW->x, state.blinker->xcoorW->y,
  1207.        state.blinker->xcoorW->w, state.blinker->xcoorW->h,
  1208.          state.blinker->xcoorW->col1);
  1209.     fl_set_input(state.blinker->xcoorW, "");
  1210.     fl_rectf(state.blinker->ycoorW->x, state.blinker->ycoorW->y,
  1211.        state.blinker->ycoorW->w, state.blinker->ycoorW->h,
  1212.          state.blinker->ycoorW->col1);
  1213.     fl_set_input(state.blinker->ycoorW, "");
  1214.     fl_rectf(state.blinker->racoorW->x, state.blinker->racoorW->y,
  1215.        state.blinker->racoorW->w, state.blinker->racoorW->h,
  1216.          state.blinker->racoorW->col1);
  1217.     fl_set_input(state.blinker->racoorW, "");
  1218.     fl_rectf(state.blinker->deccoorW->x, state.blinker->deccoorW->y,
  1219.        state.blinker->deccoorW->w, state.blinker->deccoorW->h,
  1220.          state.blinker->deccoorW->col1);
  1221.     fl_set_input(state.blinker->deccoorW, "");
  1222.     fl_rectf(state.blinker->valueW->x, state.blinker->valueW->y,
  1223.        state.blinker->valueW->w, state.blinker->valueW->h,
  1224.          state.blinker->valueW->col1);
  1225.     fl_set_input(state.blinker->valueW, "");
  1226.     break;
  1227.   }
  1228.   return 0;
  1229. }
  1230.  
  1231. void
  1232. colormapC(FL_OBJECT *obj, long val)
  1233.  
  1234. {
  1235.   switch (val) {
  1236.   case 1:
  1237.     define_greymap();
  1238.     break;
  1239.   case 2:
  1240.     define_colormap();
  1241.     break;
  1242.   }
  1243. }
  1244.  
  1245. /**********************************/
  1246. /* Switch display of markers      */
  1247. /**********************************/
  1248. void
  1249. markersC(FL_OBJECT *obj, long val)
  1250.  
  1251. {
  1252.   int n = state.control[state.control_num];
  1253.  
  1254.   if (state.frame_used > 0) {
  1255.     frame[n].objshow = fl_get_button(obj);
  1256.     if (!frame[n].objshow && frame[n].objnum > 0) {
  1257.       set_image(frame, n);
  1258.     }
  1259.     else {
  1260.       /*  Draw objects to the currently displayed image  */
  1261.       draw_objects(frame, n);
  1262.     }
  1263.     draw_image(frame, n);
  1264.   }
  1265. }
  1266.  
  1267. /*  Define the greymap  */
  1268. int
  1269. define_greymap(void)
  1270.  
  1271. {
  1272.   Visual *visual;
  1273.   int i, j;
  1274.   float k;
  1275.  
  1276.   visual = DefaultVisual(state.disp, DefaultScreen((state.disp)));
  1277.   /*  Get number of grey levels  */
  1278.   state.grey_max = min(visual->map_entries - FL_BUILT_IN_COLS, GREY_WANTED);
  1279.   state.grey_max--;
  1280.   for (i = 0; i <= state.grey_max; i++) 
  1281.     state.pixel[i] = i + FL_FREE_COL1;
  1282.   fl_free_pixels(state.pixel, state.grey_max + 1);
  1283.   k = 255.0 / state.grey_max;
  1284.   for (i = 0; i <= state.grey_max; i++) {
  1285.     j = (int) (i * k);
  1286.     fl_mapcolor(i + FL_FREE_COL1, j, j, j);
  1287.     state.pixel[i] = fl_get_pixel(state.pixel[i]);
  1288.   }
  1289.   for (i = 0; i < state.frame_used; i++) 
  1290.     set_image(frame, i);
  1291.   if (state.frame_used > 0)
  1292.     draw_image(frame, state.control[state.control_num]);
  1293.   state.color = 0;
  1294.   return 0;
  1295. }
  1296.  
  1297. /*  Define the colormap  */
  1298. int
  1299. define_colormap(void)
  1300.  
  1301. {
  1302.   Visual *visual;
  1303.   int i, j, step;
  1304.   static rgb[][3] = {{0,8,16}, {0,12,24}, {0,16,28}, {0,20,32},
  1305.              {4,20,36}, {4,24,40}, {4,28,40}, {4,28,44},
  1306.              {4,32,48}, {4,32,52}, {4,36,52}, {4,36,56},
  1307.              {4,40,56}, {4,40,60}, {4,40,60}, {4,44,64},
  1308.              {4,44,64}, {4,48,68}, {8,48,68}, {8,52,72},
  1309.              {8,52,72}, {8,56,76}, {8,56,76}, {8,60,76},
  1310.              {8,60,80}, {8,60,80}, {8,64,84}, {8,64,84},
  1311.              {12,68,84}, {12,68,88}, {12,72,88}, {12,72,88},
  1312.              {12,76,92}, {12,76,92}, {12,80,92}, {16,80,96},
  1313.              {16,80,96}, {16,84,96}, {16,84,100}, {16,88,100},
  1314.              {16,88,100}, {20,92,104}, {20,92,104}, {20,96,104},
  1315.              {20,96,108}, {20,100,108}, {24,100,108}, {24,104,108},
  1316.              {24,104,112}, {24,108,112}, {28,108,112}, {28,112,116},
  1317.              {28,112,116}, {28,116,116}, {32,116,116}, {32,120,120},
  1318.              {32,120,120}, {32,120,120}, {36,120,120}, {36,124,120},
  1319.              {36,124,116}, {36,124,116}, {36,124,116}, {40,128,116},
  1320.              {40,128,116}, {40,128,116}, {44,128,116}, {44,132,116},
  1321.              {44,132,116}, {44,132,116}, {48,132,116}, {48,136,116},
  1322.              {48,136,116}, {52,136,116}, {52,136,116}, {52,140,116},
  1323.              {52,140,116}, {56,140,116}, {56,140,116}, {56,140,116},
  1324.              {60,144,116}, {60,144,116}, {64,144,116}, {64,144,116},
  1325.              {64,148,116}, {68,148,116}, {68,148,116}, {68,148,116},
  1326.              {72,148,116}, {72,152,116}, {76,152,116}, {76,152,116},
  1327.              {76,152,116}, {80,152,116}, {80,156,116}, {84,156,116},
  1328.              {84,156,112}, {88,156,112}, {88,156,112}, {88,160,112},
  1329.              {92,160,112}, {92,160,112}, {96,160,112}, {96,160,112},
  1330.              {100,164,112}, {100,164,112}, {104,164,112}, {104,164,112},
  1331.              {108,164,112}, {108,168,116}, {112,168,116}, {112,168,116},
  1332.              {116,168,116}, {116,168,116}, {120,172,116}, {120,172,116},
  1333.              {124,172,116}, {124,172,116}, {128,172,116}, {128,172,116},
  1334.              {132,176,116}, {136,176,116}, {136,176,116}, {140,176,120},
  1335.              {140,176,120}, {144,180,120}, {144,180,120}, {148,180,120},
  1336.              {148,180,120}, {152,180,120}, {152,180,120}, {156,184,124},
  1337.              {156,184,124}, {160,184,124}, {160,184,124}, {164,184,124},
  1338.              {164,184,128}, {168,188,128}, {168,188,128}, {172,188,128},
  1339.              {172,188,132}, {176,188,132}, {176,188,132}, {180,192,132},
  1340.              {180,192,132}, {180,192,136}, {184,192,136}, {184,192,136},
  1341.              {188,192,140}, {188,196,140}, {188,196,140}, {192,196,140},
  1342.              {192,196,144}, {192,196,144}, {196,196,144}, {196,200,148},
  1343.              {196,200,148}, {200,200,148}, {200,200,152}, {200,200,152},
  1344.              {200,200,152}, {204,200,152}, {204,200,156}, {204,200,156},
  1345.              {204,200,156}, {204,200,156}, {204,204,160}, {204,204,160},
  1346.              {208,204,160}, {208,204,160}, {208,204,164}, {208,204,164},
  1347.              {208,204,164}, {208,204,168}, {208,204,168}, {212,208,168},
  1348.              {212,208,168}, {212,208,172}, {212,208,172}, {212,208,172},
  1349.              {212,208,176}, {216,212,176}, {216,212,176}, {216,212,180},
  1350.              {216,212,180}, {216,212,180}, {216,216,184}, {216,216,184},
  1351.              {220,216,184}, {220,216,188}, {220,216,188}, {220,220,188},
  1352.              {220,220,192}, {220,220,192}, {220,220,192}, {224,220,196},
  1353.              {224,224,196}, {224,224,196}, {224,224,200}, {224,224,200},
  1354.              {224,224,200}, {224,224,200}, {224,228,204}, {224,228,204},
  1355.              {224,228,204}, {224,228,204}, {228,228,208}, {228,228,208},
  1356.              {228,228,208}, {228,232,208}, {228,232,208}, {228,232,212},
  1357.              {228,232,212}, {228,232,212}, {228,232,212}, {228,232,216},
  1358.              {228,232,216}, {228,236,216}, {228,236,216}, {228,236,216},
  1359.              {228,236,220}, {228,236,220}, {228,236,220}, {228,236,220},
  1360.              {232,240,220}, {232,240,224}, {232,240,224}, {232,240,224},
  1361.              {232,240,224}, {232,240,224}, {232,240,224}, {232,240,228},
  1362.              {232,244,228}, {232,244,228}, {232,244,228}, {232,244,228},
  1363.              {232,244,232}, {232,244,232}, {232,244,232}, {232,244,232},
  1364.              {236,248,232}, {236,248,232}, {236,248,236}, {236,248,236},
  1365.              {236,248,236}, {236,248,236}, {236,248,236}, {236,248,236},
  1366.              {236,252,240}, {236,252,240}, {236,252,240}, {236,252,240},
  1367.              {236,252,240}, {236,252,240}, {236,252,240}};
  1368.   
  1369.   visual = DefaultVisual(state.disp, DefaultScreen((state.disp)));
  1370.   /*  Get number of colors levels  */
  1371.   state.grey_max = min(visual->map_entries - FL_BUILT_IN_COLS, GREY_WANTED);
  1372.   step = 256 / state.grey_max;
  1373.   state.grey_max--;
  1374.   for (i = 0; i <= state.grey_max; i++) 
  1375.     state.pixel[i] = i + FL_FREE_COL1;
  1376.   fl_free_pixels(state.pixel, state.grey_max + 1);
  1377.   j = 0;
  1378.   for (i = 0; i <= state.grey_max; i++) {
  1379.     fl_mapcolor(state.pixel[i], rgb[j][0], rgb[j][1], rgb[j][2]);
  1380.     state.pixel[i] = fl_get_pixel(state.pixel[i]);
  1381.     j += step;
  1382.   }
  1383.   for (i = 0; i < state.frame_used; i++) 
  1384.     set_image(frame, i);
  1385.   if (state.frame_used > 0)
  1386.     draw_image(frame, state.control[state.control_num]);
  1387.   state.color = 1;
  1388.   return 0;
  1389. }
  1390.  
  1391.  
  1392. void
  1393. tgui(int argc, char *argv[])
  1394.  
  1395. {
  1396.   FL_OBJECT *o;
  1397.   XEvent event;
  1398.   FL_IOPT opt;
  1399.   int op, i;
  1400.  
  1401.   opt.sharedColormap = 1;
  1402.   fl_set_defaults(FL_PDSharedMap, &opt);
  1403.   state.disp = fl_initialize(&argc, argv, "Blink", 0, 0);
  1404.   /*  Load the settings  */
  1405.   load_settings();
  1406.   check_catalogs();
  1407.   /*  Create the main form  */
  1408.   state.gui = create_form_setting();
  1409.   /*  Create the blinker  */
  1410.   state.blinker = create_form_blinker();
  1411.    /*  Disable ticks in grey level histogram and correction graphs */
  1412.   fl_set_xyplot_xtics(state.gui->firstgreyW, -1.0, -1.0);
  1413.   fl_set_xyplot_ytics(state.gui->firstgreyW, -1.0, -1.0);
  1414.   fl_set_xyplot_xtics(state.gui->firstgammaW, -1.0, -1.0);
  1415.   fl_set_xyplot_ytics(state.gui->firstgammaW, -1.0, -1.0);
  1416.   fl_set_xyplot_xtics(state.gui->secondgreyW, -1.0, -1.0);
  1417.   fl_set_xyplot_ytics(state.gui->secondgreyW, -1.0, -1.0);
  1418.   fl_set_xyplot_xtics(state.gui->secondgammaW, -1.0, -1.0);
  1419.   fl_set_xyplot_ytics(state.gui->secondgammaW, -1.0, -1.0);
  1420.  
  1421.   /*  "Press" the button of the first image  */
  1422.   fl_set_button(state.gui->firstimageW, 1); 
  1423.   fl_set_button(state.gui->secondimageW, 0);
  1424.   /* Set the upper and lower limit for interval between images  */
  1425.   fl_set_counter_bounds(state.blinker->deltatW, 0.0, 5.0);
  1426.   fl_set_counter_value(state.blinker->deltatW, state.delay);
  1427.   fl_set_counter_step(state.blinker->deltatW, 0.1, 0.1);
  1428.   /*  Hide the LOCKED ! sign and cursors */
  1429.   fl_hide_object(state.blinker->lockedW);
  1430.   fl_hide_object(state.blinker->upW);
  1431.   fl_hide_object(state.blinker->downW);
  1432.   fl_hide_object(state.blinker->rightW);
  1433.   fl_hide_object(state.blinker->leftW);
  1434.   fl_hide_object(state.blinker->circleW);
  1435.   /*  Dectivate input fields with coordinates and pixel value  */
  1436.   fl_deactivate_object(state.blinker->xcoorW);
  1437.   fl_deactivate_object(state.blinker->ycoorW);
  1438.   fl_deactivate_object(state.blinker->racoorW);
  1439.   fl_deactivate_object(state.blinker->deccoorW);
  1440.   fl_deactivate_object(state.blinker->valueW);
  1441.   /*  Set the help menu  */
  1442.   fl_set_menu(state.gui->helpW, " About | Manual ");
  1443.   /*  Set the astrometry menu  */
  1444.   fl_set_menu(state.blinker->astrometryW, " Edit parameters | Detect stars | Match stars | Save star list | Load star list | Do astrometry | | Options | Catalogs | Settings | Mail results | Show report");
  1445.   /*  Disable menu options  */
  1446.   fl_set_menu_item_mode(state.blinker->astrometryW, EDIT_PARAMETERS, FL_PUP_GREY);
  1447.   fl_set_menu_item_mode(state.blinker->astrometryW, DETECT_STARS, FL_PUP_GREY);
  1448.   fl_set_menu_item_mode(state.blinker->astrometryW, MATCH_STARS, FL_PUP_GREY);
  1449.   fl_set_menu_item_mode(state.blinker->astrometryW, SAVE_STAR_LIST, FL_PUP_GREY);
  1450.   fl_set_menu_item_mode(state.blinker->astrometryW, LOAD_STAR_LIST, FL_PUP_GREY);
  1451.   fl_set_menu_item_mode(state.blinker->astrometryW, DO_ASTROMETRY, FL_PUP_GREY);
  1452.   fl_set_menu_item_mode(state.blinker->astrometryW, EMPTY_ITEM1, FL_PUP_GREY);
  1453.   /*  Show the forms  */
  1454.   fl_show_form(state.gui->setting, FL_PLACE_MOUSE | FL_FIX_SIZE, FL_FULLBORDER, "Fitsblink");
  1455.   fl_set_form_minsize(state.blinker->blinker, 
  1456.     state.blinker->blinker->w / 2, state.blinker->blinker->h / 2);
  1457.   fl_set_form_size(state.blinker->blinker, state.blinkwidth, state.blinkheight);
  1458.   fl_show_form(state.blinker->blinker, FL_PLACE_FREE_CENTER, FL_FULLBORDER, "");
  1459.   fl_redraw_form(state.blinker->blinker);
  1460.   fl_set_form_title(state.blinker->blinker, "(no image)");
  1461.   /*  Store dimensions of the blinking area  */
  1462.   state.bw = state.blinker->blinkW->w;
  1463.   state.bh = state.blinker->blinkW->h;
  1464.   if (state.color) { 
  1465.     define_colormap();
  1466.     fl_set_button(state.blinker->greybutW, 0);
  1467.     fl_set_button(state.blinker->colorbutW, 1);
  1468.   }
  1469.   else {
  1470.     define_greymap();
  1471.     fl_set_button(state.blinker->greybutW, 1);
  1472.     fl_set_button(state.blinker->colorbutW, 0);
  1473.   }
  1474.  
  1475.  
  1476.   while ((op = getopt(argc, argv, "i:v")) != -1) {
  1477.     switch(op) {
  1478.     case 'i':
  1479.       /*  load  a .inp file  */
  1480.       load_file(optarg);
  1481.       break;
  1482.     case 'v':
  1483.       state.verbose = 1;
  1484.       break;
  1485.     case '?':
  1486.       switch(optopt) {
  1487.       default:
  1488.     fprintf(stderr, "Unknown option -%c ignored!\n", optopt);
  1489.     break;
  1490.       }
  1491.       break;
  1492.     }
  1493.   }
  1494.  
  1495.   /* Load the images  */
  1496.   for (i = optind; i < argc; i++) {
  1497.     char *fname;
  1498.     int j = i - optind;
  1499.  
  1500.     (state.frame_used)++;
  1501.     if (state.frame_used == state.frame_max) {
  1502.       int i;
  1503.       state.frame_max += FRAME_MAX;
  1504.       if ((frame = (BLINK_FRAME *) 
  1505.        realloc(frame, sizeof(BLINK_FRAME) * state.frame_max)) == NULL) {
  1506.     fprintf(stderr, "Out of memory, function loadC, variable frame\n");
  1507.     exit(1);
  1508.       }
  1509.       for (i = state.frame_used; i < state.frame_max; i++) {
  1510.     frame[i].gamx = NULL;
  1511.     frame[i].gamy = NULL;
  1512.     frame[i].kg = NULL;
  1513.     frame[i].histx = NULL;
  1514.     frame[i].histy = NULL;
  1515.     frame[i].name = NULL;
  1516.     frame[i].fits.image = NULL;
  1517.       }
  1518.     }
  1519.     frame[j].name = strdup(argv[i]);
  1520.     if (load_frame(frame, j)) {
  1521.       (state.frame_used)--;
  1522.       continue;
  1523.     }
  1524.     set_image(frame, j);
  1525.     /*  Add image name to choices  */
  1526.     fname = strrchr(argv[i], '/');
  1527.     if (!fname) fname = argv[i];
  1528.     else fname++;
  1529.     fl_addto_choice(state.gui->firstnameW, fname);
  1530.     fl_addto_choice(state.gui->secondnameW, fname);
  1531.     if (j == 0 || j == 1) {
  1532.       state.control[state.control_num] = j;
  1533.       /*  Write the file name into the input field,  */
  1534.       /*  draw histogram, grey level correction curve, translation and rotation  */
  1535.       show_frame_info(frame, j, 0);
  1536.       if (state.frame_used == 1) {
  1537.     state.control[1] = 0;
  1538.     show_frame_info(frame, j, 1);
  1539.       }
  1540.     }
  1541.   }
  1542.   do {
  1543.     o = fl_check_forms();
  1544.     if (o == FL_EVENT) {
  1545.       fl_XNextEvent(&event);
  1546.     }
  1547.     else if (o == state.blinker->playW) {
  1548.       if (state.frame_used > 1 && fl_get_button(o)) {
  1549.     state.blink = 1;
  1550.     state.blinknum = 0;
  1551.       }
  1552.       else {
  1553.     fl_set_button(o, 0);
  1554.     state.blink = 0;
  1555.     if (state.frame_used > 0) 
  1556.       draw_image(frame, state.control[state.control_num]);
  1557.       }
  1558.     } else if (state.b[0] && o == state.browser[0]->closeeditW) {
  1559.       fl_clear_browser(state.browser[0]->browseW);
  1560.       fl_hide_form(state.browser[0]->Edit);
  1561.       fl_activate_object(state.gui->firstfitsW);
  1562.       state.b[0] = 0;
  1563.     } else if (state.b[1] && o == state.browser[1]->closeeditW) {
  1564.       fl_clear_browser(state.browser[1]->browseW);
  1565.       fl_hide_form(state.browser[1]->Edit);
  1566.       fl_activate_object(state.gui->secondfitsW);
  1567.       state.b[1] = 0;
  1568.     } else if (state.readme && o == state.readme->closehelpW) {
  1569.       fl_hide_form(state.readme->help);
  1570.       fl_set_menu_item_mode(state.gui->helpW, 2, FL_PUP_NONE);
  1571.     } else if (state.parameters && o == state.parameters->parokW) {
  1572.       fl_hide_form(state.parameters->Parameters);
  1573.       fl_set_menu_item_mode(state.blinker->astrometryW, EDIT_PARAMETERS, FL_PUP_NONE);
  1574.       fl_set_menu_item_mode(state.blinker->astrometryW, DETECT_STARS, FL_PUP_NONE);
  1575.     } else if (state.options && o == state.options->acceptoptionsW) {
  1576.       fl_hide_form(state.options->Options);
  1577.       fl_set_menu_item_mode(state.blinker->astrometryW, OPTIONS, FL_PUP_NONE);
  1578.     } else if (state.catalogs && o == state.catalogs->okcatalogsW) {
  1579.       fl_hide_form(state.catalogs->Catalog);
  1580.       fl_set_menu_item_mode(state.blinker->astrometryW, CATALOGS, FL_PUP_NONE);
  1581.     } else if (state.mail && o == state.mail->closemailW) {
  1582.       fl_hide_form(state.mail->Mail);
  1583.       fl_set_menu_item_mode(state.blinker->astrometryW, SEND_MAIL, FL_PUP_NONE);
  1584.     }
  1585.     else if (state.report && o == state.report->closereportW) {
  1586.       hide_report();
  1587.     }
  1588.     else if (state.telescope && o == state.telescope->telcloseW) {
  1589.       fl_remove_timeout(state.timeout);
  1590.       fl_hide_form(state.telescope->Telescope);
  1591.     }
  1592.  
  1593.     if (state.blink) do_blink();
  1594.   } while(1);
  1595. }
  1596.