#ifndef lint static char SccsId[] = "%W% %G%"; #endif /* Module: mainkey.c (Main Key) * Purpose: Dispatch responses mapped to various keyboard keys * Subroutine: key_response() returns: void * Subroutine: set_iraf_key_trigger() returns: void * Xlib calls: XWarpPointer(), XSync() * Copyright: 1999 Smithsonian Astrophysical Observatory * You may do anything you like with this file except remove * this copyright. The Smithsonian Astrophysical Observatory * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. */ #include #include /* X window stuff */ #include /* X window manager stuff */ #include #include #include "hfiles/constant.h" /* Define codes */ #include "hfiles/struct.h" /* Declare structure types */ #include "hfiles/extern.h" /* Extern main parameter structures */ #define MAX_MAPPED_STRING_LENGTH 16 #define MetaMask Mod1Mask #ifdef ANSIC /* Exported declarations must be centralized before ANSI C can be used */ void grab_keys_for_textcursor( int state); void set_iraf_key_trigger( int state); void key_response(); void set_zoom (double zoom_factor, int *direction, double xzoom, double yzoom); #else void set_zoom (); #endif static int textcursor = 0; /* Subroutine: grab_keys_for_textcursor * Purpose: Direct all key input to the text cursor editor */ #ifdef ANSIC void grab_keys_for_textcursor ( int state ) #else void grab_keys_for_textcursor ( state ) int state; #endif { textcursor = state; } #ifdef IMTOOL static int iraf_trigger = 0; /* Subroutine: set_iraf_key_trigger * Purpose: Set and clear trigger for cursor readback through IRAF pipe */ #ifdef ANSIC void set_iraf_key_trigger ( int state ) #else void set_iraf_key_trigger ( state ) int state; #endif { iraf_trigger = state; } #endif static int direction = 1; static double oldxpix = 0.0; static double oldypix = 0.0; /* Subroutine: key_response * Purpose: Respond to a key stroke */ void key_response() { KeySym keysym; XComposeStatus compose; int char_cnt; int x, y; char vstring[16]; char string[16]; int ix,iy,lstr; int quadcube; double xcent,ycent; static int bufsize = MAX_MAPPED_STRING_LENGTH; char buffer[MAX_MAPPED_STRING_LENGTH]; #ifdef IMTOOL int trigger_curpos_to_iraf(); #endif void magnify_pan(), magnify_disp(), say_goodbye(), disp_panbox(); void disp_dispbox(), raise_windows(), get_new_cmd(), print_table(); void ascii_region(), textcursor_keyentry(); void print_center(), print_cursor(); void move_pointer(); void get_cursor_pos(); static void PrintFITSHead(); void toggle_region_visibility(), toggle_region_labeling(); double xbuf, ybuf, xfile, yfile; double oldxpos, oldypos, newxpos, newypos, distance; char sysout0[16]; char wcstr[32]; int lwcstr = 32; if (iswcs(wcs) && (wcs->prjcode == WCS_CSC || wcs->prjcode == WCS_QSC || wcs->prjcode == WCS_TSC)) quadcube = 1; else quadcube = 0; /* Decode the key event to ascii */ char_cnt = XLookupString(&control.event.xkey, buffer, bufsize, &keysym, &compose); /* Key input from display window may be redirected for special purposes */ if( control.event.xkey.window == dispbox.ID ) { #ifdef IMTOOL if( iraf_trigger && (char_cnt == 1) && trigger_curpos_to_iraf(&control.event.xkey, (int)buffer[0]) ) return; #endif /* Redirect keyboard input for textcursor editor */ if( textcursor ) { textcursor_keyentry(&control.event.xkey, keysym); return; } } /* Ignore modifier key pressing */ if( ((control.event.xkey.state & (ControlMask | MetaMask)) == 0) || (keysym >= XK_BackSpace) ) { switch( keysym ) { /* Don't update tracking now if in IRAF interactive mode */ case XK_Shift_L: case XK_Shift_R: #ifdef IMTOOL if( iraf_trigger ) return; #endif if( control.event.xkey.window == panbox.ID ) { /* Update magnifier if in panbox */ magnify_pan (&control.event); } else if( (control.event.xkey.window == dispbox.ID) && (!control.magni_track) ) { /* If in disp window and not now tracking, update magnifier */ magnify_disp (&control.event, 1, !control.coord_track); } break; #ifdef SUN /* Shifted arrow keys on Sun keypad */ case XK_R8: case XK_R10: case XK_R12: case XK_R14: if( keysym == XK_R8 ) keysym = XK_Up; else if( keysym == XK_R10 ) keysym = XK_Left; else if( keysym == XK_R12 ) keysym = XK_Right; else if( keysym == XK_R14 ) keysym = XK_Down; #endif /* Use the mouse coordinates at time of key strike */ case XK_Up: case XK_Down: case XK_Left: case XK_Right: if( keysym == XK_Up ) y = control.event.xkey.y - 1; else if( keysym == XK_Down ) y = control.event.xkey.y + 1; else y = control.event.xkey.y; if( keysym == XK_Right ) x = control.event.xkey.x + 1; else if( keysym == XK_Left ) x = control.event.xkey.x - 1; else x = control.event.xkey.x; /* Move the mouse (supercede any recent mouse movement) */ XSync (control.event.xkey.display, 0); XWarpPointer(control.event.xkey.display, None, control.event.xkey.window, 0, 0, 0, 0, x, y); break; /* Center cursor in image */ case XK_Home: move_pointer (control.event.xkey.display, control.event.xkey.window, img.filecols/2, img.filerows/2); break; /* Raise all windows out of chaos */ case XK_A: case XK_a: disp_panbox(); disp_dispbox(); raise_windows(); break; /* Debugging print_table without scaling (fool it about scaling) */ case XK_L: case XK_l: x = img.fiscaled; img.fiscaled = 0; print_table(); img.fiscaled = x; break; /* Open a new image file (see CmdNew.c) */ case XK_N: case XK_n: get_new_cmd(); break; /* #ifdef QUITKEY */ case XK_Q: case XK_q: /* q FOR QUIT */ if (!img.imtool_200) say_goodbye(0); break; /* #endif */ case XK_R: case XK_r: raise_windows(); break; /* Print table of image values if in display or pan windows */ case XK_T: case XK_t: print_table(); break; /* Character control in region (cursor) mode */ case XK_Delete: case XK_D: case XK_d: case XK_E: case XK_e: case XK_S: case XK_s: if (control.mode == COP ) { if ((control.event.xkey.window == dispbox.ID) || (cursor.type == COP_Text) ) ascii_region(&control.event.xkey, keysym); } else if (keysym == XK_E || keysym == XK_e) { wcsoutinit (wcs,"ECLIPTIC"); magnify_disp (&control.event, 0, 1); } break; /* Toggle region visibility */ case XK_bracketleft: toggle_region_visibility(); break; /* Toggle region labelling */ case XK_bracketright: toggle_region_labeling(); break; /* Read next image in a 3-D image */ case XK_plus: case XK_equal: if (img.nimage < img.filenimg) { img.nimage = img.nimage + 1; if (quadcube) (void)wcszin (img.nimage-1); else (void)wcszin (img.nimage); (void)new_image(); magnify_disp (&control.event, 0, 1); } break; /* Read previous image in a 3-D image */ case XK_minus: if (img.nimage > 1) { img.nimage = img.nimage - 1; (void)new_image(); if (quadcube) (void)wcszin (img.nimage-1); else (void)wcszin (img.nimage); magnify_disp (&control.event, 0, 1); } break; /* Print current FITS header to standard output */ case XK_F: case XK_f: PrintFITSHead (img.header); break; /* save current cursor position within image in pixel list file */ case XK_P: case XK_p: /* Center image at zoom 1x */ case XK_0: if (quadcube) { (void)wcszin (0); img.nimage = 1; (void)new_image(); magnify_disp (&control.event, 0, 1); } else { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); set_zoom (0.0, &direction, xbuf, ybuf); } break; /* Move directly to first image or zoom 1x */ case XK_1: if (img.filenimg > 1) { (void)wcszin (1); if (quadcube) img.nimage = 2; else img.nimage = 1; (void)new_image(); magnify_disp (&control.event, 0, 1); } else { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); set_zoom (1.0, &direction, xbuf, ybuf); } break; /* Move directly to second image or zoom 2x */ case XK_2: if (img.filenimg > 1) { (void)wcszin (2); if (quadcube) img.nimage = 3; else img.nimage = 2; (void)new_image(); magnify_disp (&control.event, 0, 1); } else { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); set_zoom (2.0, &direction, xbuf, ybuf); } break; /* Move directly to third image or zoom 3x */ case XK_3: if (img.filenimg > 2) { (void)wcszin (3); if (quadcube) img.nimage = 4; else img.nimage = 3; (void)new_image(); magnify_disp (&control.event, 0, 1); } else if (img.filenimg < 2) { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); set_zoom (3.0, &direction, xbuf, ybuf); } break; /* Move directly to fourth image or zoom 4x */ case XK_4: if (img.filenimg > 3) { (void)wcszin (4); if (quadcube) img.nimage = 5; else img.nimage = 4; (void)new_image(); magnify_disp (&control.event, 0, 1); } else if (img.filenimg < 2) { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); set_zoom (4.0, &direction, xbuf, ybuf); } break; /* Move directly to fifth image or zoom 5x */ case XK_5: if (img.filenimg > 4) { (void)wcszin (5); if (quadcube) img.nimage = 6; else img.nimage = 5; (void)new_image(); magnify_disp (&control.event, 0, 1); } else if (img.filenimg < 2) { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); set_zoom (5.0, &direction, xbuf, ybuf); } break; /* Move directly to sixth image or zoom 6x */ case XK_6: if (img.filenimg > 5 && !quadcube) { img.nimage = 6; (void)wcszin (img.nimage); (void)new_image(); magnify_disp (&control.event, 0, 1); } else if (img.filenimg < 2) { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); set_zoom (6.0, &direction, xbuf, ybuf); } break; /* Move directly to seventh image or zoom 7x */ case XK_7: if (img.filenimg > 6) { img.nimage = 7; (void)new_image(); (void)wcszin (img.nimage); magnify_disp (&control.event, 0, 1); } else if (img.filenimg < 2) { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); set_zoom (7.0, &direction, xbuf, ybuf); } break; /* Move directly to eighth image or zoom 8x */ case XK_8: if (img.filenimg > 7) { img.nimage = 8; (void)new_image(); (void)wcszin (img.nimage); magnify_disp (&control.event, 0, 1); } else if (img.filenimg < 2) { direction = 1.0; (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); set_zoom (8.0, &direction, xbuf, ybuf); } break; /* Move directly to ninth image or zoom 9x */ case XK_9: if (img.filenimg > 8) { img.nimage = 9; (void)new_image(); (void)wcszin (img.nimage); magnify_disp (&control.event, 0, 1); } else if (img.filenimg < 2) { direction = 1.0; (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); set_zoom (9.0, &direction, xbuf, ybuf); } break; /* Change coordinate system in which cursor tracking is occurring */ case XK_B: case XK_b: wcsoutinit (wcs,"B1950"); magnify_disp (&control.event, 0, 1); break; case XK_G: case XK_g: wcsoutinit (wcs,"GALACTIC"); magnify_disp (&control.event, 0, 1); break; case XK_I: case XK_i: wcsoutinit (wcs,"imsys"); magnify_disp (&control.event, 0, 1); break; case XK_J: case XK_j: wcsoutinit (wcs,"J2000"); magnify_disp (&control.event, 0, 1); break; /* Toggle WCS output between degrees and h:m:s d:m:s */ case XK_H: case XK_h: if (iswcs (wcs)) { if (wcs->degout) { wcs->degout = 0; wcs->ndec = 3; } else { wcs->degout = 1; wcs->ndec = 6; } } magnify_disp (&control.event, 0, 1); break; /* Print cursor position to standard output */ case XK_C: case XK_c: print_cursor (&control.event, 1); if (iswcs (wcs)) { oldxpos = wcs->xpos; oldypos = wcs->ypos; oldxpix = wcs->xpix; oldypix = wcs->ypix; } break; /* Print distance since last cursor position to standard output */ case XK_V: case XK_v: if (iswcs (wcs)) { print_cursor (&control.event, 1); newxpos = wcs->xpos; newypos = wcs->ypos; distance = wcsdist (oldxpos, oldypos, newxpos, newypos); printf ("Separation is %.5f degrees or %.2f arcseconds\n", distance, distance/3600.0); oldxpos = wcs->xpos; oldypos = wcs->ypos; } break; /* Use WCS and image coordinates of cursor with an external command */ case XK_W: case XK_w: if (iswcs (wcs)) { (void)get_cursor_pos (&control.event,&xbuf,&ybuf,&xfile,&yfile); pix2wcst (wcs, xfile, yfile, wcstr, lwcstr); if (oldxpix != 0.0 && oldypix != 0.0) { wcscom (wcs, 0, img.filename, oldxpix, oldypix, wcstr); oldxpix = 0.0; oldypix = 0.0; } else { wcscom (wcs, 0, img.filename, xfile, yfile, wcstr); } } break; case XK_X: case XK_x: print_center (&oldxpix, &oldypix); break; /* Toggle between AIPS and WCSLIB WCS subroutines */ case XK_Z: if (iswcs (wcs)) { if (wcs->wcsproj == WCS_BEST) wcs->wcsproj = WCS_ALT; else wcs->wcsproj = WCS_BEST; } magnify_disp (&control.event, 0, 1); break; case XK_z: set_zoom (99.0, &direction, xbuf, ybuf); break; /* Use WCS and image coordinates of cursor with an external command */ case XK_F1: if (iswcs (wcs)) { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); pix2wcst (wcs, xfile, yfile, wcstr, lwcstr); wcscom (wcs, 1, img.filename, xfile, yfile, wcstr); } break; case XK_F2: if (iswcs (wcs)) { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); pix2wcst (wcs, xfile, yfile, wcstr, lwcstr); wcscom (wcs, 2, img.filename, xfile, yfile, wcstr); } break; case XK_F3: if (iswcs (wcs)) { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); pix2wcst (wcs, xfile, yfile, wcstr, lwcstr); wcscom (wcs, 3, img.filename, xfile, yfile, wcstr); } break; case XK_F4: if (iswcs (wcs)) { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); pix2wcst (wcs, xfile, yfile, wcstr, lwcstr); wcscom (wcs, 4, img.filename, xfile, yfile, wcstr); } break; case XK_F5: if (iswcs (wcs)) { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); pix2wcst (wcs, xfile, yfile, wcstr, lwcstr); wcscom (wcs, 5, img.filename, xfile, yfile, wcstr); } break; case XK_F6: if (iswcs (wcs)) { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); pix2wcst (wcs, xfile, yfile, wcstr, lwcstr); wcscom (wcs, 6, img.filename, xfile, yfile, wcstr); } break; case XK_F7: if (iswcs (wcs)) { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); pix2wcst (wcs, xfile, yfile, wcstr, lwcstr); wcscom (wcs, 7, img.filename, xfile, yfile, wcstr); } break; case XK_F8: if (iswcs (wcs)) { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); pix2wcst (wcs, xfile, yfile, wcstr, lwcstr); wcscom (wcs, 8, img.filename, xfile, yfile, wcstr); } break; case XK_F9: if (iswcs (wcs)) { (void)get_cursor_pos (&control.event, &xbuf, &ybuf, &xfile, &yfile); pix2wcst (wcs, xfile, yfile, wcstr, lwcstr); wcscom (wcs, 9, img.filename, xfile, yfile, wcstr); } break; /* Print all cursor commands to standard output */ case XK_question: printf ("SAOimage keyboard commands:\n"); printf ("A rAises all SAOimage windows to the top and refresh\n"); printf ("B tracks coordinates of cursor in B1950 (FK4) coordinates\n"); printf ("C prints Coordinates of cursor (x,y, current WCS if present)\n"); printf ("D Deletes the smallest region enclosing the mouse\n"); printf ("E tracks cursor coordinates in Ecliptic coordinates\n"); printf (" saves current cursor as an excluded region in Region mode\n"); printf ("F print FITS header to standard output (for .imh images, too)\n"); printf ("G tracks cursor coordinates in Galactic coordinates\n"); printf ("H toggles cursor coordinates between degrees and hh: dd: \n"); printf ("I tracks cursor coordinates in coordinate system of image\n"); printf ("J tracks cursor coordinates in J2000 (FK5) coordinates\n"); printf ("L prints distance since last position, assuming same system\n"); printf ("N enters New command-line arguments\n"); printf ("Q Quits SAOimage\n"); printf ("R Raises all SAOimage windows to the top\n"); printf ("S Saves current cursor as an included region\n"); printf ("T prints table of the pixel values around current mouse position\n"); printf ("V prints distance since last position, assuming same system\n"); printf ("W executes WCS command\n"); printf ("X prints centroid coordinates of cursor (X,y, WCS if present)\n"); printf ("z zooms in and out by factor of two each time it is pressed\n"); printf ("+ or = gets next image from 3-D image file\n"); printf ("- gets previous image from 3-D image file\n"); printf ("1-9 gets nth image from 3-D image file or zooms n times\n"); printf ("[ toggles display of regions or overplotted catalogs\n"); printf ("] toggles display of labels of regions or overplotted catalogs\n"); printf ("shift stops tracking while cursor is moved\n"); printf ("arrow keys move the cursor\n"); break; default: break; } } } /* * Subroutine: new_image * Purpose: Having the image record set, do all that is needed to load * a new image from the same file */ static int new_image ( ) { int init_image(), init_imagebuf(); void set_tdisp(), new_display(), new_panbox(), disp_panbox(); /* get the image dimensions (need file name, type) */ if( init_image() == 0 ) return(0); /* resize the image buffer */ (void)init_imagebuf(); /* set display params and force reassessing and rescaling the image */ set_tdisp(&coord); buffer.mm.img_leftX = coord.id.srcX1 + 1; /* read new image data */ new_display(1, 1, 1, 1); /* replace the panbox with a new one */ new_panbox(1); disp_panbox(); return( 1 ); } #ifdef ANSIC static void PrintFITSHead (char *header) #else static void PrintFITSHead (header) char *header; /* Image FITS header */ #endif { char line[80], *iline, *endhead; int i, nblank; endhead = ksearch (header, "END") + 80; if (endhead == NULL) return; nblank = 0; for (iline = header; iline < endhead; iline = iline + 80) { strncpy (line, iline, 80); i = 79; while (line[i] <= 32 && i > 0) line[i--] = 0; if (i > 0) { if (nblank > 1) { printf ("COMMENT %d blank lines\n",nblank); nblank = 0; } else if (nblank > 0) { printf ("COMMENT %d blank line\n",nblank); nblank = 0; } printf ("%s\n",line); } else nblank++; } return; } /* June 29 1989 Michael VanHilst initial version * Aug 16 1989 MVH display window key to trigger IRAF write * * Jun 1 1991 MVH support for text cursor * * Oct 27 1994 Doug Mink - support for centroid * * Jun 21 1995 DJM - add help * Jul 6 1995 DJM - reword wcs calls * Aug 17 1995 DJM - add coordinate conversion * * Jan 24 1996 DJM - only change system for J,G,B * Feb 9 1996 DJM - Do not quit with q if imtool * Sep 6 1996 DJM - Pass filename to wcscom() * * Feb 18 1998 DJM - Switch between WCS subroutines * Apr 14 1998 DJM - Add e for ecliptic coordinates * May 13 1998 DJM - Add i for image coordinate system * May 29 1998 DJM - Add h for degree/hms toggling * Jul 13 1998 DJM - Call wcszin() when changing frame * Jul 16 1998 DJM - Add get nth frame option * Aug 6 1998 DJM - Add get center option * Aug 14 1998 DJM - Add function key commands * Sep 29 1998 DJM - Add distance option * Oct 14 1998 DJM - Add [ ] to toggle region labels * Oct 14 1998 DJM - Add f to print FITS header * Oct 23 1998 DJM - Add z to zoom in and out * Oct 23 1998 DJM - Zoom with 1-9 if 2-d image * Nov 6 1998 DJM - Add 0 zoom and recenter * Nov 30 1998 Paul Sydney - Fix set_zoom() calls * Nov 30 1998 DJM - Add back region exculsion control * * Feb 23 1999 DJM - Set face for quad cube projections in +-012345 * Aug 16 1999 DJM - Set number of decimal places when toggling with H * Aug 20 1999 DJM - Add WCS string argument to wcscom(); decouple X Y * Aug 20 1999 DJM - Add coordinate return from print_center() * Aug 23 1999 DJM - Fix bug in oldxpix,oldypix saving */