Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

yemc.cc

Go to the documentation of this file.
00001 /*
00002   yemc.cc - new X GUI for the EMC, that splits Cartesian and joint modes
00003 
00004   Modification history:
00005 
00006   30-May-2001 WPS added reading EMC_NMLFILE to iniLoad().
00007   30-May-2001 WPS added reading EMC_DEBUG to iniLoad().
00008   16-Jan-2001 WPS added teleop mode stuff. The teleop mode is intended for joystick control of non-slideways machines. The "$" toggles on/off telop mode inaddition to toggling between world and joint display. When the display is world and mode manual the gui will use teleop mode and otherwise not.
00009   30-Mar-2000 WPS added ferrorCurrent and ferrorHighMark junk.
00010   20-Mar-2000 WPS made the EMC_DEBUG_NML flag enable NML error messages.
00011   3-Sep-1999  FMP looked in both [TASK] and [DISPLAY] for PROGRAM_PREFIX
00012   17-Aug-1999  FMP added pre-send of program open when stepping
00013   5-Aug-1999  FMP added POS_FRAME for world, joint coords, and menu to
00014   select this
00015   3-Aug-1999  FMP created from xemc.cc; changed XEMC_NUM_AXES to 6;
00016   changed posLabel[] array to be index-based rather than hard-coded
00017  */
00018 
00019 #include <stdio.h>
00020 #include <string.h>
00021 #include <stdlib.h>
00022 #include <ctype.h>
00023 #include <values.h>             // DBL_MAX, maybe
00024 #include <limits.h>             // DBL_MAX, maybe
00025 #include <stdarg.h>
00026 #include <sys/stat.h>           // struct stat, stat()
00027 #include <unistd.h>
00028 #include <fcntl.h>              // O_CREAT
00029 
00030 #include "rcs.hh"               // etime()
00031 #include "emc.hh"               // EMC NML
00032 #include "emcglb.h"             // EMC_NMLFILE, TRAJ_MAX_VELOCITY, TOOL_TABLE_FILE
00033 #include "emccfg.h"             // DEFAULT_TRAJ_MAX_VELOCITY
00034 #include "inifile.h"            // INIFILE
00035 #include "posemath.h"           // PmPose, pmQuatRpyConvert(), etc.
00036 #include "emcpos.h"             // EmcPose
00037 
00038 /*
00039  * Include files required for all Toolkit programs
00040  */
00041 #include <X11/Intrinsic.h>      /* Intrinsics Definitions */
00042 #include <X11/StringDefs.h>     /* Standard Name-String definitions */
00043 
00044 /*
00045  * Public include file for widgets we actually use in this file.
00046  */
00047 #include <X11/Xaw/Form.h>
00048 #include <X11/Xaw/Box.h>
00049 #include <X11/Xaw/Command.h>
00050 #include <X11/Xaw/Label.h>
00051 #include <X11/Xaw/AsciiText.h>
00052 #include <X11/Xaw/MenuButton.h>
00053 #include <X11/Xaw/SimpleMenu.h>
00054 #include <X11/Xaw/SmeBSB.h>
00055 #include <X11/Xaw/SmeLine.h>
00056 #include <X11/Xaw/Dialog.h>
00057 
00058 #define UPDATE_MSECS 100
00059 
00060 // the NML channels to the EMC task
00061 static RCS_CMD_CHANNEL *emcCommandBuffer = 0;
00062 static RCS_STAT_CHANNEL *emcStatusBuffer = 0;
00063 EMC_STAT *emcStatus = 0;
00064 
00065 // the NML channel for errors
00066 static NML *emcErrorBuffer = 0;
00067 static char error_string[EMC_OPERATOR_ERROR_LEN] = "";
00068 
00069 // the current command numbers, set up updateStatus(), used in main()
00070 static int emcCommandSerialNumber = 0;
00071 
00072 static int coordNum[6] = { 0, 1, 2, 3, 4, 5};
00073 // forward decls
00074 
00075 // forward decls for error popup
00076 static void errorReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params);
00077 static void errorDoneCB(Widget w, XtPointer client_data, XtPointer call_data);
00078 static int createErrorShell();
00079 static int destroyErrorShell();
00080 static void popupError(const char *fmt, ...);
00081 
00082 // forward decl for quit() function
00083 static void quit();
00084 
00085 static int emcTaskNmlGet()
00086 {
00087   int retval = 0;
00088 
00089   // try to connect to EMC cmd
00090   if (emcCommandBuffer == 0)
00091     {
00092       emcCommandBuffer = new RCS_CMD_CHANNEL(emcFormat, "emcCommand", "xemc", EMC_NMLFILE);
00093       if (! emcCommandBuffer->valid())
00094         {
00095           delete emcCommandBuffer;
00096           emcCommandBuffer = 0;
00097           retval = -1;
00098         }
00099     }
00100 
00101   // try to connect to EMC status
00102   if (emcStatusBuffer == 0)
00103     {
00104       emcStatusBuffer = new RCS_STAT_CHANNEL(emcFormat, "emcStatus", "xemc", EMC_NMLFILE);
00105       if (! emcStatusBuffer->valid() ||
00106           EMC_STAT_TYPE != emcStatusBuffer->peek())
00107         {
00108           delete emcStatusBuffer;
00109           emcStatusBuffer = 0;
00110           emcStatus = 0;
00111           retval = -1;
00112         }
00113       else
00114         {
00115           emcStatus = (EMC_STAT *) emcStatusBuffer->get_address();
00116         }
00117     }
00118 
00119   return retval;
00120 }
00121 
00122 static int emcErrorNmlGet()
00123 {
00124   int retval = 0;
00125 
00126   if (emcErrorBuffer == 0)
00127     {
00128       emcErrorBuffer = new NML(nmlErrorFormat, "emcError", "xemc", EMC_NMLFILE);
00129       if (! emcErrorBuffer->valid())
00130         {
00131           delete emcErrorBuffer;
00132           emcErrorBuffer = 0;
00133           retval = -1;
00134         }
00135     }
00136 
00137   return retval;
00138 }
00139 
00140 static void printError(char *error)
00141 {
00142   printf("%s\n", error);
00143 }
00144 
00145 static int updateStatus()
00146 {
00147   NMLTYPE type;
00148 
00149   if (0 == emcStatus ||
00150       0 == emcStatusBuffer ||
00151       ! emcStatusBuffer->valid())
00152     {
00153       return -1;
00154     }
00155 
00156   switch (type = emcStatusBuffer->peek())
00157     {
00158     case -1:
00159       // error on CMS channel
00160       return -1;
00161       break;
00162 
00163     case 0:                     // no new data
00164     case EMC_STAT_TYPE: // new data
00165       // new data
00166       break;
00167 
00168     default:
00169       return -1;
00170       break;
00171     }
00172 
00173   return 0;
00174 }
00175 
00176 static int updateError()
00177 {
00178   NMLTYPE type;
00179 
00180   if (0 == emcErrorBuffer ||
00181       ! emcErrorBuffer->valid())
00182     {
00183       return -1;
00184     }
00185 
00186   switch (type = emcErrorBuffer->read())
00187     {
00188     case -1:
00189       // error reading channel
00190       return -1;
00191       break;
00192 
00193     case 0:
00194       // nothing new
00195       error_string[0] = 0;
00196       break;
00197 
00198     case EMC_OPERATOR_ERROR_TYPE:
00199       strncpy(error_string,
00200              ((EMC_OPERATOR_ERROR *) (emcErrorBuffer->get_address()))->error,
00201               EMC_OPERATOR_ERROR_LEN - 1);
00202       error_string[EMC_OPERATOR_ERROR_LEN - 1] = 0;
00203       break;
00204 
00205     case EMC_OPERATOR_TEXT_TYPE:
00206       strncpy(error_string,
00207              ((EMC_OPERATOR_TEXT *) (emcErrorBuffer->get_address()))->text,
00208               EMC_OPERATOR_ERROR_LEN - 1);
00209       error_string[EMC_OPERATOR_ERROR_LEN - 1] = 0;
00210       break;
00211 
00212     case EMC_OPERATOR_DISPLAY_TYPE:
00213       strncpy(error_string,
00214              ((EMC_OPERATOR_DISPLAY *) (emcErrorBuffer->get_address()))->display,
00215               EMC_OPERATOR_ERROR_LEN - 1);
00216       error_string[EMC_OPERATOR_ERROR_LEN - 1] = 0;
00217       break;
00218 
00219     case NML_ERROR_TYPE:
00220       strncpy(error_string,
00221              ((NML_ERROR *) (emcErrorBuffer->get_address()))->error,
00222               NML_ERROR_LEN - 1);
00223       error_string[NML_ERROR_LEN - 1] = 0;
00224       break;
00225 
00226     case NML_TEXT_TYPE:
00227       strncpy(error_string,
00228              ((NML_TEXT *) (emcErrorBuffer->get_address()))->text,
00229               NML_ERROR_LEN - 1);
00230       error_string[NML_ERROR_LEN - 1] = 0;
00231       break;
00232 
00233     case NML_DISPLAY_TYPE:
00234       strncpy(error_string,
00235              ((NML_DISPLAY *) (emcErrorBuffer->get_address()))->display,
00236               NML_ERROR_LEN - 1);
00237       error_string[NML_ERROR_LEN - 1] = 0;
00238       break;
00239 
00240     default:
00241       sprintf(error_string, "unrecognized error %ld",type);
00242       return -1;
00243       break;
00244     }
00245 
00246   return 0;
00247 }
00248 
00249 #define EMC_COMMAND_TIMEOUT 1.0 // how long to wait until timeout
00250 #define EMC_COMMAND_DELAY   0.1 // how long to sleep between checks
00251 
00252 /*
00253   emcCommandWaitReceived() waits until the EMC reports that it got
00254   the command with the indicated serial_number.
00255   emcCommandWaitDone() waits until the EMC reports that it got the
00256   command with the indicated serial_number, and it's done, or error.
00257 */
00258 
00259 static int emcCommandWaitReceived(int serial_number)
00260 {
00261   double start = etime();
00262 
00263   while (etime() - start < EMC_COMMAND_TIMEOUT) {
00264     updateStatus();
00265 
00266     if (emcStatus->echo_serial_number == serial_number) {
00267       return 0;
00268     }
00269 
00270     esleep(EMC_COMMAND_DELAY);
00271   }
00272 
00273   return -1;
00274 }
00275 
00276 static int emcCommandWaitDone(int serial_number)
00277 {
00278   double start = etime();
00279 
00280   while (etime() - start < EMC_COMMAND_TIMEOUT) {
00281     updateStatus();
00282 
00283     if (emcStatus->echo_serial_number == serial_number) {
00284       if (emcStatus->status == RCS_DONE) {
00285         return 0;
00286       }
00287       else if (emcStatus->status == RCS_ERROR) {
00288         return -1;
00289       }
00290     }
00291 
00292     esleep(EMC_COMMAND_DELAY);
00293   }
00294 
00295   return -1;
00296 }
00297 
00298 /*
00299   functions for handling the windowing of a file, where you
00300   give the line you wish to window and it produces an array
00301   of string, or single string, of the file's contents
00302   at that point and some lines beyond
00303   */
00304 
00305 #define LF 10
00306 #define CR 13
00307 
00308 typedef struct {
00309   /* the array holding the window of lines in the file */
00310   char *fileWindow;
00311 
00312   /* the number of lines in the window */
00313   int maxWindowLines;
00314 
00315   /* the max length of each line */
00316   int maxLineLen;
00317 
00318   /* which array index holds the first filled slot */
00319   int windowStart;
00320 
00321   /* which array index holds the next open slot */
00322   int windowEnd;
00323 
00324   /* number in ring, also used to differentiate start = end as full/empty */
00325   int windowCount;
00326 
00327   /* the file to window */
00328   FILE * fileFp;
00329 
00330   /* the line currently at the top of the window */
00331   int fileFpLine;
00332 
00333   /* flag that the line should be kept */
00334   int keepNextLine;
00335 
00336 } FILE_WINDOW;
00337 
00338 static int fwClear(FILE_WINDOW *fw)
00339 {
00340   int t;
00341 
00342   if (NULL == fw) {
00343     return -1;
00344   }
00345 
00346   for (t = 0; t < fw->maxWindowLines; t++) {
00347     fw->fileWindow[t * fw->maxLineLen] = 0;
00348   }
00349 
00350   fw->windowStart = 0;
00351   fw->windowEnd = 0;
00352   fw->windowCount = 0;
00353 
00354   fw->fileFpLine = 0;
00355 
00356   fw->keepNextLine = 1;
00357 
00358   return 0;
00359 }
00360 
00361 static int fwInit(FILE_WINDOW *fw, int _maxWindowLines, int _maxLineLen)
00362 {
00363   if (NULL == fw) {
00364     return -1;
00365   }
00366 
00367   fw->fileWindow = (char *) malloc(_maxLineLen * _maxWindowLines);
00368 
00369   fw->maxWindowLines = _maxWindowLines;
00370   fw->maxLineLen = _maxLineLen;
00371 
00372   /* clear out the remaining vars */
00373   if (0 != fwClear(fw)) {
00374     return -1;
00375   }
00376 
00377   /* mark the file closed */
00378   fw->fileFp = NULL;
00379 
00380   return 0;
00381 }
00382 
00383 static int fwOpen(FILE_WINDOW *fw, const char *file)
00384 {
00385   if (NULL == fw) {
00386     return -1;
00387   }
00388 
00389   /* close any open file */
00390   if (NULL != fw->fileFp) {
00391     fclose(fw->fileFp);
00392     fw->fileFp = NULL;
00393   }
00394 
00395   if (NULL == (fw->fileFp = fopen(file, "r"))) {
00396     return -1;
00397   }
00398 
00399   fw->keepNextLine = 1;
00400 
00401   return 0;
00402 }
00403 
00404 static int fwClose(FILE_WINDOW *fw)
00405 {
00406   int retval = 0;
00407 
00408   if (NULL == fw) {
00409     return -1;
00410   }
00411 
00412   /* first clear out the window */
00413   if (0 != fwClear(fw)) {
00414     retval = -1;
00415   }
00416 
00417   if (NULL != fw->fileFp) {
00418     fclose(fw->fileFp);
00419   }
00420   fw->fileFp = NULL;
00421 
00422   return retval;
00423 }
00424 
00425 #if 0
00426 static int fwDelete(FILE_WINDOW *fw)
00427 {
00428   if (NULL == fw) {
00429     return -1;
00430   }
00431 
00432   /* should have been closed by call to fwClose(), but make sure */
00433   if (NULL != fw->fileFp) {
00434     fclose(fw->fileFp);
00435     fw->fileFp = NULL;
00436   }
00437 
00438   free(fw->fileWindow);
00439 
00440   return 0;
00441 }
00442 #endif
00443 
00444 #if 0
00445 static int fwPrintWindow(FILE_WINDOW *fw)
00446 {
00447   int start;
00448 
00449   if (NULL == fw) {
00450     return -1;
00451   }
00452 
00453   start = fw->windowStart;
00454 
00455   if (0 == fw->windowCount) {
00456     return 0;
00457   }
00458 
00459   do {
00460     printf("%s\n", &(fw->fileWindow[start * fw->maxLineLen]));
00461     if (++start >= fw->maxWindowLines) {
00462       start = 0;
00463     }
00464   } while (start != fw->windowEnd);
00465 
00466   return 0;
00467 }
00468 #endif
00469 
00470 static int fwAddLine(FILE_WINDOW *fw, const char *line)
00471 {
00472   if (NULL == fw) {
00473     return -1;
00474   }
00475 
00476   strncpy(&fw->fileWindow[fw->windowEnd * fw->maxLineLen], line, fw->maxLineLen - 1);
00477   fw->fileWindow[fw->windowEnd * fw->maxLineLen + fw->maxLineLen - 1] = 0;
00478 
00479   if (fw->windowEnd == fw->windowStart &&
00480       0 != fw->windowCount) {
00481     /* we're full, so move fw->windowStart up */
00482     /* and don't increment fw->windowCount */
00483     if (++fw->windowStart >= fw->maxWindowLines) {
00484       fw->windowStart = 0;
00485     }
00486   }
00487   else {
00488     /* we're not full, so no need to move fw->windowStart up */
00489     /* but do increment fw->windowCount */
00490     ++fw->windowCount;
00491   }
00492 
00493   /* now increment fw->windowEnd to point to next slot */
00494   if (++fw->windowEnd >= fw->maxWindowLines) {
00495     fw->windowEnd = 0;
00496   }
00497 
00498   return 0;
00499 }
00500 
00501 #if 0
00502 static int fwDeleteLine(FILE_WINDOW *fw)
00503 {
00504   if (NULL == fw) {
00505     return -1;
00506   }
00507 
00508   if (0 == fw->windowCount) {
00509     return 0;
00510   }
00511 
00512   fw->fileWindow[fw->windowStart * fw->maxLineLen] = 0;
00513   if (++fw->windowStart >= fw->maxWindowLines) {
00514     fw->windowStart = 0;
00515   }
00516 
00517   --fw->windowCount;
00518 
00519   return 0;
00520 }
00521 #endif
00522 
00523 
00524 static int fwSyncLine(FILE_WINDOW *fw, int syncLine)
00525 {
00526   char line[256];               // FIXME-- hardcoded
00527   int pad;
00528   int len;
00529   int sawEol;
00530 
00531   if (NULL == fw) {
00532     return -1;
00533   }
00534 
00535   if (NULL == fw->fileFp) {
00536     return -1;
00537   }
00538 
00539   /* if syncLine is <= 0, make it 1 */
00540   if (syncLine <= 0) {
00541     syncLine = 1;
00542   }
00543 
00544   /* reset syncLine so that it means the first line is synched */
00545   syncLine += fw->maxWindowLines - 1;
00546 
00547   /* check if our window is ahead of file, and rewind if so */
00548   if (syncLine < fw->fileFpLine) {
00549     /* we're ahead of program, so rewind */
00550     rewind(fw->fileFp);
00551     /* and clear out fw->fileWindow */
00552     fwClear(fw);
00553   }
00554 
00555   /* now the window is at or behind the file */
00556   /* so fill it up */
00557   while (fw->fileFpLine < syncLine) {
00558     if (NULL == fgets(line, fw->maxLineLen, fw->fileFp)) {
00559       /* end file */
00560       /* pad remainder if any */
00561       pad = syncLine - fw->fileFpLine;
00562       while (pad-- > 0) {
00563         fwAddLine(fw, "");
00564       }
00565       fw->fileFpLine = syncLine;
00566       break;
00567     }
00568 
00569     sawEol = 0;
00570     len = strlen(line);
00571     while (--len >= 0) {
00572       if (CR == line[len] ||
00573           LF == line[len]) {
00574         line[len] = 0;
00575         sawEol = 1;
00576       }
00577       else {
00578         break;
00579       }
00580     }
00581 
00582     if (fw->keepNextLine) {
00583       fwAddLine(fw, line);
00584       ++fw->fileFpLine;
00585     }
00586 
00587     fw->keepNextLine = sawEol;
00588   }
00589 
00590   return 0;
00591 }
00592 
00593 static int fwString(FILE_WINDOW *fw, char *string)
00594 {
00595   int start;
00596 
00597   if (NULL == fw) {
00598     return -1;
00599   }
00600 
00601   start = fw->windowStart;
00602   string[0] = 0;
00603 
00604   if (0 == fw->windowCount) {
00605     return 0;
00606   }
00607 
00608   do {
00609     strncat(string, &(fw->fileWindow[start * fw->maxLineLen]),
00610             fw->maxLineLen - 2);
00611     strcat(string, "\n");
00612     if (++start >= fw->maxWindowLines) {
00613       start = 0;
00614     }
00615   } while (start != fw->windowEnd);
00616 
00617   return 0;
00618 }
00619 
00620 // the file window structure for the program window and related stuff
00621 
00622 #define PROGRAM_FW_NUM_LINES 10
00623 #define PROGRAM_FW_LEN_LINES 80
00624 
00625 static char *programFwString = NULL;
00626 static FILE_WINDOW programFw;
00627 
00628 // number of axes supported
00629 #define XEMC_NUM_AXES 6
00630 
00631 // number of joints in ini file
00632 static int numJoints = 3;
00633 
00634 // number of coordinate values from ini file
00635 static int numCoords = 3;
00636 
00637 // number of labels needed to hold both joints and coords,
00638 // the max of the two
00639 static int numPosLabels = 3;
00640 
00641 // string for ini file version num
00642 static char version_string[INIFILE_MAX_LINELEN] = "";
00643 
00644 // interpreter parameter file name, from ini file
00645 static char PARAMETER_FILE[EMC_TASK_FILENAME_LEN] = "";
00646 
00647 // the program path prefix
00648 static char programPrefix[EMC_TASK_FILENAME_LEN] = "";
00649 // the program name currently displayed
00650 static char programFile[EMC_TASK_FILENAME_LEN] = "*";
00651 // the program last loaded by the controller
00652 static char lastProgramFile[EMC_TASK_FILENAME_LEN] = "*";
00653 
00654 // integer version of ini file max scale factor
00655 static int maxFeedOverride = 100;
00656 
00657 #define MDI_LINELEN 80
00658 static char active_g_codes_string[MDI_LINELEN] = "";
00659 static char active_m_codes_string[MDI_LINELEN] = "";
00660 
00661 // type of kinematics in machine
00662 typedef enum {
00663   KINEMATICS_IDENTITY = 1,
00664   KINEMATICS_SERIAL,
00665   KINEMATICS_PARALLEL
00666 } KINEMATICS_TYPE;
00667 
00668 static KINEMATICS_TYPE kinematicsType = KINEMATICS_IDENTITY;
00669 
00670 // array for marking which coordinate values out of X Y Z R P W to display
00671 // with a default of X Y Z
00672 static unsigned char coordinateMark[6] = {1, 1, 1, 0, 0, 0};
00673 
00674 // how position is to be displayed-- relative or machine
00675 typedef enum {
00676   COORD_RELATIVE = 1,
00677   COORD_MACHINE
00678 } COORD_TYPE;
00679 
00680 static COORD_TYPE coords = COORD_RELATIVE;
00681 
00682 // how position is to be displayed-- actual or commanded
00683 typedef enum {
00684   POS_DISPLAY_ACT = 1,
00685   POS_DISPLAY_CMD
00686 } POS_DISPLAY_TYPE;
00687 
00688 static POS_DISPLAY_TYPE posDisplay = POS_DISPLAY_ACT;
00689 
00690 // which position coordinate frame is to be displayed-- world or joint
00691 typedef enum {
00692   POS_FRAME_WORLD = 1,
00693   POS_FRAME_JOINT
00694 } POS_FRAME_TYPE;
00695 
00696 static POS_FRAME_TYPE posFrame = POS_FRAME_WORLD;
00697 
00698 // marker for the active coord or joint
00699 static int activeJoint = 0;     // default is 0, first joint
00700 static int oldActiveJoint = -1; // force an update at startup
00701 static int activeCoord = 0;     // default is X, first coordinate
00702 static int oldActiveCoord = -1; // force an update at startup
00703 
00704 /*
00705   Note: the X key press/release events with multiple keys behave such that
00706   if key a is pressed, then b, then a released, its key-release event
00707   won't go through. So, multi-axis jogging has been disallowed in xemc,
00708   although it's supported in the motion system.
00709 */
00710 // flag that an axis is jogging, so other jogs won't go out
00711 static int axisJogging = -1;
00712 
00713 // current jog speed setting
00714 static int jogSpeed = 1;        // overridden in iniLoad()
00715 static int maxJogSpeed = 1;     // overridden in iniLoad()
00716 static int jogSpeedChange = 0;  // 0 means no change, +/- means inc/dec
00717 
00718 // current jog increment setting, non-positive means continuous
00719 static double jogIncrement = 0.0;
00720 
00721 // polarities for axis jogging, from ini file
00722 static int jogPol[XEMC_NUM_AXES];
00723 
00724 static int oldFeedOverride = -1; // forces an update at startup
00725 static int feedOverride;        // 100% integer copy of EMC status
00726 static int feedOverrideChange = 0; // same as jogSpeedChange
00727 #define FEED_OVERRIDE_DELAY_COUNT 1
00728 // timer delays until dec/inc appears
00729 static int feedOverrideDelayCount = FEED_OVERRIDE_DELAY_COUNT;
00730 
00731 // command sending functions
00732 
00733 static int sendEstop()
00734 {
00735   EMC_TASK_SET_STATE state_msg;
00736 
00737   state_msg.state = EMC_TASK_STATE_ESTOP;
00738   state_msg.serial_number = ++emcCommandSerialNumber;
00739   emcCommandBuffer->write(state_msg);
00740 
00741   return 0;
00742 }
00743 
00744 static int sendEstopReset()
00745 {
00746   EMC_TASK_SET_STATE state_msg;
00747 
00748   state_msg.state = EMC_TASK_STATE_ESTOP_RESET;
00749   state_msg.serial_number = ++emcCommandSerialNumber;
00750   emcCommandBuffer->write(state_msg);
00751 
00752   return 0;
00753 }
00754 
00755 static int sendMachineOn()
00756 {
00757   EMC_TASK_SET_STATE state_msg;
00758 
00759   state_msg.state = EMC_TASK_STATE_ON;
00760   state_msg.serial_number = ++emcCommandSerialNumber;
00761   emcCommandBuffer->write(state_msg);
00762 
00763   return 0;
00764 }
00765 
00766 static int sendMachineOff()
00767 {
00768   EMC_TASK_SET_STATE state_msg;
00769 
00770   state_msg.state = EMC_TASK_STATE_OFF;
00771   state_msg.serial_number = ++emcCommandSerialNumber;
00772   emcCommandBuffer->write(state_msg);
00773 
00774   return 0;
00775 }
00776 
00777 static int sendManual()
00778 {
00779   EMC_TASK_SET_MODE mode_msg;
00780 
00781   mode_msg.mode = EMC_TASK_MODE_MANUAL;
00782   mode_msg.serial_number = ++emcCommandSerialNumber;
00783   emcCommandBuffer->write(mode_msg);
00784 
00785   return 0;
00786 }
00787 
00788 static int sendAuto()
00789 {
00790   EMC_TASK_SET_MODE mode_msg;
00791 
00792   mode_msg.mode = EMC_TASK_MODE_AUTO;
00793   mode_msg.serial_number = ++emcCommandSerialNumber;
00794   emcCommandBuffer->write(mode_msg);
00795 
00796   return 0;
00797 }
00798 
00799 static int sendMdi()
00800 {
00801   EMC_TASK_SET_MODE mode_msg;
00802 
00803   mode_msg.mode = EMC_TASK_MODE_MDI;
00804   mode_msg.serial_number = ++emcCommandSerialNumber;
00805   emcCommandBuffer->write(mode_msg);
00806 
00807   return 0;
00808 }
00809 
00810 static int sendToolSetOffset(int tool, double length, double diameter)
00811 {
00812   EMC_TOOL_SET_OFFSET emc_tool_set_offset_msg;
00813 
00814   emc_tool_set_offset_msg.tool = tool;
00815   emc_tool_set_offset_msg.length = length;
00816   emc_tool_set_offset_msg.diameter = diameter;
00817   emc_tool_set_offset_msg.serial_number = ++emcCommandSerialNumber;
00818   emcCommandBuffer->write(emc_tool_set_offset_msg);
00819 
00820   return 0;
00821 }
00822 
00823 static int sendMistOn()
00824 {
00825   EMC_COOLANT_MIST_ON emc_coolant_mist_on_msg;
00826 
00827   emc_coolant_mist_on_msg.serial_number = ++emcCommandSerialNumber;
00828   emcCommandBuffer->write(emc_coolant_mist_on_msg);
00829 
00830   return 0;
00831 }
00832 
00833 static int sendMistOff()
00834 {
00835   EMC_COOLANT_MIST_OFF emc_coolant_mist_off_msg;
00836 
00837   emc_coolant_mist_off_msg.serial_number = ++emcCommandSerialNumber;
00838   emcCommandBuffer->write(emc_coolant_mist_off_msg);
00839 
00840   return 0;
00841 }
00842 
00843 static int sendFloodOn()
00844 {
00845   EMC_COOLANT_FLOOD_ON emc_coolant_flood_on_msg;
00846 
00847   emc_coolant_flood_on_msg.serial_number = ++emcCommandSerialNumber;
00848   emcCommandBuffer->write(emc_coolant_flood_on_msg);
00849 
00850   return 0;
00851 }
00852 
00853 static int sendFloodOff()
00854 {
00855   EMC_COOLANT_FLOOD_OFF emc_coolant_flood_off_msg;
00856 
00857   emc_coolant_flood_off_msg.serial_number = ++emcCommandSerialNumber;
00858   emcCommandBuffer->write(emc_coolant_flood_off_msg);
00859 
00860   return 0;
00861 }
00862 
00863 static int sendSpindleForward()
00864 {
00865   EMC_SPINDLE_ON emc_spindle_on_msg;
00866 
00867   emc_spindle_on_msg.speed = +1;
00868   emc_spindle_on_msg.serial_number = ++emcCommandSerialNumber;
00869   emcCommandBuffer->write(emc_spindle_on_msg);
00870 
00871   return 0;
00872 }
00873 
00874 static int sendSpindleReverse()
00875 {
00876   EMC_SPINDLE_ON emc_spindle_on_msg;
00877 
00878   emc_spindle_on_msg.speed = -1;
00879   emc_spindle_on_msg.serial_number = ++emcCommandSerialNumber;
00880   emcCommandBuffer->write(emc_spindle_on_msg);
00881 
00882   return 0;
00883 }
00884 
00885 static int sendSpindleOff()
00886 {
00887   EMC_SPINDLE_OFF emc_spindle_off_msg;
00888 
00889   emc_spindle_off_msg.serial_number = ++emcCommandSerialNumber;
00890   emcCommandBuffer->write(emc_spindle_off_msg);
00891 
00892   return 0;
00893 }
00894 
00895 static int sendSpindleIncrease()
00896 {
00897   EMC_SPINDLE_INCREASE emc_spindle_increase_msg;
00898 
00899   emc_spindle_increase_msg.serial_number = ++emcCommandSerialNumber;
00900   emcCommandBuffer->write(emc_spindle_increase_msg);
00901 
00902   return 0;
00903 }
00904 
00905 static int sendSpindleDecrease()
00906 {
00907   EMC_SPINDLE_DECREASE emc_spindle_decrease_msg;
00908 
00909   emc_spindle_decrease_msg.serial_number = ++emcCommandSerialNumber;
00910   emcCommandBuffer->write(emc_spindle_decrease_msg);
00911 
00912   return 0;
00913 }
00914 
00915 static int sendSpindleConstant()
00916 {
00917   EMC_SPINDLE_CONSTANT emc_spindle_constant_msg;
00918 
00919   emc_spindle_constant_msg.serial_number = ++emcCommandSerialNumber;
00920   emcCommandBuffer->write(emc_spindle_constant_msg);
00921 
00922   return 0;
00923 }
00924 
00925 static int sendBrakeEngage()
00926 {
00927   EMC_SPINDLE_BRAKE_ENGAGE emc_spindle_brake_engage_msg;
00928 
00929   emc_spindle_brake_engage_msg.serial_number = ++emcCommandSerialNumber;
00930   emcCommandBuffer->write(emc_spindle_brake_engage_msg);
00931 
00932   return 0;
00933 }
00934 
00935 static int sendBrakeRelease()
00936 {
00937   EMC_SPINDLE_BRAKE_RELEASE emc_spindle_brake_release_msg;
00938 
00939   emc_spindle_brake_release_msg.serial_number = ++emcCommandSerialNumber;
00940   emcCommandBuffer->write(emc_spindle_brake_release_msg);
00941 
00942   return 0;
00943 }
00944 
00945 static int sendAbort()
00946 {
00947   EMC_TASK_ABORT task_abort_msg;
00948 
00949   task_abort_msg.serial_number = ++emcCommandSerialNumber;
00950   emcCommandBuffer->write(task_abort_msg);
00951 
00952   return 0;
00953 }
00954 
00955 static int sendJogStop(int axis)
00956 {
00957   EMC_AXIS_ABORT emc_axis_abort_msg;
00958 
00959   if (axis < 0 || axis >= XEMC_NUM_AXES) {
00960     return -1;
00961   }
00962 
00963   // don't send request to jog if none are jogging
00964   if (axisJogging == -1) {
00965     return 0;
00966   }
00967 
00968   emc_axis_abort_msg.serial_number = ++emcCommandSerialNumber;
00969   emc_axis_abort_msg.axis = axisJogging;
00970   emcCommandBuffer->write(emc_axis_abort_msg);
00971 
00972   axisJogging = -1;
00973 
00974   return 0;
00975 }
00976 
00977 static int sendJogCont(int axis, double speed)
00978 {
00979   EMC_AXIS_JOG emc_axis_jog_msg;
00980   EMC_TRAJ_SET_TELEOP_VECTOR emc_set_teleop_vector;
00981 
00982   if (axis < 0 || axis >= XEMC_NUM_AXES) {
00983     return -1;
00984   }
00985 
00986   if (axisJogging != -1) {
00987     // ignore request to jog, if an axis is already jogging
00988     return 0;
00989   }
00990 
00991   if(posFrame == POS_FRAME_JOINT)
00992     {
00993       if (0 == jogPol[axis]) {
00994         speed = -speed;
00995       }
00996       
00997       emc_axis_jog_msg.serial_number = ++emcCommandSerialNumber;
00998       emc_axis_jog_msg.axis = axis;
00999       emc_axis_jog_msg.vel = speed / 60.0;
01000       emcCommandBuffer->write(emc_axis_jog_msg);
01001     }
01002   else
01003     {
01004       emc_set_teleop_vector.serial_number = ++emcCommandSerialNumber;
01005       emc_set_teleop_vector.vector.tran.x = 0.0;
01006       emc_set_teleop_vector.vector.tran.y = 0.0;
01007       emc_set_teleop_vector.vector.tran.z = 0.0;
01008 
01009       switch(axis)
01010         {
01011         case 0:
01012           emc_set_teleop_vector.vector.tran.x = speed/60.0;
01013           break;
01014         case 1:
01015           emc_set_teleop_vector.vector.tran.y = speed/60.0;
01016           break;
01017         case 2:
01018           emc_set_teleop_vector.vector.tran.z = speed/60.0;
01019           break;
01020         case 3:
01021           emc_set_teleop_vector.vector.a = speed/60.0;
01022           break;
01023         case 4:
01024           emc_set_teleop_vector.vector.b = speed/60.0;
01025           break;
01026         case 5:
01027           emc_set_teleop_vector.vector.c = speed/60.0;
01028           break;
01029         }
01030       emcCommandBuffer->write(emc_set_teleop_vector);
01031     }
01032 
01033           
01034       
01035   axisJogging = axis;
01036 
01037   return 0;
01038 }
01039 
01040 static int sendJogIncr(int axis, double speed, double incr)
01041 {
01042   EMC_AXIS_INCR_JOG emc_axis_incr_jog_msg;
01043 
01044   if (axis < 0 || axis >= XEMC_NUM_AXES) {
01045     return -1;
01046   }
01047 
01048   if (axisJogging != -1) {
01049     // ignore request to jog, if an axis is already jogging
01050     return 0;
01051   }
01052 
01053   if (0 == jogPol[axis]) {
01054     speed = -speed;
01055   }
01056 
01057   emc_axis_incr_jog_msg.serial_number = ++emcCommandSerialNumber;
01058   emc_axis_incr_jog_msg.axis = axis;
01059   emc_axis_incr_jog_msg.vel = speed / 60.0;
01060   emc_axis_incr_jog_msg.incr = jogIncrement;
01061   emcCommandBuffer->write(emc_axis_incr_jog_msg);
01062 
01063   // don't flag incremental jogs as jogging an axis-- we can
01064   // allow multiple incremental jogs since we don't need a key release
01065 
01066   return 0;
01067 }
01068 
01069 static int sendHome(int axis)
01070 {
01071   EMC_AXIS_HOME emc_axis_home_msg;
01072 
01073   emc_axis_home_msg.serial_number = ++emcCommandSerialNumber;
01074   emc_axis_home_msg.axis = axis;
01075   emcCommandBuffer->write(emc_axis_home_msg);
01076 
01077   return 0;
01078 }
01079 
01080 static int sendFeedOverride(double override)
01081 {
01082   EMC_TRAJ_SET_SCALE emc_traj_set_scale_msg;
01083 
01084   if (override < 0.0) {
01085     override = 0.0;
01086   }
01087   else if (override > (double) maxFeedOverride / 100.0) {
01088     override = (double) maxFeedOverride / 100.0;
01089   }
01090   emc_traj_set_scale_msg.serial_number = ++emcCommandSerialNumber;
01091   emc_traj_set_scale_msg.scale = override;
01092   emcCommandBuffer->write(emc_traj_set_scale_msg);
01093 
01094   return 0;
01095 }
01096 
01097 static int sendTaskPlanInit()
01098 {
01099   EMC_TASK_PLAN_INIT task_plan_init_msg;
01100 
01101   task_plan_init_msg.serial_number = ++emcCommandSerialNumber;
01102   emcCommandBuffer->write(task_plan_init_msg);
01103 
01104   return 0;
01105 }
01106 
01107 static int sendProgramOpen(char *program)
01108 {
01109   EMC_TASK_PLAN_OPEN emc_task_plan_open_msg;
01110 
01111   // first put in auto mode if it's not
01112   if (0 == emcStatus->task.mode != EMC_TASK_MODE_AUTO) {
01113     // send a request to go to auto mode
01114     sendAuto();
01115   }
01116 
01117   // wait for any previous one to go out
01118   if (0 != emcCommandWaitDone(emcCommandSerialNumber)) {
01119     printError("error executing command\n");
01120     return -1;
01121   }
01122 
01123   emc_task_plan_open_msg.serial_number = ++emcCommandSerialNumber;
01124   strcpy(emc_task_plan_open_msg.file, program);
01125   emcCommandBuffer->write(emc_task_plan_open_msg);
01126 
01127   // now clear out our stored version of the program, in case
01128   // the file contents have changed but the name is the same
01129   programFile[0] = 0;
01130 
01131   return 0;
01132 }
01133 
01134 // line in program to run from; set it in GUI when user clicks on a line,
01135 // and pass it in calls to sendProgramRun(). sendProgramRun() won't use
01136 // this directly.
01137 static int programStartLine = 0;
01138 static int programStartLineLast = 0;
01139 
01140 static int sendProgramRun(int line)
01141 {
01142   EMC_TASK_PLAN_RUN emc_task_plan_run_msg;
01143 
01144   // first reopen program if it's not open
01145   if (0 == emcStatus->task.file[0]) {
01146     // send a request to open last one
01147     sendProgramOpen(lastProgramFile);
01148 
01149     // wait for command to go out
01150     if (0 != emcCommandWaitDone(emcCommandSerialNumber)) {
01151       printError("error executing command\n");
01152       return -1;
01153     }
01154   }
01155 
01156   emc_task_plan_run_msg.serial_number = ++emcCommandSerialNumber;
01157   emc_task_plan_run_msg.line = line;
01158   emcCommandBuffer->write(emc_task_plan_run_msg);
01159 
01160   programStartLineLast = programStartLine;
01161   programStartLine = 0;
01162 
01163   return 0;
01164 }
01165 
01166 static int sendProgramPause()
01167 {
01168   EMC_TASK_PLAN_PAUSE emc_task_plan_pause_msg;
01169 
01170   emc_task_plan_pause_msg.serial_number = ++emcCommandSerialNumber;
01171   emcCommandBuffer->write(emc_task_plan_pause_msg);
01172 
01173   return 0;
01174 }
01175 
01176 static int sendProgramResume()
01177 {
01178   EMC_TASK_PLAN_RESUME emc_task_plan_resume_msg;
01179 
01180   emc_task_plan_resume_msg.serial_number = ++emcCommandSerialNumber;
01181   emcCommandBuffer->write(emc_task_plan_resume_msg);
01182 
01183   return 0;
01184 }
01185 
01186 static int sendProgramStep()
01187 {
01188   EMC_TASK_PLAN_STEP emc_task_plan_step_msg;
01189 
01190   // first reopen program if it's not open
01191   if (0 == emcStatus->task.file[0]) {
01192     // send a request to open last one
01193     sendProgramOpen(lastProgramFile);
01194 
01195     // wait for command to go out
01196     if (0 != emcCommandWaitDone(emcCommandSerialNumber)) {
01197       printError("error executing command\n");
01198       return -1;
01199     }
01200   }
01201 
01202   emc_task_plan_step_msg.serial_number = ++emcCommandSerialNumber;
01203   emcCommandBuffer->write(emc_task_plan_step_msg);
01204 
01205   programStartLineLast = programStartLine;
01206   programStartLine = 0;
01207 
01208   return 0;
01209 }
01210 
01211 static int sendMdiCmd(char *mdi)
01212 {
01213   EMC_TASK_PLAN_EXECUTE emc_task_plan_execute_msg;
01214 
01215   strcpy(emc_task_plan_execute_msg.command, mdi);
01216   emc_task_plan_execute_msg.serial_number = ++emcCommandSerialNumber;
01217   emcCommandBuffer->write(emc_task_plan_execute_msg);
01218 
01219   return 0;
01220 }
01221 
01222 static int sendLoadToolTable(const char *file)
01223 {
01224   EMC_TOOL_LOAD_TOOL_TABLE emc_tool_load_tool_table_msg;
01225 
01226   strcpy(emc_tool_load_tool_table_msg.file, file);
01227   emc_tool_load_tool_table_msg.serial_number = ++emcCommandSerialNumber;
01228   emcCommandBuffer->write(emc_tool_load_tool_table_msg);
01229 
01230   return 0;
01231 }
01232 
01233 static int sendAxisCycleTime(int axis, double cycleTime)
01234 {
01235   EMC_AXIS_SET_CYCLE_TIME emc_axis_set_cycle_time_msg;
01236 
01237   emc_axis_set_cycle_time_msg.axis = axis;
01238   emc_axis_set_cycle_time_msg.cycleTime = cycleTime;
01239   emc_axis_set_cycle_time_msg.serial_number = ++emcCommandSerialNumber;
01240   emcCommandBuffer->write(emc_axis_set_cycle_time_msg);
01241 
01242   return 0;
01243 }
01244 
01245 static int sendAxisSetGains(int axis, double p, double i, double d, double ff0, double ff1, double ff2, double backlash, double bias, double maxError)
01246 {
01247   EMC_AXIS_SET_GAINS emc_axis_set_gains_msg;
01248 
01249   emc_axis_set_gains_msg.axis = axis;
01250   emc_axis_set_gains_msg.p = p;
01251   emc_axis_set_gains_msg.i = i;
01252   emc_axis_set_gains_msg.d = d;
01253   emc_axis_set_gains_msg.ff0 = ff0;
01254   emc_axis_set_gains_msg.ff1 = ff1;
01255   emc_axis_set_gains_msg.ff2 = ff2;
01256   emc_axis_set_gains_msg.backlash = backlash;
01257   emc_axis_set_gains_msg.bias = bias;
01258   emc_axis_set_gains_msg.maxError = maxError;
01259   emc_axis_set_gains_msg.serial_number = ++emcCommandSerialNumber;
01260   emcCommandBuffer->write(emc_axis_set_gains_msg);
01261 
01262   return 0;
01263 }
01264 
01265 static int sendAxisSetOutputScale(int axis, double scale, double offset)
01266 {
01267   EMC_AXIS_SET_OUTPUT_SCALE emc_axis_set_output_scale_msg;
01268 
01269   emc_axis_set_output_scale_msg.axis = axis;
01270   emc_axis_set_output_scale_msg.scale = scale;
01271   emc_axis_set_output_scale_msg.offset = offset;
01272   emc_axis_set_output_scale_msg.serial_number = ++emcCommandSerialNumber;
01273   emcCommandBuffer->write(emc_axis_set_output_scale_msg);
01274 
01275   return 0;
01276 }
01277 
01278 static int sendAxisSetFerror(int axis, double ferror)
01279 {
01280   EMC_AXIS_SET_FERROR emc_axis_set_ferror_msg;
01281 
01282   emc_axis_set_ferror_msg.axis = axis;
01283   emc_axis_set_ferror_msg.ferror = ferror;
01284   emc_axis_set_ferror_msg.serial_number = ++emcCommandSerialNumber;
01285   emcCommandBuffer->write(emc_axis_set_ferror_msg);
01286 
01287   return 0;
01288 }
01289 
01290 // saved log file params
01291 static char saveLogFile[EMC_LOG_FILENAME_LEN] = "/tmp/emc.plot.sh";
01292 static int saveLogType = EMC_LOG_TYPE_AXES_FERROR;
01293 static int saveLogSize = 1000;
01294 static int saveLogSkip = 0;
01295 
01296 // paths to awk and xgraph, using to plot logs
01297 // fill these in for your system, if these are not in user's path
01298 #define AWK_PATH "awk"
01299 #define XGRAPH_PATH "xgraph"
01300 #define SYSTEM_STRING_LEN 1024
01301 
01302 static int plotLog(const char * logfile, int logtype)
01303 {
01304   char string[SYSTEM_STRING_LEN];
01305   int retval;
01306 
01307   if (logfile == 0)
01308     {
01309       return -1;
01310     }
01311 
01312   switch (logtype)
01313     {
01314     case EMC_LOG_TYPE_AXIS_POS:
01315     case EMC_LOG_TYPE_AXIS_VEL:
01316       sprintf(string, "( %s '{print $1 \" \" $2}' < %s ; echo \"\" ; %s '{print $1 \" \" $3}' < %s ) 2> /dev/null | %s -m 1> /dev/null 2> /dev/null", AWK_PATH, logfile, AWK_PATH, logfile, XGRAPH_PATH);
01317       break;
01318 
01319     case EMC_LOG_TYPE_AXES_INPOS:
01320     case EMC_LOG_TYPE_AXES_OUTPOS:
01321       sprintf(string, "%s '{print $2 \" \" $3}' < %s 2> /dev/null | %s -m 1> /dev/null 2> /dev/null", AWK_PATH, logfile, XGRAPH_PATH);
01322       break;
01323 
01324     case EMC_LOG_TYPE_AXES_FERROR:
01325     case EMC_LOG_TYPE_TRAJ_POS:
01326       /* we want to compose:
01327          ( awk '{print $1 " " $2}' < emc.log ; echo "" ; awk '{print $1 " " $3}' < emc.log ; echo "" ; awk '{print $1 " " $4}' < emc.log ) 2> /dev/null | xgraph -m 1> /dev/null 2> /dev/null"
01328        */
01329       sprintf(string, "( %s '{print $1 \" \" $2}' < %s ; echo \"\" ; %s '{print $1 \" \" $3}' < %s ; echo \"\" ; %s '{print $1 \" \" $4}' < %s ) 2> /dev/null | %s -m 1> /dev/null 2> /dev/null", AWK_PATH, logfile, AWK_PATH, logfile, AWK_PATH, logfile, XGRAPH_PATH);
01330       break;
01331 
01332     case EMC_LOG_TYPE_TRAJ_VEL:
01333     case EMC_LOG_TYPE_TRAJ_ACC:
01334       /* we want to compose:
01335          ( awk '{print $1 " " $2}' < emc.log ; echo "" ; awk '{print $1 " " $3}' < emc.log ; echo "" ; awk '{print $1 " " $4}' < emc.log ; echo "" ; awk '{print $1 " " $5}' < emc.log) 2> /dev/null | xgraph -m 1> /dev/null 2> /dev/null"
01336        */
01337       sprintf(string, "( %s '{print $1 \" \" $2}' < %s ; echo \"\" ; %s '{print $1 \" \" $3}' < %s ; echo \"\" ; %s '{print $1 \" \" $4}' < %s ; echo \"\" ; %s '{print $1 \" \" $5}' < %s) 2> /dev/null | %s -m 1> /dev/null 2> /dev/null", AWK_PATH, logfile, AWK_PATH, logfile, AWK_PATH, logfile, AWK_PATH, logfile, XGRAPH_PATH);
01338       break;
01339 
01340     default:
01341       return -1;
01342       break;
01343     }
01344 
01345   retval = system(string);
01346 
01347   return retval;
01348 }
01349 
01350 static int sendLogStart()
01351 {
01352   EMC_LOG_OPEN emc_log_open_msg;
01353   EMC_LOG_START emc_log_start_msg;
01354 
01355   // check for open log file first; if not, and old one saved, open it
01356   if (! emcStatus->logOpen) {
01357     if (saveLogFile[0] != 0) {
01358       strcpy(emc_log_open_msg.file, saveLogFile);
01359       emc_log_open_msg.type = saveLogType;
01360       emc_log_open_msg.size = saveLogSize;
01361       emc_log_open_msg.skip = saveLogSkip;
01362       emc_log_open_msg.which = activeJoint;
01363       emc_log_open_msg.serial_number = ++emcCommandSerialNumber;
01364       emcCommandBuffer->write(emc_log_open_msg);
01365     }
01366     else {
01367       // log is not opened, and no name saved, so ignore
01368       popupError("No log file selected");
01369       return -1;
01370     }
01371   }
01372 
01373   // wait for previous one to go out
01374   emcCommandWaitReceived(emcCommandSerialNumber);
01375 
01376   // now send log start message
01377   emc_log_start_msg.serial_number = ++emcCommandSerialNumber;
01378   emcCommandBuffer->write(emc_log_start_msg);
01379 
01380   return 0;
01381 }
01382 
01383 static int sendLogStop()
01384 {
01385   EMC_LOG_STOP emc_log_stop_msg;
01386 
01387   emc_log_stop_msg.serial_number = ++emcCommandSerialNumber;
01388   emcCommandBuffer->write(emc_log_stop_msg);
01389 
01390   return 0;
01391 };
01392 
01393 static int sendLogClose()
01394 {
01395   EMC_LOG_CLOSE emc_log_close_msg;
01396 
01397   emc_log_close_msg.serial_number = ++emcCommandSerialNumber;
01398   emcCommandBuffer->write(emc_log_close_msg);
01399 
01400   return 0;
01401 }
01402 
01403 // X stuff starts here
01404 
01405 // flag signifying that window needs to be redrawn
01406 static int redraw = 1;
01407 
01408 // global context and widgets, accessed during periodic timer
01409 static XtAppContext app_context;
01410 static Atom killAtom;
01411 static Widget topLevel;
01412 static Widget topForm;
01413 static Widget barMenuForm;
01414 static Widget abortCommand;
01415 static Widget fileMenu;
01416 static Widget viewMenu;
01417 static Widget settingsMenu;
01418 static Widget helpMenu;
01419 static Widget commandMenuForm;
01420 static Widget stateMenu;
01421 static Widget modeMenu;
01422 static Widget mistMenu;
01423 static Widget floodMenu;
01424 static Widget spindleMenu;
01425 static Widget spindleIncLabel, spindleDecLabel;
01426 static Widget brakeMenu;
01427 static Widget toolTableShell = NULL, toolTableForm, toolTableLabel, toolTableText, toolTableDone, toolTableCancel;
01428 static Widget varFileShell = NULL, varFileForm, varFileLabel, varFileText, varFileDone, varFileCancel;
01429 static Widget toolNumberForm, toolNumberFormTitle, toolNumberFormName;
01430 static Widget toolOffsetForm, toolOffsetFormTitle, toolOffsetFormName;
01431 static Widget toolSetOffsetShell, toolSetOffsetForm, toolSetOffsetToolLabel, toolSetOffsetTool, toolSetOffsetLengthLabel, toolSetOffsetLength, toolSetOffsetDiameterLabel, toolSetOffsetDiameter, toolSetOffsetDone, toolSetOffsetCancel;
01432 static Widget positionTypeForm, positionTypeFormTitle, positionTypeFormName;
01433 static Widget workOffsetForm, workOffsetFormTitle, workOffsetFormName;
01434 static Widget posLabel[XEMC_NUM_AXES];
01435 static Widget posOffsetShell, posOffsetDialog;
01436 static Widget jogSpeedForm, jogSpeedTitleLabel,
01437   jogSpeedLabel, jogSpeedIncLabel, jogSpeedDecLabel;
01438 static Widget jogSpeedShell, jogSpeedDialog;
01439 static Widget jogIncrementForm, jogIncrementTitleLabel, jogIncrementMenu;
01440 static Widget jogForm, jogTitleLabel,
01441   jogMinusLabel, homeCommand, jogPlusLabel;
01442 static Widget feedOverrideForm, feedOverrideTitleLabel,
01443   feedOverrideLabel, feedOverrideIncLabel, feedOverrideDecLabel;
01444 static Widget feedOverrideShell, feedOverrideDialog;
01445 static Widget loggingStatusForm, loggingStatusTitleLabel,
01446   loggingStatusOpenLabel, loggingStatusStartedLabel, loggingStatusPointsLabel;
01447 static Widget mdiForm, mdiFormTitle, mdiFormText;
01448 static Widget mdiCodesLabel;
01449 static Widget programForm, programFormTitle, programFormName, programFormStateTitle, programFormState;
01450 static Widget programOpenCommand, programRunCommand, programPauseCommand, programResumeCommand, programStepCommand, programVerifyCommand;
01451 static Widget programText;
01452 static Widget fileOpenShell, fileOpenDialog, fileOpenDone, fileOpenCancel;
01453 static char EDITOR_FILE[256] = ""; // FIXME-- hardcoded
01454 static Widget fileEditShell, fileEditDialog, fileEditDone, fileEditCancel;
01455 static Widget fileEditorShell = NULL, fileEditorForm, fileEditorLabel, fileEditorText, fileEditorDone, fileEditorCancel, fileEditorMark;
01456 static Widget fileQuitShell, fileQuitDialog, fileQuitDone, fileQuitCancel;
01457 static Widget helpXemcShell = NULL, helpXemcForm, helpXemcLabel, helpXemcText, helpXemcDone;
01458 static Widget helpAboutShell, helpAboutDialog, helpAboutDone;
01459 static Widget errorShell = 0, errorDialog = 0, errorDone = 0;
01460 
01461 // Pixel values inited from strings, for hard-coded colors
01462 static Pixel pixelBlack;
01463 static Pixel pixelRed;
01464 static Pixel pixelYellow;
01465 static Pixel pixelGreen;
01466 
01467 // saved background and border colors for position labels,
01468 // cleared and restored when highlighting
01469 static Pixel posLabelBackground[XEMC_NUM_AXES];
01470 static Pixel posLabelBorderColor[XEMC_NUM_AXES];
01471 
01472 static int getColor(Widget w, Pixel *pixel, int foreground)
01473 {
01474   Arg args;
01475 
01476   if (foreground)
01477     XtSetArg(args, XtNforeground, pixel);
01478   else
01479     XtSetArg(args, XtNbackground, pixel);
01480   XtGetValues(w, &args, 1);
01481 
01482   return 0;
01483 }
01484 
01485 static int setColor(Widget w, Pixel pixel, int foreground)
01486 {
01487   if (foreground)
01488     XtVaSetValues(w, XtNforeground, pixel, NULL);
01489   else
01490     XtVaSetValues(w, XtNbackground, pixel, NULL);
01491 
01492   return 0;
01493 }
01494 
01495 static int stringToPixel(Widget w, String string, Pixel *pixel)
01496 {
01497   XrmValue from, to;
01498 
01499   from.addr = string;
01500   from.size = strlen(string) + 1;
01501   to.addr = (char *) pixel;
01502   to.size = sizeof(Pixel);
01503 
01504   if (False == XtConvertAndStore(w, XtRString, &from, XtRPixel, &to))
01505     return -1;
01506   return 0;
01507 }
01508 
01509 static int getBorderColor(Widget w, Pixel *pixel)
01510 {
01511   Arg args;
01512 
01513   XtSetArg(args, XtNborderColor, pixel);
01514   XtGetValues(w, &args, 1);
01515 
01516   return 0;
01517 }
01518 
01519 static int setBorderColor(Widget w, Pixel pixel)
01520 {
01521   XtVaSetValues(w, XtNborderColor, pixel, NULL);
01522 
01523   return 0;
01524 }
01525 
01526 static int setLabel(Widget w, char *label)
01527 {
01528   Arg args;
01529   int width;
01530 
01531   XtSetArg(args, XtNwidth, &width);
01532   XtGetValues(w, &args, 1);
01533   XtVaSetValues(w, XtNlabel, label, NULL);
01534   XtVaSetValues(w, XtNwidth, width, NULL);
01535   return(0);
01536 }
01537 
01538 static int setProgramText(char *text)
01539 {
01540   XtVaSetValues(programText, XtNstring, text, NULL);
01541   return(0);
01542 }
01543 
01544 // index is diff between top and line to highlight, 0..max
01545 static int highlightProgramText(char *text, int index)
01546 {
01547   int start, end;
01548 
01549   // position 'start' to first char on index line
01550   for (start = 0; ; start++) {
01551     if (index <= 0) {
01552       break;
01553     }
01554     if (text[start] == 0 || text[start] == '\n') {
01555       index--;
01556     }
01557   }
01558 
01559   // position 'end' to last char on index line
01560   for (end = start; ; end++) {
01561     if (text[end] == 0 || text[end] == '\n') {
01562       break;
01563     }
01564   }
01565 
01566   XawTextSetSelection(programText, start, end);
01567   return(0);
01568 }
01569 
01570 // dialogPopup() is an XtNcallback that expects a
01571 // transientShellWidget class as the client_data.
01572 // Widget w is not used, but is required if this is to be used
01573 // as a callback function. If you call it directly you can put NULL
01574 // in for w and call_data.
01575 static void dialogPopup(Widget w, XtPointer client_data, XtPointer call_data)
01576 {
01577   Position x, y;
01578   Dimension width, height;
01579 
01580   // get the coordinates of the middle of topLevel widget
01581   XtVaGetValues(topForm,
01582                 XtNwidth, &width,
01583                 XtNheight, &height,
01584                 NULL);
01585 
01586   // translate coordinates in application top-level window
01587   // into coordinates from root window origin
01588   XtTranslateCoords(topForm,
01589                     (Position) 100,
01590                     (Position) 100,
01591                     &x, &y);
01592 
01593   // move popup shell to this position (it's not visible yet)
01594   XtVaSetValues((Widget) client_data,
01595                 XtNx, x,
01596                 XtNy, y,
01597                 NULL);
01598 
01599   XtPopup((Widget) client_data, XtGrabNone);
01600 }
01601 
01602 // command callbacks
01603 
01604 static void abortCB(Widget w, XtPointer client_data, XtPointer call_data)
01605 {
01606   sendAbort();
01607 }
01608 
01609 static void homeCB(Widget w, XtPointer client_data, XtPointer call_data)
01610 {
01611   sendHome(activeJoint);
01612 }
01613 
01614 // flag to prevent errors from popping up multiple times
01615 static int errorIsPopped = 0;
01616 
01617 static void errorReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
01618 {
01619   XtPopdown(errorShell);
01620   errorIsPopped = 0;
01621   destroyErrorShell();
01622 }
01623 
01624 static void errorDoneCB(Widget w, XtPointer client_data, XtPointer call_data)
01625 {
01626   XtPopdown(errorShell);
01627   errorIsPopped = 0;
01628   destroyErrorShell();
01629 }
01630 
01631 // createErrorShell() creates the error dialog widget afresh,
01632 // so that it gets sized correctly for each different error message.
01633 // Otherwise, the widget is sized for the first message, and then
01634 // that size is used for all subsequent messages.
01635 
01636 static int createErrorShell()
01637 {
01638   if (NULL != errorShell) {
01639     return 0;
01640   }
01641 
01642   errorShell =
01643     XtVaCreatePopupShell("errorShell",
01644                          transientShellWidgetClass,
01645                          topLevel,
01646                          NULL);
01647 
01648   errorDialog =
01649     XtVaCreateManagedWidget("errorDialog",
01650                             dialogWidgetClass,
01651                             errorShell,
01652                             NULL);
01653 
01654   errorDone =
01655     XtVaCreateManagedWidget("errorDone",
01656                             commandWidgetClass,
01657                             errorDialog,
01658                             NULL);
01659 
01660   XtAddCallback(errorDone, XtNcallback, errorDoneCB, errorShell);
01661 
01662   return 0;
01663 }
01664 
01665 static int destroyErrorShell()
01666 {
01667   if (0 != errorDone)
01668     {
01669       XtDestroyWidget(errorDone);
01670       errorDone = 0;
01671     }
01672 
01673   if (0 != errorDialog)
01674     {
01675       XtDestroyWidget(errorDialog);
01676       errorDialog = 0;
01677     }
01678 
01679   if (0 != errorShell)
01680     {
01681       XtDestroyWidget(errorShell);
01682       errorShell = 0;
01683     }
01684 
01685   return 0;
01686 }
01687 
01688 static void popupError(const char *fmt, ...)
01689 {
01690   va_list ap;
01691   char string[256];             // FIXME-- hardcoded value
01692 
01693   va_start(ap, fmt);
01694   vsprintf(string, fmt, ap);
01695   va_end(ap);
01696 
01697   if (errorIsPopped) {
01698     // we're popped up already, so just print the error to stdout
01699     fprintf(stderr, "error: %s\n", string);
01700     return;
01701   }
01702 
01703   destroyErrorShell();
01704   createErrorShell();
01705 
01706   XtVaSetValues(errorDialog, XtNlabel, string, NULL);
01707   errorIsPopped = 1;
01708   dialogPopup(NULL, errorShell, NULL);
01709   // trap window kill
01710   XSetWMProtocols(XtDisplay(topLevel), XtWindow(errorShell), &killAtom, 1);
01711 }
01712 
01713 // file edit forward decls
01714 static void fileEditorDoneCB(Widget w, XtPointer client_data, XtPointer call_data);
01715 static void fileEditorCancelCB(Widget w, XtPointer client_data, XtPointer call_data);
01716 static void fileEditorMarkCB(Widget w, XtPointer client_data, XtPointer call_data);
01717 static int createFileEditorShell(int writeable);
01718 static int destroyFileEditorShell();
01719 static void doFileEditorDone(int get);
01720 
01721 static void fileEditorDoneCB(Widget w, XtPointer client_data, XtPointer call_data)
01722 {
01723   doFileEditorDone(1);
01724 }
01725 
01726 static void fileEditorCancelCB(Widget w, XtPointer client_data, XtPointer call_data)
01727 {
01728   doFileEditorDone(0);
01729 }
01730 
01731 static void fileEditorMarkCB(Widget w, XtPointer client_data, XtPointer call_data)
01732 {
01733   FILE *fp;
01734   XawTextPosition pos;
01735   int charcount = 0;
01736   int line = 1;
01737   char buffer[256];             // FIXME-- hardcoded
01738 
01739   if (NULL == (fp = fopen(EDITOR_FILE, "r"))) {
01740     return;
01741   }
01742 
01743   programStartLine = 0;
01744   pos = XawTextGetInsertionPoint(fileEditorText);
01745 
01746   while (! feof(fp)) {
01747     if (NULL == fgets(buffer, 256, fp)) {
01748       // hmmm... never found line
01749       popupError("Can't mark line-- character position\n%d outside range of file", pos);
01750       break;
01751     }
01752 
01753     charcount += strlen(buffer);
01754     if (charcount > pos) {
01755       // found it
01756       sendProgramOpen(EDITOR_FILE);
01757       popupError("Marking program to start here:\n%s", buffer);
01758       programStartLine = line;
01759       break;
01760     }
01761 
01762     line++;
01763   }
01764 
01765   fclose(fp);
01766 }
01767 
01768 static int createFileEditorShell(int writeable)
01769 {
01770   char label[256];              // FIXME-- hardcoded
01771 
01772   if (NULL != fileEditorShell) {
01773     return 0;
01774   }
01775 
01776   strcpy(label, EDITOR_FILE);
01777   if (! writeable) {
01778     strcat(label, " (read only)");
01779   }
01780 
01781   fileEditorShell =
01782     XtVaCreatePopupShell("fileEditorShell",
01783                          topLevelShellWidgetClass,
01784                          topLevel,
01785                          XtNallowShellResize, True,
01786                          NULL);
01787 
01788   fileEditorForm =
01789     XtVaCreateManagedWidget("fileEditorForm",
01790                             formWidgetClass,
01791                             fileEditorShell,
01792                             NULL);
01793 
01794   fileEditorLabel =
01795     XtVaCreateManagedWidget("fileEditorLabel",
01796                             labelWidgetClass,
01797                             fileEditorForm,
01798                             XtNlabel, label,
01799                             NULL);
01800 
01801   fileEditorText =
01802     XtVaCreateManagedWidget("fileEditorText",
01803                             asciiTextWidgetClass,
01804                             fileEditorForm,
01805                             XtNfromVert, fileEditorLabel,
01806                             XtNeditType, (writeable ? XawtextEdit :
01807                                           XawtextRead),
01808                             XtNtype, XawAsciiFile,
01809                             XtNstring, EDITOR_FILE,
01810                             XtNscrollVertical, XawtextScrollWhenNeeded,
01811                             NULL);
01812 
01813   fileEditorDone =
01814     XtVaCreateManagedWidget("fileEditorDone",
01815                             commandWidgetClass,
01816                             fileEditorForm,
01817                             XtNfromVert, fileEditorText,
01818                             NULL);
01819 
01820   XtAddCallback(fileEditorDone, XtNcallback, fileEditorDoneCB, fileEditorShell);
01821 
01822   if (writeable) {
01823     XtSetSensitive(fileEditorDone, True);
01824   }
01825   else {
01826     XtSetSensitive(fileEditorDone, False);
01827   }
01828 
01829   fileEditorCancel =
01830     XtVaCreateManagedWidget("fileEditorCancel",
01831                             commandWidgetClass,
01832                             fileEditorForm,
01833                             XtNfromVert, fileEditorText,
01834                             XtNfromHoriz, fileEditorDone,
01835                             NULL);
01836 
01837   XtAddCallback(fileEditorCancel, XtNcallback, fileEditorCancelCB, fileEditorShell);
01838 
01839   fileEditorMark =
01840     XtVaCreateManagedWidget("fileEditorMark",
01841                             commandWidgetClass,
01842                             fileEditorForm,
01843                             XtNfromVert, fileEditorText,
01844                             XtNfromHoriz, fileEditorCancel,
01845                             NULL);
01846 
01847   XtAddCallback(fileEditorMark, XtNcallback, fileEditorMarkCB, fileEditorShell);
01848 
01849   return 0;
01850 }
01851 
01852 static int destroyFileEditorShell()
01853 {
01854   if (fileEditorMark != NULL) {
01855     XtDestroyWidget(fileEditorMark);
01856     fileEditorMark = NULL;
01857   }
01858 
01859   if (fileEditorCancel != NULL) {
01860     XtDestroyWidget(fileEditorCancel);
01861     fileEditorCancel = NULL;
01862   }
01863 
01864   if (fileEditorDone != NULL) {
01865     XtDestroyWidget(fileEditorDone);
01866     fileEditorDone = NULL;
01867   }
01868 
01869   if (fileEditorText != NULL) {
01870     XtDestroyWidget(fileEditorText);
01871     fileEditorText = NULL;
01872   }
01873 
01874   if (fileEditorLabel != NULL) {
01875     XtDestroyWidget(fileEditorLabel);
01876     fileEditorLabel = NULL;
01877   }
01878 
01879   if (fileEditorForm != NULL) {
01880     XtDestroyWidget(fileEditorForm);
01881     fileEditorForm = NULL;
01882   }
01883 
01884   if (fileEditorShell != NULL) {
01885     XtDestroyWidget(fileEditorShell);
01886     fileEditorShell = NULL;
01887   }
01888 
01889   return 0;
01890 }
01891 
01892 static void doFileEditorDone(int get)
01893 {
01894   Widget source;
01895   String string;
01896 
01897   if (get) {
01898     XtVaGetValues(fileEditorText,
01899                   XtNtextSource, &source,
01900                   XtNstring, &string,
01901                   NULL);
01902 
01903     XawAsciiSave(source);
01904   }
01905 
01906   XtPopdown(fileEditorShell);
01907 
01908   destroyFileEditorShell();
01909 }
01910 
01911 // tool table forward decls
01912 static void toolTableDoneCB(Widget w, XtPointer client_data, XtPointer call_data);
01913 static void toolTableCancelCB(Widget w, XtPointer client_data, XtPointer call_data);
01914 static int createToolTableShell();
01915 static int destroyToolTableShell();
01916 static void doToolTableDone(int get);
01917 
01918 static void toolTableDoneCB(Widget w, XtPointer client_data, XtPointer call_data)
01919 {
01920   doToolTableDone(1);
01921 }
01922 
01923 static void toolTableCancelCB(Widget w, XtPointer client_data, XtPointer call_data)
01924 {
01925   doToolTableDone(0);
01926 }
01927 
01928 static int createToolTableShell()
01929 {
01930   if (NULL != toolTableShell) {
01931     return 0;
01932   }
01933 
01934   toolTableShell =
01935     XtVaCreatePopupShell("toolTableShell",
01936                          topLevelShellWidgetClass,
01937                          topLevel,
01938                          XtNallowShellResize, True,
01939                          NULL);
01940 
01941   toolTableForm =
01942     XtVaCreateManagedWidget("toolTableForm",
01943                             formWidgetClass,
01944                             toolTableShell,
01945                             NULL);
01946 
01947   toolTableLabel =
01948     XtVaCreateManagedWidget("toolTableLabel",
01949                             labelWidgetClass,
01950                             toolTableForm,
01951                             XtNlabel, TOOL_TABLE_FILE,
01952                             NULL);
01953 
01954   toolTableText =
01955     XtVaCreateManagedWidget("toolTableText",
01956                             asciiTextWidgetClass,
01957                             toolTableForm,
01958                             XtNfromVert, toolTableLabel,
01959                             XtNeditType, XawtextEdit,
01960                             XtNtype, XawAsciiFile,
01961                             XtNstring, TOOL_TABLE_FILE,
01962                             XtNscrollVertical, XawtextScrollWhenNeeded,
01963                             NULL);
01964 
01965   toolTableDone =
01966     XtVaCreateManagedWidget("toolTableDone",
01967                             commandWidgetClass,
01968                             toolTableForm,
01969                             XtNfromVert, toolTableText,
01970                             NULL);
01971 
01972   XtAddCallback(toolTableDone, XtNcallback, toolTableDoneCB, toolTableShell);
01973 
01974   toolTableCancel =
01975     XtVaCreateManagedWidget("toolTableCancel",
01976                             commandWidgetClass,
01977                             toolTableForm,
01978                             XtNfromVert, toolTableText,
01979                             XtNfromHoriz, toolTableDone,
01980                             NULL);
01981 
01982   XtAddCallback(toolTableCancel, XtNcallback, toolTableCancelCB, toolTableShell);
01983 
01984   return 0;
01985 }
01986 
01987 static int destroyToolTableShell()
01988 {
01989   if (toolTableCancel != NULL) {
01990     XtDestroyWidget(toolTableCancel);
01991     toolTableCancel = NULL;
01992   }
01993 
01994   if (toolTableDone != NULL) {
01995     XtDestroyWidget(toolTableDone);
01996     toolTableDone = NULL;
01997   }
01998 
01999   if (toolTableText != NULL) {
02000     XtDestroyWidget(toolTableText);
02001     toolTableText = NULL;
02002   }
02003 
02004   if (toolTableLabel != NULL) {
02005     XtDestroyWidget(toolTableLabel);
02006     toolTableLabel = NULL;
02007   }
02008 
02009   if (toolTableForm != NULL) {
02010     XtDestroyWidget(toolTableForm);
02011     toolTableForm = NULL;
02012   }
02013 
02014   if (toolTableShell != NULL) {
02015     XtDestroyWidget(toolTableShell);
02016     toolTableShell = NULL;
02017   }
02018 
02019   return 0;
02020 }
02021 
02022 static void doToolTableDone(int get)
02023 {
02024   Widget source;
02025   String string;
02026 
02027   if (get) {
02028     XtVaGetValues(toolTableText,
02029                   XtNtextSource, &source,
02030                   XtNstring, &string,
02031                   NULL);
02032 
02033     XawAsciiSave(source);
02034     sendLoadToolTable(string);
02035   }
02036 
02037   XtPopdown(toolTableShell);
02038 
02039   destroyToolTableShell();
02040 }
02041 
02042 // forward decls
02043 
02044 static void varFileDoneCB(Widget w, XtPointer client_data, XtPointer call_data);
02045 static void varFileCancelCB(Widget w, XtPointer client_data, XtPointer call_data);
02046 static int createVarFileShell();
02047 static int destroyVarFileShell();
02048 static void doVarFileDone(int get);
02049 
02050 static void varFileDoneCB(Widget w, XtPointer client_data, XtPointer call_data)
02051 {
02052   doVarFileDone(1);
02053 }
02054 
02055 static void varFileCancelCB(Widget w, XtPointer client_data, XtPointer call_data)
02056 {
02057   doVarFileDone(0);
02058 }
02059 
02060 static int createVarFileShell()
02061 {
02062   if (NULL != varFileShell) {
02063     return 0;
02064   }
02065 
02066   varFileShell =
02067     XtVaCreatePopupShell("varFileShell",
02068                          topLevelShellWidgetClass,
02069                          topLevel,
02070                          XtNallowShellResize, True,
02071                          NULL);
02072 
02073   varFileForm =
02074     XtVaCreateManagedWidget("varFileForm",
02075                             formWidgetClass,
02076                             varFileShell,
02077                             NULL);
02078 
02079   varFileLabel =
02080     XtVaCreateManagedWidget("varFileLabel",
02081                             labelWidgetClass,
02082                             varFileForm,
02083                             XtNlabel, PARAMETER_FILE,
02084                             NULL);
02085 
02086   varFileText =
02087     XtVaCreateManagedWidget("varFileText",
02088                             asciiTextWidgetClass,
02089                             varFileForm,
02090                             XtNfromVert, varFileLabel,
02091                             XtNeditType, XawtextEdit,
02092                             XtNtype, XawAsciiFile,
02093                             XtNstring, PARAMETER_FILE,
02094                             XtNscrollVertical, XawtextScrollWhenNeeded,
02095                             NULL);
02096 
02097   varFileDone =
02098     XtVaCreateManagedWidget("varFileDone",
02099                             commandWidgetClass,
02100                             varFileForm,
02101                             XtNfromVert, varFileText,
02102                             NULL);
02103 
02104   XtAddCallback(varFileDone, XtNcallback, varFileDoneCB, varFileShell);
02105 
02106   varFileCancel =
02107     XtVaCreateManagedWidget("varFileCancel",
02108                             commandWidgetClass,
02109                             varFileForm,
02110                             XtNfromVert, varFileText,
02111                             XtNfromHoriz, varFileDone,
02112                             NULL);
02113 
02114   XtAddCallback(varFileCancel, XtNcallback, varFileCancelCB, varFileShell);
02115 
02116   return 0;
02117 }
02118 
02119 static int destroyVarFileShell()
02120 {
02121   if (varFileCancel != NULL) {
02122     XtDestroyWidget(varFileCancel);
02123     varFileCancel = NULL;
02124   }
02125 
02126   if (varFileDone != NULL) {
02127     XtDestroyWidget(varFileDone);
02128     varFileDone = NULL;
02129   }
02130 
02131   if (varFileText != NULL) {
02132     XtDestroyWidget(varFileText);
02133     varFileText = NULL;
02134   }
02135 
02136   if (varFileLabel != NULL) {
02137     XtDestroyWidget(varFileLabel);
02138     varFileLabel = NULL;
02139   }
02140 
02141   if (varFileForm != NULL) {
02142     XtDestroyWidget(varFileForm);
02143     varFileForm = NULL;
02144   }
02145 
02146   if (varFileShell != NULL) {
02147     XtDestroyWidget(varFileShell);
02148     varFileShell = NULL;
02149   }
02150 
02151   return 0;
02152 }
02153 
02154 static void doVarFileDone(int get)
02155 {
02156   Widget source;
02157   String string;
02158 
02159   if (get) {
02160   XtVaGetValues(varFileText,
02161                 XtNtextSource, &source,
02162                 XtNstring, &string,
02163                 NULL);
02164 
02165   XawAsciiSave(source);
02166   sendTaskPlanInit();
02167   }
02168 
02169   XtPopdown(varFileShell);
02170 
02171   destroyVarFileShell();
02172 }
02173 
02174 // diagnostics dialog
02175 
02176 static Widget diagnosticsShell = NULL;
02177 static Widget diagnosticsForm = NULL;
02178 static Widget diagnosticsLabel = NULL;
02179 static Widget diagnosticsTaskHBLabel = NULL;
02180 static Widget diagnosticsTaskHB = NULL;
02181 static Widget diagnosticsIoHBLabel = NULL;
02182 static Widget diagnosticsIoHB = NULL;
02183 static Widget diagnosticsMotionHBLabel = NULL;
02184 static Widget diagnosticsMotionHB= NULL;
02185 static Widget diagnosticsFerrorLabel = NULL;
02186 static Widget diagnosticsFerror = NULL;
02187 static Widget diagnosticsDone = NULL;
02188 
02189 // flag that window is up, so we don't waste time updating labels
02190 static int diagnosticsIsPopped = 0;
02191 
02192 static void diagnosticsDoDone()
02193 {
02194   diagnosticsIsPopped = 0;
02195   XtPopdown(diagnosticsShell);
02196 }
02197 
02198 static void diagnosticsDoneCB(Widget w, XtPointer client_data, XtPointer call_data)
02199 {
02200   diagnosticsDoDone();
02201 }
02202 
02203 static void diagnosticsReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02204 {
02205   diagnosticsDoDone();
02206 }
02207 
02208 static Pixel fileOpenBorderColor;
02209 static int fileOpenDoDone = 1;
02210 
02211 static void doFileOpenDone()
02212 {
02213   String string;
02214 
02215   if (fileOpenDoDone) {
02216     // note: "*value: " must be set in resources for input box
02217     // to appear, and for this to be valid (and not dump core)
02218     string = XawDialogGetValueString(fileOpenDialog);
02219     // set value to be the same in file edit dialog
02220     strcpy(EDITOR_FILE, string);
02221     XtVaSetValues(fileEditDialog, XtNvalue, EDITOR_FILE, NULL);
02222     sendProgramOpen(string);
02223   }
02224 
02225   setBorderColor(fileOpenDone, pixelRed);
02226   setBorderColor(fileOpenCancel, fileOpenBorderColor);
02227   fileOpenDoDone = 1;
02228 
02229   XtPopdown(fileOpenShell);
02230 }
02231 
02232 static void fileOpenDoneCB(Widget w, XtPointer client_data, XtPointer call_data)
02233 {
02234   doFileOpenDone();
02235 }
02236 
02237 static void fileOpenReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02238 {
02239   doFileOpenDone();
02240 }
02241 
02242 static void fileOpenTabAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02243 {
02244   if (fileOpenDoDone) {
02245     setBorderColor(fileOpenDone, fileOpenBorderColor);
02246     setBorderColor(fileOpenCancel, pixelRed);
02247     fileOpenDoDone = 0;
02248   }
02249   else {
02250     setBorderColor(fileOpenDone, pixelRed);
02251     setBorderColor(fileOpenCancel, fileOpenBorderColor);
02252     fileOpenDoDone = 1;
02253   }
02254 }
02255 
02256 static Pixel fileQuitBorderColor;
02257 static int fileQuitDoDone = 1;
02258 
02259 static void doFileQuitDone()
02260 {
02261   XtPopdown(fileQuitShell);
02262 
02263   if (fileQuitDoDone) {
02264     quit();
02265   }
02266   else {
02267     setBorderColor(fileQuitDone, pixelRed);
02268     setBorderColor(fileQuitCancel, fileQuitBorderColor);
02269     fileQuitDoDone = 1;
02270   }
02271 }
02272 
02273 static void fileQuitDoneCB(Widget w, XtPointer client_data, XtPointer call_data)
02274 {
02275   doFileQuitDone();
02276 }
02277 
02278 static void fileQuitReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02279 {
02280   doFileQuitDone();
02281 }
02282 
02283 static void fileQuitTabAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02284 {
02285   if (fileQuitDoDone) {
02286     setBorderColor(fileQuitDone, fileQuitBorderColor);
02287     setBorderColor(fileQuitCancel, pixelRed);
02288     fileQuitDoDone = 0;
02289   }
02290   else {
02291     setBorderColor(fileQuitDone, pixelRed);
02292     setBorderColor(fileQuitCancel, fileQuitBorderColor);
02293     fileQuitDoDone = 1;
02294   }
02295 }
02296 
02297 static Pixel fileEditBorderColor;
02298 static int fileEditDoDone = 1;
02299 
02300 static void doFileEditDone()
02301 {
02302   String string;
02303   struct stat buf;
02304   int fd;
02305 
02306   if (fileEditDoDone) {
02307     string = XawDialogGetValueString(fileEditDialog);
02308     // set value to be the same in file open dialog
02309     strcpy(EDITOR_FILE, string);
02310     XtVaSetValues(fileOpenDialog, XtNvalue, EDITOR_FILE, NULL);
02311   }
02312 
02313   XtPopdown(fileEditShell);
02314 
02315   if (fileEditDoDone) {
02316     if (-1 == stat(EDITOR_FILE, &buf)) {
02317       // file not found-- it's a new one. Touch it so that it
02318       // exists and the text widget won't barf
02319       fd = open(EDITOR_FILE, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
02320       close(fd);
02321       createFileEditorShell(1);
02322       dialogPopup(NULL, fileEditorShell, NULL);
02323       // trap window kill
02324       XSetWMProtocols(XtDisplay(topLevel), XtWindow(fileEditorShell), &killAtom, 1);
02325     }
02326     else {
02327       // file is there-- check type and permissions
02328       if (! S_ISREG(buf.st_mode)) {
02329         // file is not a regular file
02330         popupError("Can't edit %S: not a text file", EDITOR_FILE);
02331       }
02332       else if ((S_IWUSR & buf.st_mode)) {
02333         // file is writeable
02334         createFileEditorShell(1);
02335         dialogPopup(NULL, fileEditorShell, NULL);
02336         // trap window kill
02337         XSetWMProtocols(XtDisplay(topLevel), XtWindow(fileEditorShell), &killAtom, 1);
02338       }
02339       else {
02340         // file is read-only
02341         createFileEditorShell(0);
02342         dialogPopup(NULL, fileEditorShell, NULL);
02343         // trap window kill
02344         XSetWMProtocols(XtDisplay(topLevel), XtWindow(fileEditorShell), &killAtom, 1);
02345       }
02346     }
02347   }
02348 
02349   setBorderColor(fileEditDone, pixelRed);
02350   setBorderColor(fileEditCancel, fileEditBorderColor);
02351   fileEditDoDone = 1;
02352 }
02353 
02354 static void fileEditDoneCB(Widget w, XtPointer client_data, XtPointer call_data)
02355 {
02356   doFileEditDone();
02357 }
02358 
02359 static void fileEditReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02360 {
02361   doFileEditDone();
02362 }
02363 
02364 static void fileEditTabAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02365 {
02366   if (fileEditDoDone) {
02367     setBorderColor(fileEditDone, fileEditBorderColor);
02368     setBorderColor(fileEditCancel, pixelRed);
02369     fileEditDoDone = 0;
02370   }
02371   else {
02372     setBorderColor(fileEditDone, pixelRed);
02373     setBorderColor(fileEditCancel, fileEditBorderColor);
02374     fileEditDoDone = 1;
02375   }
02376 }
02377 
02378 static void toolSetOffsetDoDone(int done)
02379 {
02380   String str1, str2, str3;
02381   int tool;
02382   double length;
02383   double diameter;
02384 
02385   if (done) {
02386     XtVaGetValues(toolSetOffsetTool, XtNstring, &str1, NULL);
02387     XtVaGetValues(toolSetOffsetLength, XtNstring, &str2, NULL);
02388     XtVaGetValues(toolSetOffsetDiameter, XtNstring, &str3, NULL);
02389 
02390     if (1 == sscanf(str1, "%d", &tool) &&
02391         1 == sscanf(str2, "%lf", &length) &&
02392         1 == sscanf(str3, "%lf", &diameter)) {
02393       sendToolSetOffset(tool, length, diameter);
02394     }
02395   }
02396 
02397   XtPopdown(toolSetOffsetShell);
02398 }
02399 
02400 static void toolSetOffsetUpAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02401 {
02402   char string[256];
02403 
02404   sprintf(string, "%d", emcStatus->io.tool.toolInSpindle);
02405   XtVaSetValues(toolSetOffsetTool, XtNstring, string, NULL);
02406   sprintf(string, "%f",
02407           emcStatus->motion.traj.actualPosition.tran.z -
02408           emcStatus->task.origin.tran.z);
02409   XtVaSetValues(toolSetOffsetLength, XtNstring, string, NULL);
02410   XtVaSetValues(toolSetOffsetDiameter, XtNstring, "0.0", NULL);
02411 
02412   dialogPopup(NULL, toolSetOffsetShell, NULL);
02413   // trap window kill
02414   XSetWMProtocols(XtDisplay(topLevel), XtWindow(toolSetOffsetShell), &killAtom, 1);
02415 }
02416 
02417 static Pixel toolSetOffsetFormBorderColor;
02418 static int toolSetOffsetReturnIsDone = 1;
02419 
02420 static void toolSetOffsetReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02421 {
02422   if (toolSetOffsetReturnIsDone) {
02423     toolSetOffsetDoDone(1);
02424   }
02425   else {
02426     toolSetOffsetDoDone(0);
02427   }
02428 }
02429 
02430 static void toolSetOffsetDoneCB(Widget w, XtPointer client_data, XtPointer call_data)
02431 {
02432   toolSetOffsetDoDone(1);
02433 }
02434 
02435 static void toolSetOffsetCancelCB(Widget w, XtPointer client_data, XtPointer call_data)
02436 {
02437   toolSetOffsetDoDone(0);
02438 }
02439 
02440 static void toolSetOffsetTabAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02441 {
02442   if (toolSetOffsetReturnIsDone) {
02443     setBorderColor(toolSetOffsetDone, toolSetOffsetFormBorderColor);
02444     setBorderColor(toolSetOffsetCancel, pixelRed);
02445     toolSetOffsetReturnIsDone = 0;
02446   }
02447   else {
02448     setBorderColor(toolSetOffsetDone, pixelRed);
02449     setBorderColor(toolSetOffsetCancel, toolSetOffsetFormBorderColor);
02450     toolSetOffsetReturnIsDone = 1;
02451   }
02452 }
02453 
02454 static void doPosOffsetDone()
02455 {
02456   String string;
02457   char cmd[256];
02458   double val;
02459 
02460   string = XawDialogGetValueString(posOffsetDialog);
02461 
02462   if (1 == sscanf(string, "%lf", &val)) {
02463     // send MDI command
02464     // FIXME-- this RS-274-NGC specific; need to add NML way to do this
02465     sprintf(cmd, "G92%s%f\n",
02466             activeCoord == 0 ? "X" :
02467             activeCoord == 1 ? "Y" :
02468             activeCoord == 2 ? "Z" : "X",
02469             val);
02470     sendMdiCmd(cmd);
02471   }
02472 
02473   XtPopdown(posOffsetShell);
02474 }
02475 
02476 static void posOffsetUpAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02477 {
02478   int axis;
02479 
02480   // disallow pos offset if joints are displayed
02481   if (posFrame == POS_FRAME_JOINT) {
02482     return;
02483   }
02484 
02485   for (axis = 0; axis < numPosLabels; axis++) {
02486     if (w == posLabel[axis]) {
02487       activeCoord = axis;
02488       break;
02489     }
02490   }
02491 
02492   XtVaSetValues(posOffsetDialog, XtNvalue, "0.0", NULL);
02493   dialogPopup(NULL, posOffsetShell, NULL);
02494   // trap window kill
02495   XSetWMProtocols(XtDisplay(topLevel), XtWindow(posOffsetShell), &killAtom, 1);
02496 }
02497 
02498 static void posOffsetReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02499 {
02500   doPosOffsetDone();
02501 }
02502 
02503 static void doJogSpeedDone()
02504 {
02505   String string;
02506   int val;
02507   char labelString[80];
02508 
02509   string = XawDialogGetValueString(jogSpeedDialog);
02510 
02511   if (1 == sscanf(string, "%d", &val)) {
02512     jogSpeed = val;
02513     if (jogSpeed > maxJogSpeed) {
02514       jogSpeed = maxJogSpeed;
02515     }
02516     sprintf(labelString, "%d", jogSpeed);
02517     setLabel(jogSpeedLabel, labelString);
02518     redraw = 1;
02519   }
02520 
02521   XtPopdown(jogSpeedShell);
02522 }
02523 
02524 static void jogSpeedReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02525 {
02526   doJogSpeedDone();
02527 }
02528 
02529 static void doFeedOverrideDone()
02530 {
02531   String string;
02532   double val;
02533 
02534   string = XawDialogGetValueString(feedOverrideDialog);
02535 
02536   if (1 == sscanf(string, "%lf", &val)) {
02537     sendFeedOverride(val / 100.0);
02538   }
02539 
02540   XtPopdown(feedOverrideShell);
02541 }
02542 
02543 static void feedOverrideReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02544 {
02545   doFeedOverrideDone();
02546 }
02547 
02548 static void programRunCB(Widget w, XtPointer client_data, XtPointer call_data)
02549 {
02550   sendProgramRun(programStartLine);
02551 }
02552 
02553 static void programPauseCB(Widget w, XtPointer client_data, XtPointer call_data)
02554 {
02555   sendProgramPause();
02556 }
02557 
02558 static void programResumeCB(Widget w, XtPointer client_data, XtPointer call_data)
02559 {
02560   sendProgramResume();
02561 }
02562 
02563 static void programStepCB(Widget w, XtPointer client_data, XtPointer call_data)
02564 {
02565   sendProgramStep();
02566 }
02567 
02568 static void programVerifyCB(Widget w, XtPointer client_data, XtPointer call_data)
02569 {
02570   programStartLine = -1;
02571   sendProgramRun(programStartLine);
02572 }
02573 
02574 static void helpXemcReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02575 {
02576   XtPopdown(helpXemcShell);
02577 }
02578 
02579 static void helpAboutReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02580 {
02581   XtPopdown(helpAboutShell);
02582 }
02583 
02584 static void genericDoneCB(Widget w, XtPointer client_data, XtPointer call_data)
02585 {
02586   XtPopdown((Widget) client_data);
02587 }
02588 
02589 // button handling code
02590 
02591 static void downAction(Widget w,
02592                        XEvent *ev,
02593                        String *params,
02594                        Cardinal *numParams)
02595 {
02596   int axis;
02597   char string[80];
02598 
02599   for (axis = 0; axis < numPosLabels; axis++) {
02600     if (w == posLabel[axis]) {
02601         activeJoint = axis;
02602         activeCoord = axis;
02603         return;
02604     }
02605   }
02606 
02607   if (w == spindleIncLabel) {
02608     sendSpindleIncrease();
02609   }
02610   else if (w == spindleDecLabel) {
02611     sendSpindleDecrease();
02612   }
02613   else if (w == jogMinusLabel) {
02614     if (jogIncrement > 0.0) {
02615       sendJogIncr(activeJoint, -jogSpeed, jogIncrement);
02616     }
02617     else {
02618          if (posFrame == POS_FRAME_JOINT) 
02619            {
02620              sendJogCont(activeJoint, -jogSpeed);
02621            }
02622          else
02623            {
02624              sendJogCont(coordNum[activeCoord], -jogSpeed);
02625            }
02626     }
02627   }
02628   else if (w == jogPlusLabel) {
02629     if (jogIncrement > 0.0) {
02630       sendJogIncr(activeJoint, jogSpeed, jogIncrement);
02631     }
02632     else {
02633          if (posFrame == POS_FRAME_JOINT) 
02634            {
02635              sendJogCont(activeJoint, -jogSpeed);
02636            }
02637          else
02638            {
02639              sendJogCont(coordNum[activeCoord], -jogSpeed);
02640            }
02641     }
02642   }
02643   else if (w == jogSpeedLabel) {
02644     // pop up menu to change jog speed
02645     XtVaSetValues(jogSpeedDialog,
02646                   XtNvalue, "",
02647                   NULL);
02648     dialogPopup(NULL, jogSpeedShell, NULL);
02649     // trap window kill
02650     XSetWMProtocols(XtDisplay(topLevel), XtWindow(jogSpeedShell), &killAtom, 1);
02651   }
02652   else if (w == jogSpeedDecLabel) {
02653     // change it once here and redraw
02654     if (--jogSpeed <= 0) {
02655       jogSpeed = 1;
02656     }
02657     sprintf(string, "%d", jogSpeed);
02658     setLabel(jogSpeedLabel, string);
02659     redraw = 1;
02660 
02661     // set jogSpeedChange so that timer callback will continue to change
02662     // until button up clears it
02663     jogSpeedChange = -1;
02664   }
02665   else if (w == jogSpeedIncLabel) {
02666     // change it once here and redraw
02667     if (++jogSpeed > maxJogSpeed) {
02668       jogSpeed = maxJogSpeed;
02669     }
02670     sprintf(string, "%d", jogSpeed);
02671     setLabel(jogSpeedLabel, string);
02672     redraw = 1;
02673 
02674     // set jogSpeedChange so that timer callback will continue to change
02675     // until button up clears it
02676     jogSpeedChange = +1;
02677   }
02678   else if (w == feedOverrideLabel) {
02679     // pop up menu to change feed override
02680     XtVaSetValues(feedOverrideDialog,
02681                   XtNvalue, "",
02682                   NULL);
02683     dialogPopup(NULL, feedOverrideShell, NULL);
02684     // trap window kill
02685     XSetWMProtocols(XtDisplay(topLevel), XtWindow(feedOverrideShell), &killAtom, 1);
02686   }
02687   else if (w == feedOverrideDecLabel) {
02688     // change it once here and redraw
02689     if ((feedOverride -= 10) <= 0) {
02690       feedOverride = 0;
02691     }
02692     sprintf(string, "%3d", feedOverride);
02693     setLabel(feedOverrideLabel, string);
02694     redraw = 1;
02695 
02696     // set feedOverrideChange so that timer callback will continue to change
02697     // until button up clears it
02698     feedOverrideChange = -1;
02699   }
02700   else if (w == feedOverrideIncLabel) {
02701     // change it once here and redraw
02702     if ((feedOverride += 10) > maxFeedOverride) {
02703       feedOverride = maxFeedOverride;
02704     }
02705     sprintf(string, "%3d", feedOverride);
02706     setLabel(feedOverrideLabel, string);
02707     redraw = 1;
02708 
02709     // set feedOverrideChange so that timer callback will continue to change
02710     // until button up clears it
02711     feedOverrideChange = +1;
02712   }
02713   else {
02714     printf("down\n");
02715   }
02716 }
02717 
02718 static void upAction(Widget w,
02719                      XEvent *ev,
02720                      String *params,
02721                      Cardinal *numParams)
02722 {
02723   int axis;
02724 
02725   for (axis = 0; axis < numPosLabels; axis++) {
02726     if (w == posLabel[axis]) {
02727       return;
02728     }
02729   }
02730 
02731   if (w == spindleIncLabel) {
02732     sendSpindleConstant();
02733   }
02734   else if (w == spindleDecLabel) {
02735     sendSpindleConstant();
02736   }
02737   else if (w == jogMinusLabel) {
02738     // only stop it if it's continuous jogging
02739     if (jogIncrement <= 0.0) {
02740       sendJogStop(axisJogging);
02741     }
02742   }
02743   else if (w == jogPlusLabel) {
02744     // only stop it if it's continuous jogging
02745     if (jogIncrement <= 0.0) {
02746       sendJogStop(axisJogging);
02747     }
02748   }
02749   else if (w == jogSpeedDecLabel) {
02750     jogSpeedChange = 0;
02751   }
02752   else if (w == jogSpeedIncLabel) {
02753     jogSpeedChange = 0;
02754   }
02755   else if (w == feedOverrideDecLabel) {
02756     feedOverrideChange = 0;
02757     sendFeedOverride((double) feedOverride / 100.0);
02758   }
02759   else if (w == feedOverrideIncLabel) {
02760     feedOverrideChange = 0;
02761     sendFeedOverride((double) feedOverride / 100.0);
02762   }
02763   else {
02764     printf("up\n");
02765   }
02766 }
02767 
02768 static void mdiReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
02769 {
02770   String string;
02771 
02772   XtVaGetValues(mdiFormText, XtNstring, &string, NULL);
02773 
02774   sendMdiCmd(string);
02775 }
02776 
02777 // key handling code
02778 
02779 // FIXME-- better way to get these?
02780 #define XEVENT_TYPE_XKEY_KEY_PRESS_EVENT 2
02781 #define XEVENT_TYPE_XKEY_KEY_RELEASE_EVENT 3
02782 #define XKEY_EVENT_STATE_NONE    0x00
02783 #define XKEY_EVENT_STATE_SHIFT   0x01
02784 #define XKEY_EVENT_STATE_CONTROL 0x04
02785 #define XKEY_EVENT_STATE_ALT     0x08
02786 
02787 #define KEY_ESC     9
02788 #define KEY_F1     67
02789 #define KEY_F2     68
02790 #define KEY_F3     69
02791 #define KEY_F4     70
02792 #define KEY_F5     71
02793 #define KEY_F6     72
02794 #define KEY_F7     73
02795 #define KEY_F8     74
02796 #define KEY_F9     75
02797 #define KEY_F10    76
02798 #define KEY_F11    95
02799 #define KEY_F12    96
02800 #define KEY_PGUP   99
02801 #define KEY_PGDN  105
02802 #define KEY_LEFT  100
02803 #define KEY_RIGHT 102
02804 #define KEY_UP     98
02805 #define KEY_DOWN  104
02806 #define KEY_X      53
02807 #define KEY_Y      29
02808 #define KEY_Z      52
02809 #define KEY_HOME   97
02810 #define KEY_END   103
02811 #define KEY_1      10
02812 #define KEY_2      11
02813 #define KEY_3      12
02814 #define KEY_4      13
02815 #define KEY_5      14
02816 #define KEY_6      15
02817 #define KEY_7      16
02818 #define KEY_8      17
02819 #define KEY_9      18
02820 #define KEY_0      19
02821 #define KEY_Q      24
02822 #define KEY_W      25
02823 #define KEY_E      26
02824 #define KEY_R      27
02825 #define KEY_T      28
02826 #define KEY_Y      29
02827 #define KEY_I      31
02828 #define KEY_O      32
02829 #define KEY_P      33
02830 #define KEY_A      38
02831 #define KEY_S      39
02832 #define KEY_D      40
02833 #define KEY_F      41
02834 #define KEY_G      42
02835 #define KEY_H      43
02836 #define KEY_V      55
02837 #define KEY_B      56
02838 #define KEY_COMMA  59
02839 #define KEY_PERIOD 60
02840 #define KEY_C      54
02841 
02842 static int keyReleaseOut = 0;   // set if we saw a release, cleared right away
02843                                 // if the key repeat kicks back on, else it
02844                                 // goes through as a true key release
02845 static double keyReleaseTime = 0.0;
02846 static unsigned int keyPressState;
02847 static unsigned int keyPressKeycode;
02848 static unsigned int keyReleaseState;
02849 static unsigned int keyReleaseKeycode;
02850 
02851 static void keyPressAction(unsigned int state, unsigned int keycode)
02852 {
02853   char string[256];
02854   static double saveJogIncrement = 0.1000;
02855 
02856   switch (keycode) {
02857 
02858   case KEY_ESC:
02859     sendAbort();
02860     break;
02861 
02862   case KEY_F1:
02863     // estop toggle
02864     if (emcStatus->task.state == EMC_TASK_STATE_ESTOP) {
02865       sendEstopReset();
02866     }
02867     else {
02868       sendEstop();
02869     }
02870     break;
02871 
02872   case KEY_F2:
02873     // estop toggle
02874     if (emcStatus->task.state == EMC_TASK_STATE_ESTOP_RESET) {
02875       sendMachineOn();
02876     }
02877     else {
02878       sendMachineOff();
02879     }
02880     break;
02881 
02882   case KEY_F3:
02883     // manual mode
02884     sendManual();
02885     break;
02886 
02887   case KEY_F4:
02888     // auto mode
02889     sendAuto();
02890     break;
02891 
02892   case KEY_F5:
02893     // mdi mode
02894     sendMdi();
02895     break;
02896 
02897   case KEY_F6:
02898     sendTaskPlanInit();
02899     break;
02900 
02901   case KEY_F7:
02902     // mist toggle
02903     if (emcStatus->io.coolant.mist) {
02904       sendMistOff();
02905     }
02906     else {
02907       sendMistOn();
02908     }
02909     break;
02910 
02911   case KEY_F8:
02912     // flood toggle
02913     if (emcStatus->io.coolant.flood) {
02914       sendFloodOff();
02915     }
02916     else {
02917       sendFloodOn();
02918     }
02919     break;
02920 
02921   case KEY_F9:
02922     // spindle fwd/off
02923     if (emcStatus->io.spindle.direction == 0) {
02924       // it's off, so turn forward
02925       sendSpindleForward();
02926     }
02927     else
02928       {
02929         // it's not off, so turn off
02930         sendSpindleOff();
02931       }
02932     break;
02933 
02934   case KEY_F10:
02935     // spindle rev/off
02936     if (emcStatus->io.spindle.direction == 0) {
02937       // it's off, so turn reverse
02938       sendSpindleReverse();
02939     }
02940     else
02941       {
02942         // it's not off, so turn off
02943         sendSpindleOff();
02944       }
02945     break;
02946 
02947   case KEY_F11:
02948     // spindle decrease
02949     if (emcStatus->io.spindle.direction != 0) {
02950       sendSpindleDecrease();
02951     }
02952     break;
02953 
02954   case KEY_F12:
02955     // spindle increase
02956     if (emcStatus->io.spindle.direction != 0) {
02957       sendSpindleIncrease();
02958     }
02959     break;
02960 
02961   case KEY_RIGHT:
02962     switch (state) {
02963     case XKEY_EVENT_STATE_ALT:
02964       activeJoint = 3;
02965       break;
02966     default:
02967       activeJoint = 0;
02968       break;
02969     }
02970     if (jogIncrement > 0.0) {
02971       sendJogIncr(activeJoint, jogSpeed, jogIncrement);
02972     }
02973     else {
02974       sendJogCont(activeJoint, jogSpeed);
02975     }
02976     break;
02977 
02978   case KEY_LEFT:
02979     switch (state) {
02980     case XKEY_EVENT_STATE_ALT:
02981       activeJoint = 3;
02982       break;
02983     default:
02984       activeJoint = 0;
02985       break;
02986     }
02987     if (jogIncrement > 0.0) {
02988       sendJogIncr(activeJoint, -jogSpeed, jogIncrement);
02989     }
02990     else {
02991       sendJogCont(activeJoint, -jogSpeed);
02992     }
02993     break;
02994 
02995   case KEY_UP:
02996     switch (state) {
02997     case XKEY_EVENT_STATE_ALT:
02998       activeJoint = 4;
02999       break;
03000     default:
03001       activeJoint = 1;
03002       break;
03003     }
03004     if (jogIncrement > 0.0) {
03005       sendJogIncr(activeJoint, jogSpeed, jogIncrement);
03006     }
03007     else {
03008       sendJogCont(activeJoint, jogSpeed);
03009     }
03010     break;
03011 
03012   case KEY_DOWN:
03013     switch (state) {
03014     case XKEY_EVENT_STATE_ALT:
03015       activeJoint = 4;
03016       break;
03017     default:
03018       activeJoint = 1;
03019       break;
03020     }
03021     if (jogIncrement > 0.0) {
03022       sendJogIncr(activeJoint, -jogSpeed, jogIncrement);
03023     }
03024     else {
03025       sendJogCont(activeJoint, -jogSpeed);
03026     }
03027     break;
03028 
03029   case KEY_PGUP:
03030     switch (state) {
03031     case XKEY_EVENT_STATE_ALT:
03032       activeJoint = 5;
03033       break;
03034     default:
03035       activeJoint = 2;
03036       break;
03037     }
03038     if (jogIncrement > 0.0) {
03039       sendJogIncr(activeJoint, jogSpeed, jogIncrement);
03040     }
03041     else {
03042       sendJogCont(activeJoint, jogSpeed);
03043     }
03044     break;
03045 
03046   case KEY_PGDN:
03047     switch (state) {
03048     case XKEY_EVENT_STATE_ALT:
03049       activeJoint = 5;
03050       break;
03051     default:
03052       activeJoint = 2;
03053       break;
03054     }
03055     if (jogIncrement > 0.0) {
03056       sendJogIncr(activeJoint, -jogSpeed, jogIncrement);
03057     }
03058     else {
03059       sendJogCont(activeJoint, -jogSpeed);
03060     }
03061     break;
03062 
03063   case KEY_Q:
03064     if (emcStatus->task.mode == EMC_TASK_MODE_MANUAL) {
03065       if (numJoints <= 0)
03066         break; // joint out of range
03067       activeJoint = 0;
03068       if (jogIncrement > 0.0) {
03069         sendJogIncr(activeJoint, jogSpeed, jogIncrement);
03070       }
03071       else {
03072         sendJogCont(activeJoint, jogSpeed);
03073       }
03074     }
03075     break;
03076 
03077   case KEY_W:
03078     if (emcStatus->task.mode == EMC_TASK_MODE_MANUAL) {
03079       if (numJoints <= 1)
03080         break; // joint out of range
03081       activeJoint = 1;
03082       if (jogIncrement > 0.0) {
03083         sendJogIncr(activeJoint, jogSpeed, jogIncrement);
03084       }
03085       else {
03086         sendJogCont(activeJoint, jogSpeed);
03087       }
03088     }
03089     break;
03090 
03091   case KEY_E:
03092     if (emcStatus->task.mode == EMC_TASK_MODE_MANUAL) {
03093       if (numJoints <= 2)
03094         break; // joint out of range
03095       activeJoint = 2;
03096       if (jogIncrement > 0.0) {
03097         sendJogIncr(activeJoint, jogSpeed, jogIncrement);
03098       }
03099       else {
03100         sendJogCont(activeJoint, jogSpeed);
03101       }
03102     }
03103     else {
03104       dialogPopup(NULL, fileEditShell, NULL);
03105       // trap window kill
03106       XSetWMProtocols(XtDisplay(topLevel), XtWindow(fileEditShell), &killAtom, 1);
03107     }
03108     break;
03109 
03110   case KEY_R:
03111     if (emcStatus->task.mode == EMC_TASK_MODE_MANUAL) {
03112       if (numJoints <= 3)
03113         break; // joint out of range
03114       activeJoint = 3;
03115       if (jogIncrement > 0.0) {
03116         sendJogIncr(activeJoint, jogSpeed, jogIncrement);
03117       }
03118       else {
03119         sendJogCont(activeJoint, jogSpeed);
03120       }
03121     }
03122     else {
03123       sendProgramRun(programStartLine);
03124     }
03125     break;
03126 
03127   case KEY_T:
03128     if (emcStatus->task.mode == EMC_TASK_MODE_MANUAL) {
03129       if (numJoints <= 4)
03130         break; // joint out of range
03131       activeJoint = 4;
03132       if (jogIncrement > 0.0) {
03133         sendJogIncr(activeJoint, jogSpeed, jogIncrement);
03134       }
03135       else {
03136         sendJogCont(activeJoint, jogSpeed);
03137       }
03138     }
03139     else {
03140       switch (state) {
03141       case XKEY_EVENT_STATE_ALT:
03142         sprintf(string, "%d", emcStatus->io.tool.toolInSpindle);
03143         XtVaSetValues(toolSetOffsetTool, XtNstring, string, NULL);
03144         sprintf(string, "%f",
03145                 emcStatus->motion.traj.actualPosition.tran.z -
03146                 emcStatus->task.origin.tran.z);
03147         XtVaSetValues(toolSetOffsetLength, XtNstring, string, NULL);
03148         XtVaSetValues(toolSetOffsetDiameter, XtNstring, "0.0", NULL);
03149         dialogPopup(NULL, toolSetOffsetShell, NULL);
03150         // trap window kill
03151         XSetWMProtocols(XtDisplay(topLevel), XtWindow(toolSetOffsetShell), &killAtom, 1);
03152         break;
03153       }
03154     }
03155     break;
03156 
03157   case KEY_Y:
03158     if (emcStatus->task.mode == EMC_TASK_MODE_MANUAL) {
03159       if (numJoints <= 5)
03160         break; // joint out of range
03161       activeJoint = 5;
03162       if (jogIncrement > 0.0) {
03163         sendJogIncr(activeJoint, jogSpeed, jogIncrement);
03164       }
03165       else {
03166         sendJogCont(activeJoint, jogSpeed);
03167       }
03168     }
03169     break;
03170 
03171   case KEY_X:
03172     break;
03173 
03174   case KEY_Z:
03175     break;
03176 
03177   case KEY_HOME:
03178     sendHome(activeJoint);
03179     break;
03180 
03181   case KEY_END:
03182     dialogPopup(NULL, fileQuitShell, NULL);
03183     // trap window kill
03184     XSetWMProtocols(XtDisplay(topLevel), XtWindow(fileQuitShell), &killAtom, 1);
03185     break;
03186 
03187   case KEY_1:
03188       sendFeedOverride(0.1);
03189     break;
03190 
03191   case KEY_2:
03192     switch (state) {
03193     case XKEY_EVENT_STATE_NONE:
03194       sendFeedOverride(0.2);
03195       break;
03196 
03197     case XKEY_EVENT_STATE_SHIFT:
03198       // @
03199       if (posDisplay == POS_DISPLAY_CMD) {
03200         posDisplay = POS_DISPLAY_ACT;
03201       }
03202       else {
03203         posDisplay = POS_DISPLAY_CMD;
03204       }
03205       break;
03206 
03207     }
03208     break;
03209 
03210   case KEY_3:
03211     switch (state) {
03212     case XKEY_EVENT_STATE_NONE:
03213       sendFeedOverride(0.3);
03214       break;
03215 
03216     case XKEY_EVENT_STATE_SHIFT:
03217       if (coords == COORD_RELATIVE) {
03218         coords = COORD_MACHINE;
03219       }
03220       else {
03221         coords = COORD_RELATIVE;
03222       }
03223       break;
03224 
03225     }
03226     break;
03227 
03228   case KEY_4:
03229     switch (state) {
03230     case XKEY_EVENT_STATE_NONE:
03231       sendFeedOverride(0.4);
03232       break;
03233 
03234     case XKEY_EVENT_STATE_SHIFT:
03235       EMC_TRAJ_SET_TELEOP_ENABLE emc_traj_set_teleop_enable;
03236       if (posFrame == POS_FRAME_WORLD) {
03237         posFrame = POS_FRAME_JOINT;
03238         emc_traj_set_teleop_enable.enable = 0;
03239       }
03240       else {
03241         posFrame = POS_FRAME_WORLD;
03242         emc_traj_set_teleop_enable.enable = 1;
03243       }
03244       emc_traj_set_teleop_enable.serial_number = ++emcCommandSerialNumber;
03245       emcCommandBuffer->write(&emc_traj_set_teleop_enable);
03246       break;
03247 
03248     }
03249     break;
03250 
03251   case KEY_5:
03252     sendFeedOverride(0.5);
03253     break;
03254 
03255   case KEY_6:
03256     sendFeedOverride(0.6);
03257     break;
03258 
03259   case KEY_7:
03260     sendFeedOverride(0.7);
03261     break;
03262 
03263   case KEY_8:
03264     sendFeedOverride(0.8);
03265     break;
03266 
03267   case KEY_9:
03268     sendFeedOverride(0.9);
03269     break;
03270 
03271   case KEY_0:
03272     sendFeedOverride(1.0);
03273     break;
03274 
03275   case KEY_O:
03276     dialogPopup(NULL, fileOpenShell, NULL);
03277     // trap window kill
03278     XSetWMProtocols(XtDisplay(topLevel), XtWindow(fileOpenShell), &killAtom, 1);
03279     break;
03280 
03281   case KEY_P:
03282     switch (state) {
03283     case XKEY_EVENT_STATE_NONE:
03284     case XKEY_EVENT_STATE_SHIFT:
03285       sendProgramPause();
03286       break;
03287 
03288     case XKEY_EVENT_STATE_ALT:
03289       sendLogStop();
03290       break;
03291 
03292     case XKEY_EVENT_STATE_CONTROL:
03293       plotLog(saveLogFile, saveLogType);
03294       break;
03295     }
03296     break;
03297 
03298   case KEY_V:
03299     programStartLine = -1;
03300     sendProgramRun(programStartLine);
03301     break;
03302 
03303   case KEY_A:
03304     if (emcStatus->task.mode == EMC_TASK_MODE_MANUAL) {
03305       if (numJoints <= 0)
03306         break; // joint out of range
03307       activeJoint = 0;
03308       if (jogIncrement > 0.0) {
03309         sendJogIncr(activeJoint, -jogSpeed, jogIncrement);
03310       }
03311       else {
03312         sendJogCont(activeJoint, -jogSpeed);
03313       }
03314     }
03315     else {
03316       sendProgramStep();
03317     }
03318     break;
03319 
03320   case KEY_S:
03321     if (emcStatus->task.mode == EMC_TASK_MODE_MANUAL) {
03322       if (numJoints <= 1)
03323         break; // joint out of range
03324       activeJoint = 1;
03325       if (jogIncrement > 0.0) {
03326         sendJogIncr(activeJoint, -jogSpeed, jogIncrement);
03327       }
03328       else {
03329         sendJogCont(activeJoint, -jogSpeed);
03330       }
03331     }
03332     else {
03333       switch (state) {
03334       case XKEY_EVENT_STATE_NONE:
03335       case XKEY_EVENT_STATE_SHIFT:
03336         sendProgramResume();
03337         break;
03338 
03339       case XKEY_EVENT_STATE_ALT:
03340         sendLogStart();
03341         break;
03342       }
03343     }
03344     break;
03345 
03346   case KEY_D:
03347     if (emcStatus->task.mode == EMC_TASK_MODE_MANUAL) {
03348       if (numJoints <= 2)
03349         break; // joint out of range
03350       activeJoint = 2;
03351       if (jogIncrement > 0.0) {
03352         sendJogIncr(activeJoint, -jogSpeed, jogIncrement);
03353       }
03354       else {
03355         sendJogCont(activeJoint, -jogSpeed);
03356       }
03357     }
03358     break;
03359 
03360   case KEY_F:
03361     if (emcStatus->task.mode == EMC_TASK_MODE_MANUAL) {
03362       if (numJoints <= 3)
03363         break; // joint out of range
03364       activeJoint = 3;
03365       if (jogIncrement > 0.0) {
03366         sendJogIncr(activeJoint, -jogSpeed, jogIncrement);
03367       }
03368       else {
03369         sendJogCont(activeJoint, -jogSpeed);
03370       }
03371     }
03372     else {
03373       switch (state) {
03374       case XKEY_EVENT_STATE_ALT:
03375         sendLogClose();
03376         break;
03377       }
03378     }
03379     break;
03380 
03381   case KEY_G:
03382     if (emcStatus->task.mode == EMC_TASK_MODE_MANUAL) {
03383       if (numJoints <= 4)
03384         break; // joint out of range
03385       activeJoint = 4;
03386       if (jogIncrement > 0.0) {
03387         sendJogIncr(activeJoint, -jogSpeed, jogIncrement);
03388       }
03389       else {
03390         sendJogCont(activeJoint, -jogSpeed);
03391       }
03392     }
03393     break;
03394 
03395   case KEY_H:
03396     if (emcStatus->task.mode == EMC_TASK_MODE_MANUAL) {
03397       if (numJoints <= 5)
03398         break; // joint out of range
03399       activeJoint = 5;
03400       if (jogIncrement > 0.0) {
03401         sendJogIncr(activeJoint, -jogSpeed, jogIncrement);
03402       }
03403       else {
03404         sendJogCont(activeJoint, -jogSpeed);
03405       }
03406     }
03407     break;
03408 
03409   case KEY_B:
03410     switch (state) {
03411     case XKEY_EVENT_STATE_NONE:
03412       sendBrakeRelease();
03413       break;
03414 
03415     case XKEY_EVENT_STATE_SHIFT:
03416       sendBrakeEngage();
03417       break;
03418 
03419     }
03420     break;
03421 
03422   case KEY_I:
03423     // check for entering from continuous jog, and restore saved increment
03424     if (jogIncrement <= 0.0) {
03425       jogIncrement = saveJogIncrement;
03426     }
03427     // go from 0.1000 to 0.0100
03428     else if (jogIncrement > 0.0500) {
03429       jogIncrement = 0.0100;
03430     }
03431     // go from 0.0100 to 0.0010
03432     else if (jogIncrement > 0.0050) {
03433       jogIncrement = 0.0010;
03434     }
03435     // go from 0.0010 to 0.0001
03436     else if (jogIncrement > 0.0005) {
03437       jogIncrement = 0.0001;
03438     }
03439     // go from 0.0001 to 0.1000
03440     else {
03441       jogIncrement = 0.1000;
03442     }
03443     saveJogIncrement = jogIncrement;
03444     break;
03445 
03446   case KEY_C:
03447     // change to continuous jog, but save increment for restoring
03448     jogIncrement = 0.0;
03449     break;
03450 
03451   case KEY_COMMA:
03452     // change it once here and redraw
03453     if (--jogSpeed <= 0) {
03454       jogSpeed = 1;
03455     }
03456     sprintf(string, "%d", jogSpeed);
03457     setLabel(jogSpeedLabel, string);
03458     redraw = 1;
03459 
03460     // set jogSpeedChange so that timer callback will continue to change
03461     // until button up clears it
03462     jogSpeedChange = -1;
03463     break;
03464 
03465   case KEY_PERIOD:
03466     // change it once here and redraw
03467     if (++jogSpeed > maxJogSpeed) {
03468       jogSpeed = maxJogSpeed;
03469     }
03470     sprintf(string, "%d", jogSpeed);
03471     setLabel(jogSpeedLabel, string);
03472     redraw = 1;
03473 
03474     // set jogSpeedChange so that timer callback will continue to change
03475     // until button up clears it
03476     jogSpeedChange = +1;
03477     break;
03478 
03479   default:
03480     printf("key press %d %d\n", state, keycode);
03481   }
03482 }
03483 
03484 static void keyReleaseAction(unsigned int state, unsigned int keycode)
03485 {
03486   switch (keycode) {
03487 
03488   case KEY_LEFT:
03489   case KEY_RIGHT:
03490   case KEY_UP:
03491   case KEY_DOWN:
03492   case KEY_PGUP:
03493   case KEY_PGDN:
03494   case KEY_Q:
03495   case KEY_W:
03496   case KEY_E:
03497   case KEY_R:
03498   case KEY_T:
03499   case KEY_Y:
03500   case KEY_A:
03501   case KEY_S:
03502   case KEY_D:
03503   case KEY_F:
03504   case KEY_G:
03505   case KEY_H:
03506     if (jogIncrement <= 0.0) {
03507       // only stop it if it's continuous jogging
03508       sendJogStop(axisJogging);
03509     }
03510     break;
03511 
03512   case KEY_F11:
03513   case KEY_F12:
03514     sendSpindleConstant();
03515     break;
03516 
03517   case KEY_COMMA:
03518   case KEY_PERIOD:
03519     jogSpeedChange = 0;
03520     break;
03521 
03522   default:
03523     printf("key release %d %d\n", state, keycode);
03524     break;
03525   }
03526 }
03527 
03528 static void keyAction(Widget w,
03529                       XEvent *ev,
03530                       String *params,
03531                       Cardinal *numParams)
03532 {
03533   if (ev->type == XEVENT_TYPE_XKEY_KEY_PRESS_EVENT) {
03534     keyPressKeycode = ev->xkey.keycode;
03535     keyPressState = ev->xkey.state;
03536 
03537     if (keyReleaseOut) {
03538       if (keyPressKeycode == keyReleaseKeycode &&
03539           keyPressState == keyReleaseState) {
03540         // the press matched the release before the timeout, so it's
03541         // a key repeat on this key and we won't signal a key release
03542         keyReleaseOut = 0;
03543       }
03544       else {
03545         // it's a key press on a different key than the previous release,
03546         // so allow the release to go through by leaving keyReleaseOut set
03547       }
03548     }
03549     else {
03550       keyPressAction(ev->xkey.state, ev->xkey.keycode);
03551     }
03552   }
03553   else if (ev->type == XEVENT_TYPE_XKEY_KEY_RELEASE_EVENT) {
03554     keyReleaseKeycode = ev->xkey.keycode;
03555     keyReleaseState = ev->xkey.state;
03556     keyReleaseTime = etime();
03557     keyReleaseOut = 1;
03558   }
03559 
03560   return;
03561 }
03562 
03563 static String fileMenuEntryNames[] = {
03564   "[O]    Open...",
03565   "[E]     Edit...",
03566   "[F6]   Reset",
03567   "-",
03568   "[End] Quit",
03569   NULL
03570 };
03571 
03572 static String viewMenuEntryNames[] = {
03573   "Tools...",
03574   "Offsets and Variables...",
03575   "Diagnostics...",
03576   NULL
03577 };
03578 
03579 static String settingsMenuEntryNames[] = {
03580   "[#] Relative Values",
03581   "[#] Machine Values",
03582   "-",
03583   "[@] Actual Position",
03584   "[@] Commanded Position",
03585   "-",
03586   "[$] World Frame",
03587   "[$] Joint Frame",
03588   "-",
03589   "Calibration...",
03590   "Logging...",
03591   NULL
03592 };
03593 
03594 static String helpMenuEntryNames[] = {
03595   "Help...",
03596   "-",
03597   "About...",
03598   NULL
03599 };
03600 
03601 static String stateMenuEntryNames[] = {
03602   "[F1] Estop on",
03603   "[F1] Estop off",
03604   "-",
03605   "[F2] Machine on",
03606   "[F2] Machine off",
03607   NULL
03608 };
03609 
03610 static String modeMenuEntryNames[] = {
03611   "[F3] Manual",
03612   "[F4] Auto",
03613   "[F5] MDI",
03614   NULL
03615 };
03616 
03617 static String mistMenuEntryNames[] = {
03618   "[F7] Mist on",
03619   "[F7] Mist off",
03620   NULL
03621 };
03622 
03623 static String floodMenuEntryNames[] = {
03624   "[F8] Flood on",
03625   "[F8] Flood off",
03626   NULL
03627 };
03628 
03629 static String spindleMenuEntryNames[] = {
03630   "[F9]        Spindle forward",
03631   "[F10]      Spindle reverse",
03632   "[F9/F10] Spindle off",
03633   NULL
03634 };
03635 
03636 static String brakeMenuEntryNames[] = {
03637   "[B] Brake on",
03638   "[b] Brake off",
03639   NULL
03640 };
03641 
03642 static String jogIncrementMenuEntryNames[] = {
03643   "0.0001",
03644   "0.0010",
03645   "0.0100",
03646   "0.1000",
03647   "-",
03648   "continuous",
03649   NULL
03650 };
03651 
03652 static String loggingTypeMenuEntryNames[] = {
03653   "Axis Position",
03654   "All Input Positions",
03655   "All Output Positions",
03656   "Axis Velocity",
03657   "All Following Errors",
03658   "All Trajectory Points",
03659   "All Trajectory Vels",
03660   "All Trajectory Accels",
03661   NULL
03662 };
03663 
03664 static void fileMenuSelect(Widget w, XtPointer client_data, XtPointer call_data)
03665 {
03666   switch ((int) client_data) {
03667   case 0:                       // Open...
03668     dialogPopup(NULL, fileOpenShell, NULL);
03669     // trap window kill
03670     XSetWMProtocols(XtDisplay(topLevel), XtWindow(fileOpenShell), &killAtom, 1);
03671     break;
03672 
03673   case 1:                       // Edit...
03674     dialogPopup(NULL, fileEditShell, NULL);
03675     // trap window kill
03676     XSetWMProtocols(XtDisplay(topLevel), XtWindow(fileEditShell), &killAtom, 1);
03677     break;
03678 
03679   case 2:                       // Reset
03680     sendTaskPlanInit();
03681     break;
03682 
03683     // case 3 is separator
03684 
03685   case 4:                       // Quit
03686     dialogPopup(NULL, fileQuitShell, NULL);
03687     // trap window kill
03688     XSetWMProtocols(XtDisplay(topLevel), XtWindow(fileQuitShell), &killAtom, 1);
03689     break;
03690 
03691   default:
03692     break;
03693   }
03694 }
03695 
03696 static void viewMenuSelect(Widget w, XtPointer client_data, XtPointer call_data)
03697 {
03698   char string[256];
03699 
03700   switch ((int) client_data) {
03701   case 0:                       // Tools
03702     createToolTableShell();
03703     dialogPopup(NULL, toolTableShell, NULL);
03704     // trap window kill
03705     XSetWMProtocols(XtDisplay(topLevel), XtWindow(toolTableShell), &killAtom, 1);
03706     break;
03707 
03708   case 1:                       // Variables
03709     createVarFileShell();
03710     dialogPopup(NULL, varFileShell, NULL);
03711     // trap window kill
03712     XSetWMProtocols(XtDisplay(topLevel), XtWindow(varFileShell), &killAtom, 1);
03713     break;
03714 
03715   case 2:                       // Diagnostics
03716     sprintf(string, "Axis %d Diagnostics", activeJoint);
03717     setLabel(diagnosticsLabel, string);
03718     dialogPopup(NULL, diagnosticsShell, NULL);
03719     diagnosticsIsPopped = 1;
03720     // trap window kill
03721     XSetWMProtocols(XtDisplay(topLevel), XtWindow(diagnosticsShell), &killAtom, 1);
03722     break;
03723 
03724   default:
03725     break;
03726   }
03727 }
03728 
03729 // calibration dialog
03730 
03731 static Widget calibShell = NULL;
03732 static Widget calibForm = NULL;
03733 static Widget calibLabel = NULL;
03734 static Widget calibCycleTimeLabel = NULL;
03735 static Widget calibCycleTime = NULL;
03736 static Widget calibPGainLabel = NULL;
03737 static Widget calibPGain = NULL;
03738 static Widget calibIGainLabel = NULL;
03739 static Widget calibIGain = NULL;
03740 static Widget calibDGainLabel = NULL;
03741 static Widget calibDGain = NULL;
03742 static Widget calibFF0GainLabel = NULL;
03743 static Widget calibFF0Gain = NULL;
03744 static Widget calibFF1GainLabel = NULL;
03745 static Widget calibFF1Gain = NULL;
03746 static Widget calibFF2GainLabel = NULL;
03747 static Widget calibFF2Gain = NULL;
03748 static Widget calibBacklashLabel = NULL;
03749 static Widget calibBacklash = NULL;
03750 static Widget calibBiasLabel = NULL;
03751 static Widget calibBias = NULL;
03752 static Widget calibMaxErrorLabel = NULL;
03753 static Widget calibMaxError = NULL;
03754 static Widget calibOutputScaleLabel = NULL;
03755 static Widget calibOutputScale = NULL;
03756 static Widget calibOutputOffsetLabel = NULL;
03757 static Widget calibOutputOffset = NULL;
03758 static Widget calibFerrorLabel = NULL;
03759 static Widget calibFerror = NULL;
03760 static Widget calibDone = NULL;
03761 static Widget calibCancel = NULL;
03762 
03763 static int calibReturnIsDone = 1;
03764 static Pixel calibFormBorderColor;
03765 static void calibDoDone(int done);
03766 static void calibDoneCB(Widget w, XtPointer client_data, XtPointer call_data);
03767 static void calibCancelCB(Widget w, XtPointer client_data, XtPointer call_data);
03768 static void calibReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params);
03769 static void calibTabAction(Widget w, XEvent *event, String *params, Cardinal *num_params);
03770 
03771 static void calibDoDone(int done)
03772 {
03773   int iserror = 0;
03774   String str1, str2, str3, str4, str5, str6, str7, str8, str9, str10, str11, str12, str13;
03775   double cycleTime;
03776   double p;
03777   double i;
03778   double d;
03779   double ff0;
03780   double ff1;
03781   double ff2;
03782   double bias;
03783   double backlash;
03784   double maxError;
03785   double outputScale;
03786   double outputOffset;
03787   double ferror;
03788 
03789   if (done) {
03790     // get current values for rest of gains
03791     cycleTime = emcStatus->motion.axis[activeJoint].cycleTime;
03792     p = emcStatus->motion.axis[activeJoint].p;
03793     i = emcStatus->motion.axis[activeJoint].i;
03794     d = emcStatus->motion.axis[activeJoint].d;
03795     ff0 = emcStatus->motion.axis[activeJoint].ff0;
03796     ff1 = emcStatus->motion.axis[activeJoint].ff1;
03797     ff2 = emcStatus->motion.axis[activeJoint].ff2;
03798     backlash = emcStatus->motion.axis[activeJoint].backlash;
03799     bias = emcStatus->motion.axis[activeJoint].bias;
03800     maxError = emcStatus->motion.axis[activeJoint].maxError;
03801     outputScale = emcStatus->motion.axis[activeJoint].outputScale;
03802     outputOffset = emcStatus->motion.axis[activeJoint].outputOffset;
03803 
03804     XtVaGetValues(calibCycleTime, XtNstring, &str1, NULL);
03805     XtVaGetValues(calibPGain, XtNstring, &str2, NULL);
03806     XtVaGetValues(calibIGain, XtNstring, &str3, NULL);
03807     XtVaGetValues(calibDGain, XtNstring, &str4, NULL);
03808     XtVaGetValues(calibFF0Gain, XtNstring, &str5, NULL);
03809     XtVaGetValues(calibFF1Gain, XtNstring, &str6, NULL);
03810     XtVaGetValues(calibFF2Gain, XtNstring, &str7, NULL);
03811     XtVaGetValues(calibBacklash, XtNstring, &str8, NULL);
03812     XtVaGetValues(calibBias, XtNstring, &str9, NULL);
03813     XtVaGetValues(calibMaxError, XtNstring, &str10, NULL);
03814     XtVaGetValues(calibOutputScale, XtNstring, &str11, NULL);
03815     XtVaGetValues(calibOutputOffset, XtNstring, &str12, NULL);
03816     XtVaGetValues(calibFerror, XtNstring, &str13, NULL);
03817 
03818     if (1 == sscanf(str1, "%lf", &cycleTime) &&
03819         1 == sscanf(str2, "%lf", &p) &&
03820         1 == sscanf(str3, "%lf", &i) &&
03821         1 == sscanf(str4, "%lf", &d) &&
03822         1 == sscanf(str5, "%lf", &ff0) &&
03823         1 == sscanf(str6, "%lf", &ff1) &&
03824         1 == sscanf(str7, "%lf", &ff2) &&
03825         1 == sscanf(str8, "%lf", &backlash) &&
03826         1 == sscanf(str9, "%lf", &bias) &&
03827         1 == sscanf(str10, "%lf", &maxError) &&
03828         1 == sscanf(str11, "%lf", &outputScale) &&
03829         1 == sscanf(str12, "%lf", &outputOffset) &&
03830         1 == sscanf(str13, "%lf", &ferror)) {
03831       sendAxisCycleTime(activeJoint, cycleTime);
03832       emcCommandWaitDone(emcCommandSerialNumber);
03833       sendAxisSetGains(activeJoint, p, i, d, ff0, ff1, ff2, backlash, bias, maxError);
03834       emcCommandWaitDone(emcCommandSerialNumber);
03835       sendAxisSetOutputScale(activeJoint, outputScale, outputOffset);
03836       emcCommandWaitDone(emcCommandSerialNumber);
03837       sendAxisSetFerror(activeJoint, ferror);
03838     }
03839     else {
03840       iserror = 1;
03841     }
03842   }
03843 
03844   calibReturnIsDone = 1;
03845   XtPopdown(calibShell);
03846 
03847   if (iserror) {
03848     popupError("Bad gain values");
03849   }
03850 }
03851 
03852 static void calibDoneCB(Widget w, XtPointer client_data, XtPointer call_data)
03853 {
03854   calibDoDone(1);
03855 }
03856 
03857 static void calibCancelCB(Widget w, XtPointer client_data, XtPointer call_data)
03858 {
03859   calibDoDone(0);
03860 }
03861 
03862 static void calibReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
03863 {
03864   if (calibReturnIsDone) {
03865     calibDoDone(1);
03866   }
03867   else {
03868     calibDoDone(0);
03869   }
03870 }
03871 
03872 static void calibTabAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
03873 {
03874   if (calibReturnIsDone) {
03875     setBorderColor(calibDone, calibFormBorderColor);
03876     setBorderColor(calibCancel, pixelRed);
03877     calibReturnIsDone = 0;
03878   }
03879   else {
03880     setBorderColor(calibDone, pixelRed);
03881     setBorderColor(calibCancel, calibFormBorderColor);
03882     calibReturnIsDone = 1;
03883   }
03884 }
03885 
03886 // logging dialog
03887 
03888 static Widget loggingShell = NULL;
03889 static Widget loggingForm = NULL;
03890 static Widget loggingLabel = NULL;
03891 static Widget loggingFileLabel = NULL;
03892 static Widget loggingFile = NULL;
03893 static Widget loggingTypeLabel = NULL;
03894 static Widget loggingTypeMenu = NULL;
03895 static Widget loggingSizeLabel = NULL;
03896 static Widget loggingSize = NULL;
03897 static Widget loggingSkipLabel = NULL;
03898 static Widget loggingSkip = NULL;
03899 static Widget loggingStart = NULL;
03900 static Widget loggingStop = NULL;
03901 static Widget loggingSave = NULL;
03902 static Widget loggingPlot = NULL;
03903 
03904 static Widget loggingDone = NULL;
03905 static Widget loggingCancel = NULL;
03906 
03907 static int loggingReturnIsDone = 1;
03908 static Pixel loggingFormBorderColor;
03909 static int loggingGetStrings();
03910 static void loggingDoDone(int done);
03911 static void loggingStartCB(Widget w, XtPointer client_data, XtPointer call_data);
03912 static void loggingStopCB(Widget w, XtPointer client_data, XtPointer call_data);
03913 static void loggingSaveCB(Widget w, XtPointer client_data, XtPointer call_data);
03914 static void loggingPlotCB(Widget w, XtPointer client_data, XtPointer call_data);
03915 static void loggingDoneCB(Widget w, XtPointer client_data, XtPointer call_data);
03916 static void loggingCancelCB(Widget w, XtPointer client_data, XtPointer call_data);
03917 static void loggingReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params);
03918 static void loggingTabAction(Widget w, XEvent *event, String *params, Cardinal *num_params);
03919 
03920 static int loggingGetStrings()
03921 {
03922   int iserror = 0;
03923   String str1, str2, str3;
03924 
03925   XtVaGetValues(loggingFile, XtNstring, &str1, NULL);
03926   XtVaGetValues(loggingSize, XtNstring, &str2, NULL);
03927   XtVaGetValues(loggingSkip, XtNstring, &str3, NULL);
03928 
03929   strcpy(saveLogFile, str1);
03930   if (1 == sscanf(str2, "%d", &saveLogSize) &&
03931       1 == sscanf(str3, "%d", &saveLogSkip)) {
03932     iserror = 0;
03933   }
03934   else {
03935     iserror = 1;
03936   }
03937 
03938   return iserror;
03939 }
03940 
03941 static void loggingDoDone(int done)
03942 {
03943   int retval;
03944 
03945   if (done) {
03946   retval = loggingGetStrings();
03947   }
03948 
03949   loggingReturnIsDone = 1;
03950   XtPopdown(loggingShell);
03951 
03952   if (done &&
03953       0 != retval) {
03954     popupError("Bad log values");
03955   }
03956 }
03957 
03958 static void loggingStartCB(Widget w, XtPointer client_data, XtPointer call_data)
03959 {
03960   int retval;
03961 
03962   retval = loggingGetStrings();
03963 
03964   if (0 != retval) {
03965     popupError("Bad log values");
03966   }
03967   else {
03968     sendLogStart();
03969   }
03970 }
03971 
03972 static void loggingStopCB(Widget w, XtPointer client_data, XtPointer call_data)
03973 {
03974   sendLogStop();
03975 }
03976 
03977 static void loggingSaveCB(Widget w, XtPointer client_data, XtPointer call_data)
03978 {
03979   sendLogClose();
03980 }
03981 
03982 static void loggingPlotCB(Widget w, XtPointer client_data, XtPointer call_data)
03983 {
03984   plotLog(saveLogFile, saveLogType);
03985 }
03986 
03987 static void loggingDoneCB(Widget w, XtPointer client_data, XtPointer call_data)
03988 {
03989   loggingDoDone(1);
03990 }
03991 
03992 static void loggingCancelCB(Widget w, XtPointer client_data, XtPointer call_data)
03993 {
03994   loggingDoDone(0);
03995 }
03996 
03997 static void loggingReturnAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
03998 {
03999   if (loggingReturnIsDone) {
04000     loggingDoDone(1);
04001   }
04002   else {
04003     loggingDoDone(0);
04004   }
04005 }
04006 
04007 static void loggingTabAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
04008 {
04009   if (loggingReturnIsDone) {
04010     setBorderColor(loggingDone, loggingFormBorderColor);
04011     setBorderColor(loggingCancel, pixelRed);
04012     loggingReturnIsDone = 0;
04013   }
04014   else {
04015     setBorderColor(loggingDone, pixelRed);
04016     setBorderColor(loggingCancel, loggingFormBorderColor);
04017     loggingReturnIsDone = 1;
04018   }
04019 }
04020 
04021 // menu select functions
04022 
04023 static void settingsMenuSelect(Widget w, XtPointer client_data, XtPointer call_data)
04024 {
04025   char string[256];             // FIXME-- hardcoded value
04026 
04027   switch ((int) client_data) {
04028   case 0:                       // Relative
04029     coords = COORD_RELATIVE;
04030     break;
04031 
04032   case 1:                       // Machine
04033     coords = COORD_MACHINE;
04034     break;
04035 
04036     // case 2 is separator
04037 
04038   case 3:                       // Actual
04039     posDisplay = POS_DISPLAY_ACT;
04040     break;
04041 
04042   case 4:                       // Commanded
04043     posDisplay = POS_DISPLAY_CMD;
04044     break;
04045 
04046     // case 5 is separator
04047 
04048   case 6:                       // World
04049     posFrame = POS_FRAME_WORLD;
04050     break;
04051 
04052   case 7:                       // Joint
04053     posFrame = POS_FRAME_JOINT;
04054     break;
04055 
04056     // case 8 is separator
04057 
04058   case 9:                       // Calibration...
04059 
04060     sprintf(string, "Axis %d Calibration", activeJoint);
04061     XtVaSetValues(calibLabel, XtNlabel, string, NULL);
04062 
04063     sprintf(string, "%f", emcStatus->motion.axis[activeJoint].cycleTime);
04064     XtVaSetValues(calibCycleTime, XtNstring, string, NULL);
04065 
04066     sprintf(string, "%f", emcStatus->motion.axis[activeJoint].p);
04067     XtVaSetValues(calibPGain, XtNstring, string, NULL);
04068     sprintf(string, "%f", emcStatus->motion.axis[activeJoint].i);
04069     XtVaSetValues(calibIGain, XtNstring, string, NULL);
04070     sprintf(string, "%f", emcStatus->motion.axis[activeJoint].d);
04071     XtVaSetValues(calibDGain, XtNstring, string, NULL);
04072 
04073     sprintf(string, "%f", emcStatus->motion.axis[activeJoint].ff0);
04074     XtVaSetValues(calibFF0Gain, XtNstring, string, NULL);
04075     sprintf(string, "%f", emcStatus->motion.axis[activeJoint].ff1);
04076     XtVaSetValues(calibFF1Gain, XtNstring, string, NULL);
04077     sprintf(string, "%f", emcStatus->motion.axis[activeJoint].ff2);
04078     XtVaSetValues(calibFF2Gain, XtNstring, string, NULL);
04079 
04080     sprintf(string, "%f", emcStatus->motion.axis[activeJoint].backlash);
04081     XtVaSetValues(calibBacklash, XtNstring, string, NULL);
04082     sprintf(string, "%f", emcStatus->motion.axis[activeJoint].bias);
04083     XtVaSetValues(calibBias, XtNstring, string, NULL);
04084     sprintf(string, "%f", emcStatus->motion.axis[activeJoint].maxError);
04085     XtVaSetValues(calibMaxError, XtNstring, string, NULL);
04086 
04087     sprintf(string, "%f", emcStatus->motion.axis[activeJoint].outputScale);
04088     XtVaSetValues(calibOutputScale, XtNstring, string, NULL);
04089     sprintf(string, "%f", emcStatus->motion.axis[activeJoint].outputOffset);
04090     XtVaSetValues(calibOutputOffset, XtNstring, string, NULL);
04091 
04092     sprintf(string, "%f", emcStatus->motion.axis[activeJoint].maxFerror);
04093     XtVaSetValues(calibFerror, XtNstring, string, NULL);
04094 
04095     dialogPopup(NULL, calibShell, NULL);
04096     // trap window kill
04097     XSetWMProtocols(XtDisplay(topLevel), XtWindow(calibShell), &killAtom, 1);
04098     break;
04099 
04100   case 10:                      // Logging...
04101     XtVaSetValues(loggingFile, XtNstring, saveLogFile, NULL);
04102     sprintf(string,
04103             saveLogType == EMC_LOG_TYPE_AXIS_POS ?    "Axis Position" :
04104             saveLogType == EMC_LOG_TYPE_AXES_INPOS ?  "All Input Positions" :
04105             saveLogType == EMC_LOG_TYPE_AXES_OUTPOS ? "All Output Positions" :
04106             saveLogType == EMC_LOG_TYPE_AXIS_VEL ?    "Axis Velocity" :
04107             saveLogType == EMC_LOG_TYPE_AXES_FERROR ? "All Following Errors" :
04108             saveLogType == EMC_LOG_TYPE_TRAJ_POS ? "All Trajectory Points" :
04109             saveLogType == EMC_LOG_TYPE_TRAJ_VEL ? "All Trajectory Vels" :
04110             saveLogType == EMC_LOG_TYPE_TRAJ_ACC ? "All Trajectory Accels" :
04111             "(unknown)");
04112     XtVaSetValues(loggingTypeMenu, XtNlabel, string, NULL);
04113     sprintf(string, "%d", saveLogSize);
04114     XtVaSetValues(loggingSize, XtNstring, string, NULL);
04115     sprintf(string, "%d", saveLogSkip);
04116     XtVaSetValues(loggingSkip, XtNstring, string, NULL);
04117 
04118     dialogPopup(NULL, loggingShell, NULL);
04119     // trap window kill
04120     XSetWMProtocols(XtDisplay(topLevel), XtWindow(loggingShell), &killAtom, 1);
04121     break;
04122 
04123   default:
04124     break;
04125   }
04126 }
04127 
04128 static void helpMenuSelect(Widget w, XtPointer client_data, XtPointer call_data)
04129 {
04130   switch ((int) client_data) {
04131   case 0:                       // Help...
04132     dialogPopup(w, helpXemcShell, NULL);
04133     // trap window kill
04134     XSetWMProtocols(XtDisplay(topLevel), XtWindow(helpXemcShell), &killAtom, 1);
04135     break;
04136 
04137     // case 1 is separator
04138 
04139   case 2:                       // About...
04140     dialogPopup(NULL, helpAboutShell, NULL);
04141     XSetWMProtocols(XtDisplay(topLevel), XtWindow(helpAboutShell), &killAtom, 1);
04142     break;
04143 
04144   default:
04145     break;
04146   }
04147 }
04148 
04149 static void stateMenuSelect(Widget w, XtPointer client_data, XtPointer call_data)
04150 {
04151   switch ((int) client_data) {
04152   case 0:
04153     sendEstop();
04154     break;
04155 
04156   case 1:
04157     sendEstopReset();
04158     break;
04159 
04160     // case 2 is separator
04161 
04162   case 3:
04163     sendMachineOn();
04164     break;
04165 
04166   case 4:
04167     sendMachineOff();
04168     break;
04169 
04170   default:
04171     break;
04172   }
04173 }
04174 
04175 static void modeMenuSelect(Widget w, XtPointer client_data, XtPointer call_data)
04176 {
04177   switch ((int) client_data) {
04178   case 0:
04179     sendManual();
04180     break;
04181 
04182   case 1:
04183     sendAuto();
04184     break;
04185 
04186   case 2:
04187     sendMdi();
04188     break;
04189 
04190   default:
04191     break;
04192   }
04193 }
04194 
04195 static void mistMenuSelect(Widget w, XtPointer client_data, XtPointer call_data)
04196 {
04197   switch ((int) client_data) {
04198   case 0:
04199     sendMistOn();
04200     break;
04201 
04202   case 1:
04203     sendMistOff();
04204     break;
04205 
04206   default:
04207     break;
04208   }
04209 }
04210 
04211 static void floodMenuSelect(Widget w, XtPointer client_data, XtPointer call_data)
04212 {
04213   switch ((int) client_data) {
04214   case 0:
04215     sendFloodOn();
04216     break;
04217 
04218   case 1:
04219     sendFloodOff();
04220     break;
04221 
04222   default:
04223     break;
04224   }
04225 }
04226 
04227 static void spindleMenuSelect(Widget w, XtPointer client_data, XtPointer call_data)
04228 {
04229   switch ((int) client_data) {
04230   case 0:
04231     sendSpindleForward();
04232     break;
04233 
04234   case 1:
04235     sendSpindleReverse();
04236     break;
04237 
04238   case 2:
04239     sendSpindleOff();
04240     break;
04241 
04242   default:
04243     break;
04244   }
04245 }
04246 
04247 static void brakeMenuSelect(Widget w, XtPointer client_data, XtPointer call_data)
04248 {
04249   switch ((int) client_data) {
04250   case 0:
04251     sendBrakeEngage();
04252     break;
04253 
04254   case 1:
04255     sendBrakeRelease();
04256     break;
04257 
04258   default:
04259     break;
04260   }
04261 }
04262 
04263 static void jogIncrementMenuSelect(Widget w, XtPointer client_data, XtPointer call_data)
04264 {
04265   switch ((int) client_data) {
04266   case 0:
04267     jogIncrement = 0.0001;
04268     break;
04269 
04270   case 1:
04271     jogIncrement = 0.0010;
04272     break;
04273 
04274   case 2:
04275     jogIncrement = 0.0100;
04276     break;
04277 
04278   case 3:
04279     jogIncrement = 0.1000;
04280     break;
04281 
04282     // case 4 is separator
04283 
04284   case 5:
04285     jogIncrement = -1.0;
04286     break;
04287 
04288   default:
04289     break;
04290   }
04291 }
04292 
04293 static void loggingTypeMenuSelect(Widget w, XtPointer client_data, XtPointer call_data)
04294 {
04295   char string[256];
04296 
04297   switch ((int) client_data) {
04298   case 0:
04299     saveLogType = EMC_LOG_TYPE_AXIS_POS;
04300     break;
04301 
04302   case 1:
04303     saveLogType = EMC_LOG_TYPE_AXES_INPOS;
04304     break;
04305 
04306   case 2:
04307     saveLogType = EMC_LOG_TYPE_AXES_OUTPOS;
04308     break;
04309 
04310   case 3:
04311     saveLogType = EMC_LOG_TYPE_AXIS_VEL;
04312     break;
04313 
04314   case 4:
04315     saveLogType = EMC_LOG_TYPE_AXES_FERROR;
04316     break;
04317 
04318   case 5:
04319     saveLogType = EMC_LOG_TYPE_TRAJ_POS;
04320     break;
04321 
04322   case 6:
04323     saveLogType = EMC_LOG_TYPE_TRAJ_VEL;
04324     break;
04325 
04326   case 7:
04327     saveLogType = EMC_LOG_TYPE_TRAJ_ACC;
04328     break;
04329 
04330   default:
04331     break;
04332   }
04333 
04334   sprintf(string,
04335           saveLogType == EMC_LOG_TYPE_AXIS_POS ?    "Axis Position" :
04336           saveLogType == EMC_LOG_TYPE_AXES_INPOS ?  "All Input Positions" :
04337           saveLogType == EMC_LOG_TYPE_AXES_OUTPOS ? "All Output Positions" :
04338           saveLogType == EMC_LOG_TYPE_AXIS_VEL ?    "Axis Velocity" :
04339           saveLogType == EMC_LOG_TYPE_AXES_FERROR ? "All Following Errors" :
04340           saveLogType == EMC_LOG_TYPE_TRAJ_POS ? "All Trajectory Points" :
04341           saveLogType == EMC_LOG_TYPE_TRAJ_VEL ? "All Trajectory Vels" :
04342           saveLogType == EMC_LOG_TYPE_TRAJ_ACC ? "All Trajectory Accels" :
04343           "(unknown)");
04344   XtVaSetValues(loggingTypeMenu, XtNlabel, string, NULL);
04345 }
04346 
04347 // menu dimming
04348 
04349 static void enableAuxMenus(Boolean torf)
04350 {
04351   static Boolean auxMenusEnabled = True;
04352 
04353   if (auxMenusEnabled != torf) {
04354     XtSetSensitive(mistMenu, torf);
04355     XtSetSensitive(floodMenu, torf);
04356     XtSetSensitive(spindleMenu, torf);
04357     XtSetSensitive(brakeMenu, torf);
04358     auxMenusEnabled = torf;
04359   }
04360 }
04361 
04362 static void enableManualMenus(Boolean torf)
04363 {
04364   static Boolean manualMenusEnabled = True;
04365 
04366   if (manualMenusEnabled != torf) {
04367     XtSetSensitive(jogMinusLabel, torf);
04368     XtSetSensitive(homeCommand, torf);
04369     XtSetSensitive(jogPlusLabel, torf);
04370     XtSetSensitive(programPauseCommand, torf);
04371     XtSetSensitive(programResumeCommand, torf);
04372     manualMenusEnabled = torf;
04373   }
04374 }
04375 
04376 static void enableAutoMenus(Boolean torf)
04377 {
04378   static Boolean autoMenusEnabled = True;
04379 
04380   if (autoMenusEnabled != torf) {
04381     XtSetSensitive(programOpenCommand, torf);
04382     XtSetSensitive(programRunCommand, torf);
04383     XtSetSensitive(programPauseCommand, torf);
04384     XtSetSensitive(programResumeCommand, torf);
04385     XtSetSensitive(programStepCommand, torf);
04386     XtSetSensitive(programVerifyCommand, torf);
04387     autoMenusEnabled = torf;
04388   }
04389 }
04390 
04391 static void enableMdiMenus(Boolean torf)
04392 {
04393   static Boolean mdiMenusEnabled = True;
04394 
04395   if (mdiMenusEnabled != torf) {
04396     //FIXME    XtSetSensitive(mdiFormText, torf);
04397     XtSetSensitive(programPauseCommand, torf);
04398     XtSetSensitive(programResumeCommand, torf);
04399     mdiMenusEnabled = torf;
04400   }
04401 
04402   if (torf) {
04403     /* set focus to mdi window */
04404     XtSetKeyboardFocus(topForm, mdiFormText);
04405   }
04406   else {
04407     XtSetKeyboardFocus(topForm, None);
04408   }
04409 }
04410 
04411 // saved old values, used to determine if redraw is necessary.
04412 // Make them invalid so that everything is updated at startup, or
04413 // at least make them the same as the initial labels.
04414 static unsigned long int oldTaskHeartbeat =0;
04415 static unsigned long int oldIoHeartbeat =0;
04416 static unsigned long int oldMotionHeartbeat =0;
04417 static double oldAxisFerror[XEMC_NUM_AXES]; // inited to invalid in main()
04418 static int oldState = -1;
04419 static int oldMode = -1;
04420 static int oldMist = -1;
04421 static int oldFlood = -1;
04422 static int oldSpindleIncreasing = -1;
04423 static int oldSpindleDirection = -2;
04424 static int oldBrake = -1;
04425 static int oldTool = -1;
04426 static double oldToolOffset = DBL_MAX; // invalid val forces first print
04427 static EmcPose oldOrigin ={ { DBL_MAX, DBL_MAX, DBL_MAX }, 
04428                          DBL_MAX, DBL_MAX, DBL_MAX };
04429 static double newPosLabelValue[XEMC_NUM_AXES]; // inited to 0 in main
04430 static double oldPosLabelValue[XEMC_NUM_AXES]; // inited to DBL_MAX in main()
04431 static char posLabelWorld[XEMC_NUM_AXES] = {'X', 'Y', 'Z', 'R', 'P', 'W'};
04432 static char posLabelJoint[XEMC_NUM_AXES] = {'1', '2', '3', '4', '5', '6'};
04433 static int oldCoords = 0; // invalid val forces first print
04434 static int oldPosDisplay = 0; // ditto
04435 static int oldPosFrame = 0; // ditto
04436 static double oldJogIncrement = -1.0; // invalid val forces first print
04437 static Pixel posColor[XEMC_NUM_AXES]; // inited to invalid in main()
04438 static int oldLogOpen = -1;
04439 static int oldLogStarted = -1;
04440 static int oldLogPoints = -1;
04441 static char oldMdiCodes[256] = ""; // FIXME-- harcoded
04442 static int oldProgramActiveLine = -1;
04443 static char oldProgramString[256] = "";
04444 
04445 /*
04446   mapPoseToLabels(EmcPose pose) takes the pose and sets the global floating
04447   point newPosLabelValue[] as a side effect. newPosLabelValue[] will be
04448   compared with the old one to inhibit redraws of the same value.
04449 */
04450 static void mapPoseToLabels(EmcPose pose)
04451 {
04452   int m;
04453   int p;
04454 
04455 
04456   // run through all 6 possible markers, pick out when there's a 1 and put
04457   // appropriate coordinate value in next posLabel slot
04458   for (m = 0, p = 0; m < 6; m++) {
04459     if (coordinateMark[m]) {
04460       if (m == 0)
04461         newPosLabelValue[p] = pose.tran.x;
04462       else if (m == 1)
04463         newPosLabelValue[p] = pose.tran.y;
04464       else if (m == 2)
04465         newPosLabelValue[p] = pose.tran.z;
04466       else if (m == 3)
04467         newPosLabelValue[p] = pose.a;
04468       else if (m == 4)
04469         newPosLabelValue[p] = pose.b;
04470       else if (m == 5)
04471         newPosLabelValue[p] = pose.c;
04472       p++;
04473     }
04474   }
04475 }
04476 
04477 void timeoutCB(XtPointer clientdata, XtIntervalId *id)
04478 {
04479   double now;
04480   char string[256];             // FIXME-- hardcoded
04481   int t;
04482   unsigned char changedPosDisplayType = 0;
04483   unsigned char changedCoordType = 0;
04484   unsigned char changedPosFrameType = 0;
04485   int code;
04486   int programActiveLine;
04487   int programTopLine;
04488   char mdiCodes[256];           // FIXME-- hardcoded
04489   int axis;
04490   EmcPose offsetPose;
04491 
04492   // set the time
04493   now = etime();
04494 
04495   // read the EMC status
04496   if (0 != updateStatus()) {
04497     sprintf(error_string, "bad status");
04498   }
04499 
04500   // read the EMC errors
04501   if (0 != updateError()) {
04502     sprintf(error_string, "bad status");
04503   }
04504 
04505   // print any result stored by updateError() in error_string
04506   if (error_string[0] != 0) {
04507     popupError(error_string);
04508     error_string[0] = 0;
04509   }
04510 
04511   // handle key up events
04512   if (keyReleaseOut &&
04513       now - keyReleaseTime > 0.100) {
04514     // key up event has occurred
04515     keyReleaseOut = 0;
04516     keyReleaseAction(keyReleaseState, keyReleaseKeycode);
04517   }
04518 
04519   // handle button press repeats
04520 
04521   if (jogSpeedChange < 0) {
04522     if (--jogSpeed <= 0) {
04523       jogSpeed = 1;
04524     }
04525     sprintf(string, "%d", jogSpeed);
04526     setLabel(jogSpeedLabel, string);
04527     redraw = 1;
04528   }
04529   else if (jogSpeedChange > 0) {
04530     if (++jogSpeed > maxJogSpeed) {
04531       jogSpeed = maxJogSpeed;
04532     }
04533     sprintf(string, "%d", jogSpeed);
04534     setLabel(jogSpeedLabel, string);
04535     redraw = 1;
04536   }
04537 
04538   if (feedOverrideChange < 0) {
04539     if (--feedOverrideDelayCount < 0) {
04540       if ((feedOverride -= 10) < 0) {
04541         feedOverride = 0;
04542       }
04543       sprintf(string, "%3d", feedOverride);
04544       setLabel(feedOverrideLabel, string);
04545       feedOverrideDelayCount = FEED_OVERRIDE_DELAY_COUNT;
04546 
04547       redraw = 1;
04548     }
04549   }
04550   else if (feedOverrideChange > 0) {
04551     if (--feedOverrideDelayCount < 0) {
04552       if ((feedOverride += 10) > maxFeedOverride) {
04553         feedOverride = maxFeedOverride;
04554       }
04555       sprintf(string, "%3d", feedOverride);
04556       setLabel(feedOverrideLabel, string);
04557       feedOverrideDelayCount = FEED_OVERRIDE_DELAY_COUNT;
04558       redraw = 1;
04559     }
04560   }
04561   else {
04562     // we're not changing it, so update it from EMC value
04563     feedOverride = (int) (emcStatus->motion.traj.scale * 100.0 + 0.5);
04564     if (feedOverride != oldFeedOverride) {
04565       oldFeedOverride = feedOverride;
04566       sprintf(string, "%3d", feedOverride);
04567       setLabel(feedOverrideLabel, string);
04568       redraw = 1;
04569     }
04570   }
04571 
04572   // handle internal status changes
04573 
04574   // flag changes in display types
04575   if (posDisplay != oldPosDisplay) {
04576     changedPosDisplayType = 1;
04577     oldPosDisplay = posDisplay;
04578   }
04579   if (coords != oldCoords) {
04580     changedCoordType = 1;
04581     oldCoords = coords;
04582   }
04583   if (posFrame != oldPosFrame) {
04584     changedPosFrameType = 1;
04585     oldPosFrame = posFrame;
04586   }
04587 
04588   if (posFrame == POS_FRAME_JOINT) {
04589     if (activeJoint != oldActiveJoint ||
04590         changedPosFrameType) {
04591       /* first clear the border for them all */
04592       for (axis = 0; axis < numPosLabels; axis++) {
04593         setBorderColor(posLabel[axis], posLabelBackground[axis]);
04594       }
04595       /* now set the border for the selected one */
04596       setBorderColor(posLabel[activeJoint], posLabelBorderColor[activeJoint]);
04597       redraw = 1;
04598 
04599       oldActiveJoint = activeJoint;
04600     }
04601   }
04602   else {
04603     if (activeCoord != oldActiveCoord ||
04604         changedPosFrameType) {
04605       /* first clear the border for them all */
04606       for (axis = 0; axis < numPosLabels; axis++) {
04607         setBorderColor(posLabel[axis], posLabelBackground[axis]);
04608       }
04609       /* now set the border for the selected one */
04610       setBorderColor(posLabel[activeCoord], posLabelBorderColor[activeCoord]);
04611       redraw = 1;
04612 
04613       oldActiveCoord = activeCoord;
04614     }
04615   }
04616 
04617   if (jogIncrement != oldJogIncrement) {
04618     if (jogIncrement > 0.0) {
04619       sprintf(string, "%1.4f", jogIncrement);
04620     }
04621     else {
04622       sprintf(string, "continuous");
04623     }
04624     setLabel(jogIncrementMenu, string);
04625     redraw = 1;
04626 
04627     oldJogIncrement = jogIncrement;
04628   }
04629 
04630   // handle EMC status changes
04631   /*
04632     Note that changing the label changes the size of the label,
04633     but not the size of the enclosing box. So, the initial label
04634     width will set the size of the enclosing box, but won't have
04635     any other effect during the life of the label. For this reason
04636     label widths for dynamically labeled labels are not specified,
04637     and they are set manually before the labels are realized to a
04638     blank string the same width of the labels. If you use proportional
04639     fonts for the labels, they will change in size.
04640   */
04641 
04642   if (diagnosticsIsPopped) {
04643     if (emcStatus->task.heartbeat != oldTaskHeartbeat) {
04644       sprintf(string, "%ld %ld %d %d %d",
04645               emcStatus->task.heartbeat,
04646               emcStatus->task.command_type,
04647               emcStatus->task.echo_serial_number,
04648               emcStatus->task.status,
04649               emcStatus->task.execState);
04650       setLabel(diagnosticsTaskHB, string);
04651       redraw = 1;
04652 
04653       oldTaskHeartbeat = emcStatus->task.heartbeat;
04654     }
04655 
04656     if (emcStatus->io.heartbeat != oldIoHeartbeat) {
04657       sprintf(string, "%ld %ld %d %d",
04658               emcStatus->io.heartbeat,
04659               emcStatus->io.command_type,
04660               emcStatus->io.echo_serial_number,
04661               emcStatus->io.status);
04662       setLabel(diagnosticsIoHB, string);
04663       redraw = 1;
04664 
04665       oldIoHeartbeat = emcStatus->io.heartbeat;
04666     }
04667 
04668     if (emcStatus->motion.heartbeat != oldMotionHeartbeat) {
04669       sprintf(string, "%ld %ld %d %d",
04670               emcStatus->motion.heartbeat,
04671               emcStatus->motion.command_type,
04672               emcStatus->motion.echo_serial_number,
04673               emcStatus->motion.status);
04674       setLabel(diagnosticsMotionHB, string);
04675       redraw = 1;
04676 
04677       oldMotionHeartbeat = emcStatus->motion.heartbeat;
04678     }
04679 
04680     if (emcStatus->motion.axis[activeJoint].ferrorHighMark !=
04681         oldAxisFerror[activeJoint]) {
04682       sprintf(string, "%.3f", emcStatus->motion.axis[activeJoint].ferrorHighMark);
04683       setLabel(diagnosticsFerror, string);
04684       redraw = 1;
04685 
04686       oldAxisFerror[activeJoint] = emcStatus->motion.axis[activeJoint].ferrorHighMark;
04687     }
04688   }
04689 
04690   if (emcStatus->task.state != oldState) {
04691     switch(emcStatus->task.state) {
04692     case EMC_TASK_STATE_OFF:
04693       sprintf(string, "OFF");
04694       break;
04695     case EMC_TASK_STATE_ON:
04696       sprintf(string, "ON");
04697       break;
04698     case EMC_TASK_STATE_ESTOP:
04699       sprintf(string, "ESTOP");
04700       break;
04701     case EMC_TASK_STATE_ESTOP_RESET:
04702       sprintf(string, "ESTOP RESET");
04703       break;
04704     default:
04705       sprintf(string, "?");
04706       break;
04707     }
04708 
04709     setLabel(stateMenu, string);
04710     redraw = 1;
04711 
04712     oldState = emcStatus->task.state;
04713   }
04714 
04715   if (emcStatus->task.mode != oldMode) {
04716     switch(emcStatus->task.mode) {
04717     case EMC_TASK_MODE_MANUAL:
04718       sprintf(string, "MANUAL");
04719       break;
04720     case EMC_TASK_MODE_AUTO:
04721       sprintf(string, "AUTO");
04722       break;
04723     case EMC_TASK_MODE_MDI:
04724       sprintf(string, "MDI");
04725       break;
04726     default:
04727       sprintf(string, "?");
04728       break;
04729     }
04730 
04731     setLabel(modeMenu, string);
04732     redraw = 1;
04733 
04734     oldMode = emcStatus->task.mode;
04735   }
04736 
04737   if (emcStatus->io.coolant.mist != oldMist) {
04738     if (emcStatus->io.coolant.mist) {
04739       sprintf(string, "MIST ON");
04740     }
04741     else {
04742       sprintf(string, "MIST OFF");
04743     }
04744 
04745     setLabel(mistMenu, string);
04746     redraw = 1;
04747 
04748     oldMist = emcStatus->io.coolant.mist;
04749   }
04750 
04751   if (emcStatus->io.coolant.flood != oldFlood) {
04752     if (emcStatus->io.coolant.flood) {
04753       sprintf(string, "FLOOD ON");
04754     }
04755     else {
04756       sprintf(string, "FLOOD OFF");
04757     }
04758 
04759     setLabel(floodMenu, string);
04760     redraw = 1;
04761 
04762     oldFlood = emcStatus->io.coolant.flood;
04763   }
04764 
04765   if (emcStatus->io.spindle.increasing != oldSpindleIncreasing) {
04766     if (emcStatus->io.spindle.increasing > 0) {
04767       sprintf(string, "SPINDLE INC");
04768     }
04769     else if (emcStatus->io.spindle.increasing < 0) {
04770       sprintf(string, "SPINDLE DEC");
04771     }
04772     else {
04773       // spindle constant-- flag invalid oldSpindleDirection
04774       // so code below will pick up a redraw
04775       oldSpindleDirection = -2;
04776     }
04777 
04778     setLabel(spindleMenu, string);
04779     redraw = 1;
04780 
04781     oldSpindleIncreasing = emcStatus->io.spindle.increasing;
04782   }
04783 
04784   if (emcStatus->io.spindle.direction != oldSpindleDirection) {
04785     if (emcStatus->io.spindle.direction > 0) {
04786       sprintf(string, "SPINDLE FWD");
04787       XtSetSensitive(spindleDecLabel, True);
04788       XtSetSensitive(spindleIncLabel, True);
04789     }
04790     else if (emcStatus->io.spindle.direction < 0) {
04791       sprintf(string, "SPINDLE REV");
04792       XtSetSensitive(spindleDecLabel, True);
04793       XtSetSensitive(spindleIncLabel, True);
04794     }
04795     else {
04796       sprintf(string, "SPINDLE OFF");
04797       XtSetSensitive(spindleDecLabel, False);
04798       XtSetSensitive(spindleIncLabel, False);
04799     }
04800 
04801     setLabel(spindleMenu, string);
04802     redraw = 1;
04803 
04804     oldSpindleDirection = emcStatus->io.spindle.direction;
04805   }
04806 
04807   if (emcStatus->io.spindle.brake != oldBrake) {
04808     if (emcStatus->io.spindle.brake) {
04809       sprintf(string, "BRAKE ON");
04810     }
04811     else {
04812       sprintf(string, "BRAKE OFF");
04813     }
04814 
04815     setLabel(brakeMenu, string);
04816     redraw = 1;
04817 
04818     oldBrake = emcStatus->io.spindle.brake;
04819   }
04820 
04821   if (emcStatus->io.tool.toolInSpindle != oldTool) {
04822     sprintf(string, "%d", emcStatus->io.tool.toolInSpindle);
04823     setLabel(toolNumberFormName, string);
04824 
04825     redraw = 1;
04826 
04827     oldTool = emcStatus->io.tool.toolInSpindle;
04828   }
04829 
04830   if (emcStatus->task.toolOffset.tran.z != oldToolOffset) {
04831     sprintf(string, "%.4f", emcStatus->task.toolOffset.tran.z);
04832     setLabel(toolOffsetFormName, string);
04833 
04834     redraw = 1;
04835 
04836     oldToolOffset = emcStatus->task.toolOffset.tran.z;
04837   }
04838 
04839   // redraw label for types of position displayed, if any have changed
04840   if (changedPosDisplayType ||
04841       changedCoordType ||
04842       changedPosFrameType) {
04843     sprintf(string, "%s %s %s",
04844             (posDisplay == POS_DISPLAY_CMD) ? "Commanded" : "Actual",
04845             (coords == COORD_MACHINE) ? "Machine" : "Relative",
04846             (posFrame == POS_FRAME_WORLD) ? "World" : "Joint");
04847     setLabel(positionTypeFormName, string);
04848     redraw = 1;
04849   }
04850 
04851   // check if we changed between machine and relative coords. If so,
04852   // redraw the work offset string.
04853   if (changedCoordType) {
04854     if (coords == COORD_MACHINE) {
04855     // switched to machine display, so blank out offsets
04856       string[0] = 0;
04857       setLabel(workOffsetFormName, string);
04858       redraw = 1;
04859     }
04860     else {
04861       // switched to relative display, so redisplay offsets
04862       sprintf(string, "X%.4f  Y%.4f  Z%.4f",
04863               emcStatus->task.origin.tran.x,
04864               emcStatus->task.origin.tran.y,
04865               emcStatus->task.origin.tran.z);
04866       setLabel(workOffsetFormName, string);
04867       redraw = 1;
04868     }
04869   }
04870 
04871   // check if controller offset changed
04872   if (emcStatus->task.origin.tran.x != oldOrigin.tran.x || 
04873       emcStatus->task.origin.tran.y != oldOrigin.tran.y || 
04874       emcStatus->task.origin.tran.z != oldOrigin.tran.z || 
04875       emcStatus->task.origin.a != oldOrigin.a || 
04876       emcStatus->task.origin.b != oldOrigin.b || 
04877       emcStatus->task.origin.c != oldOrigin.c
04878       ) {
04879     if (coords == COORD_MACHINE) {
04880       // display offsets changed, but we're not displaying them
04881     }
04882     else {
04883       // display offsets changed and we are displaying them
04884       // FIXME-- tran only
04885       sprintf(string, "X%.4f  Y%.4f  Z%.4f",
04886               emcStatus->task.origin.tran.x,
04887               emcStatus->task.origin.tran.y,
04888               emcStatus->task.origin.tran.z);
04889       setLabel(workOffsetFormName, string);
04890       redraw = 1;
04891 
04892       oldOrigin = emcStatus->task.origin;
04893     }
04894   }
04895 
04896   // compute new posLabel[] numbers
04897   if (posFrame == POS_FRAME_WORLD) {
04898     if (coords == COORD_MACHINE) {
04899       if (posDisplay == POS_DISPLAY_ACT) {
04900         mapPoseToLabels(emcStatus->motion.traj.actualPosition);
04901       }
04902       else {
04903         mapPoseToLabels(emcStatus->motion.traj.position);
04904       }
04905     }
04906     else {
04907       // COORD_RELATIVE-- need to subtract off offsets
04908       // FIXME-- this just does the tran portion, no support
04909       // for quaternion offsets yet
04910       if (posDisplay == POS_DISPLAY_ACT) {
04911         offsetPose.tran.x = emcStatus->motion.traj.actualPosition.tran.x -
04912           emcStatus->task.origin.tran.x;
04913         offsetPose.tran.y = emcStatus->motion.traj.actualPosition.tran.y -
04914           emcStatus->task.origin.tran.y;
04915         offsetPose.tran.z = emcStatus->motion.traj.actualPosition.tran.z -
04916           emcStatus->task.origin.tran.z -
04917           emcStatus->task.toolOffset.tran.z;
04918         offsetPose.a = emcStatus->motion.traj.actualPosition.a -
04919           emcStatus->task.origin.a;
04920         offsetPose.b = emcStatus->motion.traj.actualPosition.b -
04921           emcStatus->task.origin.b;
04922         offsetPose.c = emcStatus->motion.traj.actualPosition.c -
04923           emcStatus->task.origin.c;
04924         mapPoseToLabels(offsetPose);
04925       }
04926       else {
04927         offsetPose.tran.x = emcStatus->motion.traj.position.tran.x -
04928           emcStatus->task.origin.tran.x;
04929         offsetPose.tran.y = emcStatus->motion.traj.position.tran.y -
04930           emcStatus->task.origin.tran.y;
04931         offsetPose.tran.z = emcStatus->motion.traj.position.tran.z -
04932           emcStatus->task.origin.tran.z -
04933           emcStatus->task.toolOffset.tran.z;
04934         offsetPose.a = emcStatus->motion.traj.position.a -
04935           emcStatus->task.origin.a;
04936         offsetPose.b = emcStatus->motion.traj.position.b -
04937           emcStatus->task.origin.b;
04938         offsetPose.c = emcStatus->motion.traj.position.c -
04939           emcStatus->task.origin.c;
04940         mapPoseToLabels(offsetPose);
04941       }
04942     }
04943   }
04944   else {
04945     // joint coordinates
04946     if (posDisplay == POS_DISPLAY_ACT) {
04947       // actual joints
04948       for (t = 0; t < numJoints; t++) {
04949         newPosLabelValue[t] = emcStatus->motion.axis[t].input;
04950       }
04951     }
04952     else {
04953       // commanded joints
04954       for (t = 0; t < numJoints; t++) {
04955         newPosLabelValue[t] = emcStatus->motion.axis[t].setpoint;
04956       }
04957     }
04958   }
04959 
04960   for (t = 0; t < numPosLabels; t++) {
04961     if (newPosLabelValue[t] != oldPosLabelValue[t] ||
04962         changedPosFrameType) {
04963       if (posFrame == POS_FRAME_WORLD) {
04964         // use posLabelWorld[] array of {'X', 'Y'} etc.
04965         // and blank out unused coords
04966         if (t < numCoords) {
04967           sprintf(string, "%c %9.4f", posLabelWorld[t], newPosLabelValue[t]);
04968         }
04969         else {
04970           string[0] = 0;
04971         }
04972       }
04973       else {
04974         // use joint numbering from posLabelJoint[] array of {'1', '2'} etc.
04975         // and blank out unused axes
04976         if (t < numJoints) {
04977           sprintf(string, "%c %9.4f", posLabelJoint[t], newPosLabelValue[t]);
04978         }
04979         else {
04980           string[0] = 0;
04981         }
04982       }
04983       setLabel(posLabel[t], string);
04984       redraw = 1;
04985 
04986       oldPosLabelValue[t] = newPosLabelValue[t];
04987     }
04988   }
04989 
04990   // fill in the logging status
04991   if (oldLogOpen != emcStatus->logOpen) {
04992     strcpy(string, emcStatus->logOpen ? "Open" : "Closed");
04993     setLabel(loggingStatusOpenLabel, string);
04994     redraw = 1;
04995 
04996     oldLogOpen = emcStatus->logOpen;
04997   }
04998 
04999   if (oldLogStarted != emcStatus->logStarted) {
05000     strcpy(string, emcStatus->logStarted ? "Logging" : "Not Logging");
05001     setLabel(loggingStatusStartedLabel, string);
05002     redraw = 1;
05003 
05004     oldLogStarted = emcStatus->logStarted;
05005   }
05006 
05007   if (oldLogPoints != emcStatus->logPoints) {
05008     sprintf(string, "%d", emcStatus->logPoints);
05009     setLabel(loggingStatusPointsLabel, string);
05010     redraw = 1;
05011 
05012     oldLogPoints = emcStatus->logPoints;
05013   }
05014 
05015   // fill in the active G codes
05016   active_g_codes_string[0] = 0;
05017   for (t = 1; t < EMC_TASK_ACTIVE_G_CODES; t++) {
05018     code = emcStatus->task.activeGCodes[t];
05019     if (code == -1) {
05020       continue;
05021     }
05022     if (code % 10) {
05023       sprintf(string, "G%.1f ", (double) code / 10.0);
05024     }
05025     else {
05026       sprintf(string, "G%d ", code / 10);
05027     }
05028     strcat(active_g_codes_string, string);
05029   }
05030 
05031   // fill in the active M codes, settings too
05032   active_m_codes_string[0] = 0;
05033   for (t = 1; t < EMC_TASK_ACTIVE_M_CODES; t++) {
05034     code = emcStatus->task.activeMCodes[t];
05035     if (code == -1) {
05036       continue;
05037     }
05038     sprintf(string, "M%d ", code);
05039     strcat(active_m_codes_string, string);
05040   }
05041 
05042   sprintf(mdiCodes, "%s %s", active_g_codes_string, active_m_codes_string);
05043 
05044   // fill in F and S codes also
05045   sprintf(string, " F%.0f", emcStatus->task.activeSettings[1]);
05046   strcat(mdiCodes, string);
05047   sprintf(string, " S%.0f", emcStatus->task.activeSettings[2]);
05048   strcat(mdiCodes, string);
05049 
05050   if (0 != strcmp(oldMdiCodes, mdiCodes)) {
05051     XtVaSetValues(mdiCodesLabel, XtNlabel, mdiCodes, NULL);
05052     strcpy(oldMdiCodes, mdiCodes);
05053   }
05054 
05055   // program text updating
05056 
05057   if (0 != emcStatus->task.file[0] &&
05058       0 != strcmp(programFile, emcStatus->task.file)) {
05059     // new program has been opened-- open it here
05060 
05061     fwClose(&programFw);
05062     oldProgramActiveLine = -1;
05063 
05064     if (0 == fwOpen(&programFw, emcStatus->task.file)) {
05065       // opened successfully locally
05066       // save it to run again
05067       strcpy(lastProgramFile, emcStatus->task.file);
05068       // set string for label
05069       strcpy(string, emcStatus->task.file);
05070     }
05071     else {
05072       // couldn't open it locally
05073       // save it to run again, even though we can't see it
05074       strcpy(lastProgramFile, emcStatus->task.file);
05075       // set string for label
05076       sprintf(string, "(%s not found)", emcStatus->task.file);
05077     }
05078 
05079     // set the program label
05080     setLabel(programFormName, string);
05081     redraw = 1;
05082 
05083     strcpy(programFile, emcStatus->task.file);
05084   }
05085 
05086   // compose program state string
05087   switch (emcStatus->task.interpState) {
05088   case EMC_TASK_INTERP_IDLE:
05089     strcpy(string, "Idle");
05090     break;
05091 
05092   case EMC_TASK_INTERP_READING:
05093   case EMC_TASK_INTERP_WAITING:
05094     strcpy(string, "Running");
05095     break;
05096 
05097   case EMC_TASK_INTERP_PAUSED:
05098     strcpy(string, "PAUSED");
05099     break;
05100 
05101   default:
05102     strcpy(string, "(Idle)");   // shouldn't get here; parens for debug
05103     break;
05104   }
05105   // and print it, if new
05106   if (strcmp(string, oldProgramString)) {
05107     setLabel(programFormState, string);
05108     redraw = 1;
05109 
05110     strcpy(oldProgramString, string);
05111   }
05112 
05113   // print active line and next few in window
05114 
05115   if (programStartLineLast < 0 ||
05116       emcStatus->task.readLine < programStartLineLast) {
05117     // controller is skipping lines
05118     programActiveLine = emcStatus->task.readLine;
05119   }
05120   else {                        // controller is not skipping lines
05121     if (emcStatus->task.currentLine > 0) {
05122       if (emcStatus->task.motionLine > 0 &&
05123           emcStatus->task.motionLine < emcStatus->task.currentLine) {
05124         // active line is the motion line, which lags
05125         programActiveLine = emcStatus->task.motionLine;
05126       }
05127       else {
05128         // active line is the current line-- no motion lag
05129         programActiveLine = emcStatus->task.currentLine;
05130       }
05131     }
05132     else {
05133       // no active line at all
05134       programActiveLine = 0;
05135     }
05136   } // end of else controller is not skipping lines
05137 
05138   if (programActiveLine != oldProgramActiveLine) {
05139     programTopLine = programActiveLine - 2;
05140     if (programTopLine < 1) {
05141       programTopLine = 1;
05142     }
05143     fwSyncLine(&programFw, programTopLine);
05144     fwString(&programFw, programFwString);
05145     setProgramText(programFwString);
05146     highlightProgramText(programFwString, programActiveLine - programTopLine);
05147     redraw = 1;
05148 
05149     oldProgramActiveLine = programActiveLine;
05150   }
05151 
05152   // set label colors: do red for limit first
05153   // FIXME-- this should only be done for joint frame; what do
05154   // we do for world frame?
05155   for (t = 0; t < numPosLabels; t++) {
05156     if (emcStatus->motion.axis[t].minHardLimit ||
05157         emcStatus->motion.axis[t].minSoftLimit ||
05158         emcStatus->motion.axis[t].maxSoftLimit ||
05159         emcStatus->motion.axis[t].maxHardLimit) {
05160       if (posColor[t] != pixelRed) {
05161         setColor(posLabel[t], pixelRed, 1);
05162         posColor[t] = pixelRed;
05163       }
05164     }
05165     else if (emcStatus->motion.axis[t].homed &&
05166              posColor[t] != pixelGreen) {
05167       setColor(posLabel[t], pixelGreen, 1);
05168       posColor[t] = pixelGreen;
05169     }
05170     else if (! emcStatus->motion.axis[t].homed &&
05171              posColor[t] != pixelYellow) {
05172       setColor(posLabel[t], pixelYellow, 1);
05173       posColor[t] = pixelYellow;
05174     }
05175   }
05176 
05177   // do menu dimming
05178 
05179   if (emcStatus->task.state != EMC_TASK_STATE_ON) {
05180     // if not on, dim all menus
05181     enableAuxMenus(False);
05182     enableManualMenus(False);
05183     enableAutoMenus(False);
05184     enableMdiMenus(False);
05185   }
05186   else {
05187     // it's on, so only enable according to mode
05188     if (emcStatus->task.mode == EMC_TASK_MODE_MANUAL) {
05189       enableAuxMenus(True);
05190       enableAutoMenus(False);
05191       enableMdiMenus(False);
05192       enableManualMenus(True);
05193     }
05194     else if (emcStatus->task.mode == EMC_TASK_MODE_AUTO) {
05195       if (emcStatus->task.interpState == EMC_TASK_INTERP_IDLE ||
05196           emcStatus->task.interpState == EMC_TASK_INTERP_PAUSED) {
05197         enableAuxMenus(True);
05198       }
05199       else {
05200         enableAuxMenus(False);
05201       }
05202       enableMdiMenus(False);
05203       enableManualMenus(False);
05204       enableAutoMenus(True);
05205     }
05206     else if (emcStatus->task.mode == EMC_TASK_MODE_MDI) {
05207       enableAuxMenus(True);
05208       enableManualMenus(False);
05209       enableAutoMenus(False);
05210       enableMdiMenus(True);
05211     }
05212   }
05213 
05214   // flush changes now if necessary, don't wait for event
05215   if (redraw) {
05216     XFlush(XtDisplay(topForm));
05217     redraw = 0;
05218   }
05219 
05220   // re-register this proc for the timeout
05221   XtAppAddTimeOut(app_context, UPDATE_MSECS, timeoutCB, NULL);
05222 
05223   return;
05224 }
05225 
05226   static void topLevelProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05227 {
05228   quit();
05229 }
05230 
05231 static void fileOpenShellProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05232 {
05233   XtPopdown(fileOpenShell);
05234 }
05235 
05236 static void fileQuitShellProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05237 {
05238   XtPopdown(fileQuitShell);
05239 }
05240 
05241 static void fileEditShellProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05242 {
05243   XtPopdown(fileEditShell);
05244 }
05245 
05246 static void fileEditorShellProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05247 {
05248   XtPopdown(fileEditorShell);
05249   destroyFileEditorShell();
05250 }
05251 
05252 static void toolTableShellProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05253 {
05254   XtPopdown(toolTableShell);
05255   destroyToolTableShell();
05256 }
05257 
05258 static void toolSetOffsetShellProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05259 {
05260   XtPopdown(toolSetOffsetShell);
05261 }
05262 
05263 static void posOffsetShellProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05264 {
05265   XtPopdown(posOffsetShell);
05266 }
05267 
05268 static void jogSpeedShellProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05269 {
05270   XtPopdown(jogSpeedShell);
05271 }
05272 
05273 static void feedOverrideShellProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05274 {
05275   XtPopdown(feedOverrideShell);
05276 }
05277 
05278 static void varFileShellProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05279 {
05280   XtPopdown(varFileShell);
05281   destroyVarFileShell();
05282 }
05283 
05284 static void diagnosticsShellProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05285 {
05286   diagnosticsIsPopped = 0;
05287   XtPopdown(diagnosticsShell);
05288 }
05289 
05290 static void calibShellProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05291 {
05292   XtPopdown(calibShell);
05293 }
05294 
05295 static void loggingShellProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05296 {
05297   XtPopdown(loggingShell);
05298 }
05299 
05300 static void helpXemcProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05301 {
05302   XtPopdown(helpXemcShell);
05303 }
05304 
05305 static void helpAboutProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05306 {
05307   XtPopdown(helpAboutShell);
05308 }
05309 
05310 static void errorShellProtocols(Widget w, XEvent *event, String *string, Cardinal *c)
05311 {
05312   XtPopdown(errorShell);
05313   errorIsPopped = 0;
05314   destroyErrorShell();
05315 }
05316 
05317 static XtActionsRec actionsTable[] =
05318 {
05319   {"downAction", downAction},
05320   {"upAction", upAction},
05321   {"keyAction", keyAction},
05322   {"fileOpenReturnAction", fileOpenReturnAction},
05323   {"fileOpenTabAction", fileOpenTabAction},
05324   {"fileEditReturnAction", fileEditReturnAction},
05325   {"fileEditTabAction", fileEditTabAction},
05326   {"fileQuitReturnAction", fileQuitReturnAction},
05327   {"fileQuitTabAction", fileQuitTabAction},
05328   {"diagnosticsReturnAction", diagnosticsReturnAction},
05329   {"calibReturnAction", calibReturnAction},
05330   {"calibTabAction", calibTabAction},
05331   {"loggingReturnAction", loggingReturnAction},
05332   {"loggingTabAction", loggingTabAction},
05333   {"toolSetOffsetUpAction", toolSetOffsetUpAction},
05334   {"toolSetOffsetReturnAction", toolSetOffsetReturnAction},
05335   {"toolSetOffsetTabAction", toolSetOffsetTabAction},
05336   {"posOffsetUpAction", posOffsetUpAction},
05337   {"posOffsetReturnAction", posOffsetReturnAction},
05338   {"jogSpeedReturnAction", jogSpeedReturnAction},
05339   {"feedOverrideReturnAction", feedOverrideReturnAction},
05340   {"mdiReturnAction", mdiReturnAction},
05341   {"helpXemcReturnAction", helpXemcReturnAction},
05342   {"helpAboutReturnAction", helpAboutReturnAction},
05343   {"errorReturnAction", errorReturnAction},
05344   {"topLevelProtocols", topLevelProtocols},
05345   {"fileOpenShellProtocols", fileOpenShellProtocols},
05346   {"fileQuitShellProtocols", fileQuitShellProtocols},
05347   {"fileEditShellProtocols", fileEditShellProtocols},
05348   {"fileEditorShellProtocols", fileEditorShellProtocols},
05349   {"toolTableShellProtocols", toolTableShellProtocols},
05350   {"toolSetOffsetShellProtocols", toolSetOffsetShellProtocols},
05351   {"posOffsetShellProtocols", posOffsetShellProtocols},
05352   {"jogSpeedShellProtocols", jogSpeedShellProtocols},
05353   {"feedOverrideShellProtocols", feedOverrideShellProtocols},
05354   {"varFileShellProtocols", varFileShellProtocols},
05355   {"diagnosticsShellProtocols", diagnosticsShellProtocols},
05356   {"calibShellProtocols", calibShellProtocols},
05357   {"loggingShellProtocols", loggingShellProtocols},
05358   {"helpXemcProtocols", helpXemcProtocols},
05359   {"helpAboutProtocols", helpAboutProtocols},
05360   {"errorShellProtocols", errorShellProtocols}
05361 };
05362 
05363 typedef void (MenuSelectFunc)(Widget w, XtPointer client_data, XtPointer call_data);
05364 
05365 static int setupMenu(Widget *menu, char *label,
05366                      char **labels,
05367                      Widget which,
05368                      Widget horiz, Widget vert,
05369                      MenuSelectFunc *func)
05370 {
05371   Widget *popup = new Widget;   // this will be freed automatically at exit
05372   int t;
05373 
05374   if (NULL != horiz)
05375     {
05376       if (NULL != vert)
05377         {
05378           *menu =
05379             XtVaCreateManagedWidget(label,
05380                                     menuButtonWidgetClass,
05381                                     which,
05382                                     XtNfromHoriz, horiz,
05383                                     XtNfromVert, vert,
05384                                     NULL);
05385         }
05386       else
05387         {
05388           *menu =
05389             XtVaCreateManagedWidget(label,
05390                                     menuButtonWidgetClass,
05391                                     which,
05392                                     XtNfromHoriz, horiz,
05393                                     NULL);
05394         }
05395     }
05396   else
05397     {
05398       if (NULL != vert)
05399         {
05400           *menu =
05401             XtVaCreateManagedWidget(label,
05402                                     menuButtonWidgetClass,
05403                                     which,
05404                                     XtNfromVert, vert,
05405                                     NULL);
05406         }
05407       else
05408         {
05409           *menu =
05410             XtVaCreateManagedWidget(label,
05411                                     menuButtonWidgetClass,
05412                                     which,
05413                                     NULL);
05414         }
05415     }
05416 
05417   *popup =
05418     XtVaCreatePopupShell("menu", // need to hard-code "menu" here
05419                          simpleMenuWidgetClass,
05420                          *menu,
05421                          NULL);
05422 
05423   // set the menu item names
05424   for (t = 0; labels[t] != NULL; t++)
05425     {
05426       if (labels[t][0] == '-' &&
05427           labels[t][1] == 0)
05428         {
05429           // it's a dash
05430           XtAddCallback(XtVaCreateManagedWidget(labels[t],
05431                                                 smeLineObjectClass,
05432                                                 *popup,
05433                                                 NULL),
05434                         XtNcallback, func, (XtPointer) t);
05435 
05436         }
05437       else
05438         {
05439           XtAddCallback(XtVaCreateManagedWidget(labels[t],
05440                                                 smeBSBObjectClass,
05441                                                 *popup,
05442                                                 NULL),
05443                         XtNcallback, func, (XtPointer) t);
05444         }
05445     }
05446   return(0);
05447 }
05448 
05449 static String fallbackResources[] =
05450 {
05451   NULL
05452 };
05453 
05454 static void quit()
05455 {
05456   // clean up NML buffers
05457 
05458   if (emcErrorBuffer != 0)
05459     {
05460       delete emcErrorBuffer;
05461       emcErrorBuffer = 0;
05462     }
05463 
05464   if (emcStatusBuffer != 0)
05465     {
05466       delete emcStatusBuffer;
05467       emcStatusBuffer = 0;
05468       emcStatus = 0;
05469     }
05470 
05471   if (emcCommandBuffer != 0)
05472     {
05473       delete emcCommandBuffer;
05474       emcCommandBuffer = 0;
05475     }
05476 
05477   // get rid of program file window string
05478   if (NULL != programFwString) {
05479     free(programFwString);
05480     programFwString = 0;
05481   }
05482 
05483   exit(0);
05484 }
05485 
05486 // destructively converts string to its uppercase counterpart
05487 static char *upcase(char *string)
05488 {
05489   char *ptr = string;
05490 
05491   while (*ptr != 0)
05492     {
05493       *ptr = toupper(*ptr);
05494       ptr++;
05495     }
05496 
05497   return string;
05498 }
05499 
05500 static int iniLoad(const char *filename)
05501 {
05502   INIFILE inifile;
05503   const char *inistring;
05504   char machine[INIFILE_MAX_LINELEN] = "";
05505   char version[INIFILE_MAX_LINELEN] = "";
05506   char displayString[INIFILE_MAX_LINELEN] = "";
05507   int t;
05508   int i;
05509   double d;
05510   int len;
05511 
05512   // open it
05513   if (-1 == inifile.open(filename)) {
05514     return -1;
05515   }
05516 
05517   if (NULL != (inistring = inifile.find("NML_FILE", "EMC"))) {
05518     // copy to global
05519     strcpy(EMC_NMLFILE, inistring);
05520   }
05521   else {
05522     // not found, use default
05523   }
05524 
05525   if (NULL != (inistring = inifile.find("DEBUG", "EMC"))) {
05526     // copy to global
05527     if (1 != sscanf(inistring, "%i", &EMC_DEBUG)) {
05528       EMC_DEBUG = 0;
05529     }
05530   }
05531   else {
05532     // not found, use default
05533     EMC_DEBUG = 0;
05534   }
05535 
05536 
05537   if (NULL != (inistring = inifile.find("AXES", "TRAJ"))) {
05538     if (1 == sscanf(inistring, "%d", &numJoints)) {
05539       // compare against XEMC_NUM_AXES, if larger then clip and warn
05540       if (numJoints > XEMC_NUM_AXES) {
05541         numJoints = XEMC_NUM_AXES;
05542       }
05543     }
05544     else {
05545       // there, but invalid
05546       numJoints = 3;
05547     }
05548   }
05549   else {
05550     // not there, use default
05551     numJoints = 3;
05552   }
05553 
05554   if (NULL != (inistring = inifile.find("KINEMATICS", "TRAJ"))) {
05555     if (! strcmp(inistring, "IDENTITY")) {
05556       kinematicsType = KINEMATICS_IDENTITY;
05557     }
05558     else if (! strcmp(inistring, "SERIAL")) {
05559       kinematicsType = KINEMATICS_SERIAL;
05560     }
05561     else if (! strcmp(inistring, "PARALLEL")) {
05562       kinematicsType = KINEMATICS_SERIAL;
05563     }
05564     else {
05565       // there, but invalid
05566       kinematicsType = KINEMATICS_IDENTITY;
05567     }
05568   }
05569   else {
05570     // not there, use default
05571     kinematicsType = KINEMATICS_IDENTITY;
05572   }
05573 
05574   // set coordinateMark[] array with 1's for those coordinates
05575   // to be displayed, e.g., 1 1 0 0 0 1 for X Y W out of X Y Z R P W
05576   if (NULL != (inistring = inifile.find("COORDINATES", "TRAJ"))) {
05577     len = strlen(inistring);
05578     // there's an entry in ini file, so clear all the marks out first
05579     // so that defaults don't apply at all
05580     for (t = 0; t < 6; t++) {
05581       coordinateMark[t] = 0;
05582     }
05583     // now set actual marks
05584     for (t = 0; t < len; t++) {
05585       if (inistring[t] == 'X')
05586         coordinateMark[0] = 1;
05587       else if (inistring[t] == 'Y')
05588         coordinateMark[1] = 1;
05589       else if (inistring[t] == 'Z')
05590         coordinateMark[2] = 1;
05591       else if (inistring[t] == 'R')
05592         coordinateMark[3] = 1;
05593       else if (inistring[t] == 'P')
05594         coordinateMark[4] = 1;
05595       else if (inistring[t] == 'W')
05596         coordinateMark[5] = 1;
05597     }
05598   }
05599   else {
05600     // not there, use default
05601     // by leaving coordinateMark[] alone
05602   }
05603 
05604   // count the number of unique marks
05605   numCoords = 0;
05606   for (t = 0; t < 6; t++) {
05607     if (coordinateMark[t]) {
05608       // since t never lags numCoords, we can pack letters down
05609       posLabelWorld[numCoords] = posLabelWorld[t];
05610       coordNum[numCoords] = t;
05611       numCoords++;
05612     }
05613   }
05614 
05615   if (NULL != (inistring = inifile.find("MACHINE", "EMC"))) {
05616     strcpy(machine, inistring);
05617 
05618     if (NULL != (inistring = inifile.find("VERSION", "EMC"))) {
05619       sscanf(inistring, "$Revision: %s", version);
05620 
05621       sprintf(version_string, "%s EMC Version %s", machine, version);
05622     }
05623   }
05624 
05625   if (NULL != (inistring = inifile.find("TOOL_TABLE", "EMCIO"))) {
05626     strcpy(TOOL_TABLE_FILE, inistring);
05627   }
05628   else {
05629     strcpy(TOOL_TABLE_FILE, "tool.tbl"); // FIXME-- hardcoded
05630   }
05631 
05632   if (NULL != (inistring = inifile.find("PARAMETER_FILE", "RS274NGC"))) {
05633     strcpy(PARAMETER_FILE, inistring);
05634   }
05635   else {
05636     strcpy(PARAMETER_FILE, "rs274ngc.var"); // FIXME-- hardcoded
05637   }
05638 
05639   if (NULL != (inistring = inifile.find("DEFAULT_VELOCITY", "TRAJ"))) {
05640     if (1 != sscanf(inistring, "%lf", &TRAJ_DEFAULT_VELOCITY)) {
05641       TRAJ_DEFAULT_VELOCITY = DEFAULT_TRAJ_DEFAULT_VELOCITY;
05642     }
05643   }
05644   else {
05645     TRAJ_DEFAULT_VELOCITY = DEFAULT_TRAJ_DEFAULT_VELOCITY;
05646   }
05647   // round jogSpeed in display to integer, per-minute
05648   jogSpeed = (int) (TRAJ_DEFAULT_VELOCITY * 60.0 + 0.5);
05649 
05650   if (NULL != (inistring = inifile.find("MAX_VELOCITY", "TRAJ"))) {
05651     if (1 != sscanf(inistring, "%lf", &TRAJ_MAX_VELOCITY)) {
05652       TRAJ_MAX_VELOCITY = DEFAULT_TRAJ_MAX_VELOCITY;
05653     }
05654   }
05655   else {
05656     TRAJ_MAX_VELOCITY = DEFAULT_TRAJ_MAX_VELOCITY;
05657   }
05658   // round maxJogSpeed in display to integer, per-minute
05659   maxJogSpeed = (int) (TRAJ_MAX_VELOCITY * 60.0 + 0.5);
05660 
05661   if (NULL != (inistring = inifile.find("PROGRAM_PREFIX", "DISPLAY"))) {
05662     if (1 != sscanf(inistring, "%s", programPrefix)) {
05663       programPrefix[0] = 0;
05664     }
05665   }
05666   else if (NULL != (inistring = inifile.find("PROGRAM_PREFIX", "TASK"))) {
05667     if (1 != sscanf(inistring, "%s", programPrefix)) {
05668       programPrefix[0] = 0;
05669     }
05670   }
05671   else {
05672     programPrefix[0] = 0;
05673   }
05674 
05675   if (NULL != (inistring = inifile.find("POSITION_OFFSET", "DISPLAY"))) {
05676     if (1 == sscanf(inistring, "%s", displayString)) {
05677       if (! strcmp(upcase(displayString), "MACHINE")) {
05678         coords = COORD_MACHINE;
05679       }
05680       else if (1 == sscanf(inistring, "%s", displayString)) {
05681         if (! strcmp(upcase(displayString), "RELATIVE")) {
05682           coords = COORD_RELATIVE;
05683         }
05684       }
05685       else {
05686         // error-- invalid value
05687         // ignore
05688       }
05689     }
05690     else {
05691       // error-- no value provided
05692       // ignore
05693     }
05694   }
05695   else {
05696     // no line at all
05697     // ignore
05698   }
05699 
05700   if (NULL != (inistring = inifile.find("POSITION_FEEDBACK", "DISPLAY"))) {
05701     if (1 == sscanf(inistring, "%s", displayString)) {
05702       if (! strcmp(upcase(displayString), "ACTUAL")) {
05703         posDisplay = POS_DISPLAY_ACT;
05704       }
05705       else if (1 == sscanf(inistring, "%s", displayString)) {
05706         if (! strcmp(upcase(displayString), "COMMANDED")) {
05707           posDisplay = POS_DISPLAY_CMD;
05708         }
05709       }
05710       else {
05711         // error-- invalid value
05712         // ignore
05713       }
05714     }
05715     else {
05716       // error-- no value provided
05717       // ignore
05718     }
05719   }
05720   else {
05721     // no line at all
05722     // ignore
05723   }
05724 
05725   for (t = 0; t < XEMC_NUM_AXES; t++) {
05726     jogPol[t] = 1;              // set to default
05727     sprintf(displayString, "AXIS_%d", t);
05728     if (NULL != (inistring = inifile.find("JOGGING_POLARITY", displayString)) &&
05729         1 == sscanf(inistring, "%d", &i) &&
05730         i == 0) {
05731       // it read as 0, so override default
05732       jogPol[t] = 0;
05733     }
05734   }
05735 
05736   if (NULL != (inistring = inifile.find("MAX_FEED_OVERRIDE", "DISPLAY"))) {
05737     if (1 == sscanf(inistring, "%lf", &d) &&
05738         d > 0.0) {
05739       maxFeedOverride = (int) (d * 100.0 + 0.5);
05740     }
05741     else {
05742       // error-- no value provided
05743       // ignore
05744     }
05745   }
05746   else {
05747     // no line at all
05748     // ignore
05749   }
05750 
05751   // close it
05752   inifile.close();
05753 
05754   return 0;;
05755 }
05756 
05757 int main(int argc, char **argv)
05758 {
05759   int t;
05760   double start;
05761   int good;
05762   char string[80];
05763   Dimension cmfbw, sdw, sw, siw, sh, bh, bw;
05764   Dimension stw, mw;
05765   Dimension posw;
05766 
05767   // process command line args, indexing argv[] from [1]
05768   for (t = 1; t < argc; t++)
05769     {
05770       // try -ini
05771       if (!strcmp(argv[t], "-ini"))
05772         {
05773           if (t == argc - 1)
05774             {
05775               printf("syntax: -ini <inifile\n");
05776               exit(1);
05777             }
05778           else
05779             {
05780               strcpy(EMC_INIFILE, argv[t+1]);
05781               t++;              // step over inifile
05782               continue;
05783             }
05784         }
05785     }
05786 
05787   // read INI file
05788   iniLoad(EMC_INIFILE);
05789 
05790   // blank out the annoying RCS version message
05791   rcs_version_printed = 1;
05792 
05793   // init NML
05794 
05795 #define RETRY_TIME 10.0         // seconds to wait for subsystems to come up
05796 #define RETRY_INTERVAL 1.0      // seconds between wait tries for a subsystem
05797 
05798   if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
05799     set_rcs_print_destination(RCS_PRINT_TO_NULL);     // inhibit diag messages
05800   }
05801   start = etime();
05802   good = 0;
05803   do {
05804     if (0 == emcTaskNmlGet()) {
05805       good = 1;
05806       break;
05807     }
05808     esleep(RETRY_INTERVAL);
05809   } while (etime() - start < RETRY_TIME);
05810   if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
05811     set_rcs_print_destination(RCS_PRINT_TO_STDOUT); // restore diag messages
05812   }
05813   if (! good) {
05814     rcs_print_error("can't establish communication with emc\n");
05815     exit(1);
05816   }
05817 
05818   if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
05819     set_rcs_print_destination(RCS_PRINT_TO_NULL);     // inhibit diag messages
05820   }
05821   updateStatus();
05822   if(emcStatus->motion.traj.kinematics_type != 1)
05823     {   
05824       posFrame = POS_FRAME_JOINT;
05825     }
05826   start = etime();
05827   good = 0;
05828   do {
05829     if (0 == emcErrorNmlGet()) {
05830       good = 1;
05831       break;
05832     }
05833     esleep(RETRY_INTERVAL);
05834   } while (etime() - start < RETRY_TIME);
05835   if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
05836     set_rcs_print_destination(RCS_PRINT_TO_STDOUT); // restore diag messages
05837   }
05838   if (! good) {
05839     rcs_print_error("can't establish communication with emc\n");
05840     exit(1);
05841   }
05842 
05843   // create file window for program text
05844 
05845   programFwString =
05846     (char *) malloc(PROGRAM_FW_NUM_LINES * PROGRAM_FW_LEN_LINES);
05847 
05848   if (0 != fwInit(&programFw, PROGRAM_FW_NUM_LINES, PROGRAM_FW_LEN_LINES)) {
05849     fprintf(stderr, "can't init file window\n");
05850     exit(1);
05851   }
05852 
05853   // get widgets
05854 
05855   topLevel =
05856     XtVaAppInitialize(&app_context, /* Application context */
05857                       "YEmc",   /* Application class */
05858                       NULL, 0,  /* command line option list */
05859                       &argc, argv, /* command line args */
05860                       fallbackResources, /* app defaults string, or NULL */
05861                       NULL);    /* terminate varargs list */
05862 
05863   topForm =
05864     XtVaCreateManagedWidget("topForm", /* arbitrary widget name */
05865                             formWidgetClass, /* widget class from Label.h */
05866                             topLevel, /* parent widget */
05867                             NULL); /* terminate varargs list */
05868 
05869   barMenuForm =
05870     XtVaCreateManagedWidget("barMenuForm",
05871                             formWidgetClass,
05872                             topForm,
05873                             NULL);
05874 
05875   setupMenu(&fileMenu, "fileMenu",
05876             fileMenuEntryNames,
05877             barMenuForm,
05878             NULL, NULL,
05879             fileMenuSelect);
05880 
05881   setupMenu(&viewMenu, "viewMenu",
05882             viewMenuEntryNames,
05883             barMenuForm,
05884             fileMenu, NULL,
05885             viewMenuSelect);
05886 
05887   setupMenu(&settingsMenu, "settingsMenu",
05888             settingsMenuEntryNames,
05889             barMenuForm,
05890             viewMenu, NULL,
05891             settingsMenuSelect);
05892 
05893   setupMenu(&helpMenu, "helpMenu",
05894             helpMenuEntryNames,
05895             barMenuForm,
05896             settingsMenu, NULL,
05897             helpMenuSelect);
05898 
05899   commandMenuForm =
05900     XtVaCreateManagedWidget("commandMenuForm",
05901                             formWidgetClass,
05902                             topForm,
05903                             XtNfromVert, barMenuForm,
05904                             NULL);
05905 
05906   setupMenu(&stateMenu, "stateMenu",
05907             stateMenuEntryNames,
05908             commandMenuForm,
05909             NULL, NULL,
05910             stateMenuSelect);
05911 
05912   XtVaGetValues(stateMenu,
05913                 XtNwidth, &stw,
05914                 NULL);
05915 
05916   setupMenu(&modeMenu, "modeMenu",
05917             modeMenuEntryNames,
05918             commandMenuForm,
05919             NULL, stateMenu,
05920             modeMenuSelect);
05921 
05922   XtVaSetValues(modeMenu,
05923                 XtNwidth, stw,
05924                 NULL);
05925 
05926   setupMenu(&mistMenu, "mistMenu",
05927             mistMenuEntryNames,
05928             commandMenuForm,
05929             stateMenu, NULL,
05930             mistMenuSelect);
05931 
05932   XtVaGetValues(mistMenu,
05933                 XtNwidth, &mw,
05934                 NULL);
05935 
05936   setupMenu(&floodMenu, "floodMenu",
05937             floodMenuEntryNames,
05938             commandMenuForm,
05939             stateMenu, mistMenu,
05940             floodMenuSelect);
05941 
05942   XtVaSetValues(floodMenu,
05943                 XtNwidth, mw,
05944                 NULL);
05945 
05946   spindleDecLabel =
05947     XtVaCreateManagedWidget("spindleDecLabel",
05948                             labelWidgetClass,
05949                             commandMenuForm,
05950                             XtNfromHoriz, mistMenu,
05951                             NULL);
05952 
05953   setupMenu(&spindleMenu, "spindleMenu",
05954             spindleMenuEntryNames,
05955             commandMenuForm,
05956             spindleDecLabel, NULL,
05957             spindleMenuSelect);
05958 
05959   spindleIncLabel =
05960     XtVaCreateManagedWidget("spindleIncLabel",
05961                             labelWidgetClass,
05962                             commandMenuForm,
05963                             XtNfromHoriz, spindleMenu,
05964                             NULL);
05965 
05966   XtVaGetValues(spindleMenu,
05967                 XtNwidth, &sw,
05968                 XtNheight, &sh,
05969                 XtNborderWidth, &cmfbw,
05970                 NULL);
05971 
05972   XtVaGetValues(spindleDecLabel,
05973                 XtNwidth, &sdw,
05974                 NULL);
05975 
05976   XtVaGetValues(spindleIncLabel,
05977                 XtNwidth, &siw,
05978                 NULL);
05979 
05980   setupMenu(&brakeMenu, "brakeMenu",
05981             brakeMenuEntryNames,
05982             commandMenuForm,
05983             mistMenu, spindleDecLabel,
05984             brakeMenuSelect);
05985 
05986   bw = sdw + cmfbw + cmfbw + sw + cmfbw + cmfbw + siw;
05987   XtVaSetValues(brakeMenu,
05988                 XtNwidth, bw,
05989                 NULL);
05990 
05991   XtVaGetValues(brakeMenu,
05992                 XtNheight, &bh,
05993                 NULL);
05994 
05995   fileOpenShell =
05996     XtVaCreatePopupShell("fileOpenShell",
05997                          transientShellWidgetClass,
05998                          topLevel,
05999                          XtNallowShellResize, True,
06000                          NULL);
06001 
06002   fileOpenDialog =
06003     XtVaCreateManagedWidget("fileOpenDialog",
06004                             dialogWidgetClass,
06005                             fileOpenShell,
06006                             XtNvalue, programPrefix,
06007                             NULL);
06008 
06009   fileOpenDone =
06010     XtVaCreateManagedWidget("fileOpenDone",
06011                             commandWidgetClass,
06012                             fileOpenDialog,
06013                             NULL);
06014 
06015   XtAddCallback(fileOpenDone, XtNcallback, fileOpenDoneCB, fileOpenShell);
06016 
06017   fileOpenCancel =
06018     XtVaCreateManagedWidget("fileOpenCancel",
06019                             commandWidgetClass,
06020                             fileOpenDialog,
06021                             NULL);
06022 
06023   XtAddCallback(fileOpenCancel, XtNcallback, genericDoneCB, fileOpenShell);
06024 
06025   fileEditShell =
06026     XtVaCreatePopupShell("fileEditShell",
06027                          transientShellWidgetClass,
06028                          topLevel,
06029                          XtNallowShellResize, True,
06030                          NULL);
06031 
06032   fileEditDialog =
06033     XtVaCreateManagedWidget("fileEditDialog",
06034                             dialogWidgetClass,
06035                             fileEditShell,
06036                             XtNvalue, programPrefix,
06037                             NULL);
06038 
06039   fileEditDone =
06040     XtVaCreateManagedWidget("fileEditDone",
06041                             commandWidgetClass,
06042                             fileEditDialog,
06043                             NULL);
06044 
06045   XtAddCallback(fileEditDone, XtNcallback, fileEditDoneCB, fileEditShell);
06046 
06047   fileEditCancel =
06048     XtVaCreateManagedWidget("fileEditCancel",
06049                             commandWidgetClass,
06050                             fileEditDialog,
06051                             NULL);
06052 
06053   XtAddCallback(fileEditCancel, XtNcallback, genericDoneCB, fileEditShell);
06054 
06055   fileQuitShell =
06056     XtVaCreatePopupShell("fileQuitShell",
06057                          transientShellWidgetClass,
06058                          topLevel,
06059                          XtNallowShellResize, True,
06060                          NULL);
06061 
06062   fileQuitDialog =
06063     XtVaCreateManagedWidget("fileQuitDialog",
06064                             dialogWidgetClass,
06065                             fileQuitShell,
06066                             NULL);
06067 
06068   fileQuitDone =
06069     XtVaCreateManagedWidget("fileQuitDone",
06070                             commandWidgetClass,
06071                             fileQuitDialog,
06072                             NULL);
06073 
06074   XtAddCallback(fileQuitDone, XtNcallback, fileQuitDoneCB, fileQuitShell);
06075 
06076   fileQuitCancel =
06077     XtVaCreateManagedWidget("fileQuitCancel",
06078                             commandWidgetClass,
06079                             fileQuitDialog,
06080                             NULL);
06081 
06082   XtAddCallback(fileQuitCancel, XtNcallback, genericDoneCB, fileQuitShell);
06083 
06084   // diagnostics shell
06085 
06086   diagnosticsShell =
06087     XtVaCreatePopupShell("diagnosticsShell",
06088                          topLevelShellWidgetClass,
06089                          topLevel,
06090                          XtNallowShellResize, True,
06091                          NULL);
06092 
06093   diagnosticsForm =
06094     XtVaCreateManagedWidget("diagnosticsForm",
06095                             formWidgetClass,
06096                             diagnosticsShell,
06097                             NULL);
06098 
06099   diagnosticsLabel =
06100     XtVaCreateManagedWidget("diagnosticsLabel",
06101                             labelWidgetClass,
06102                             diagnosticsForm,
06103                             XtNborderWidth, 0,
06104                             NULL);
06105 
06106   diagnosticsTaskHBLabel =
06107     XtVaCreateManagedWidget("diagnosticsTaskHBLabel",
06108                             labelWidgetClass,
06109                             diagnosticsForm,
06110                             XtNfromVert, diagnosticsLabel,
06111                             XtNborderWidth, 0,
06112                             NULL);
06113 
06114   diagnosticsTaskHB =
06115     XtVaCreateManagedWidget("diagnosticsTaskHB",
06116                             labelWidgetClass,
06117                             diagnosticsForm,
06118                             XtNfromVert, diagnosticsLabel,
06119                             XtNfromHoriz, diagnosticsTaskHBLabel,
06120                             NULL);
06121 
06122   diagnosticsIoHBLabel =
06123     XtVaCreateManagedWidget("diagnosticsIoHBLabel",
06124                             labelWidgetClass,
06125                             diagnosticsForm,
06126                             XtNfromVert, diagnosticsTaskHBLabel,
06127                             XtNborderWidth, 0,
06128                             NULL);
06129 
06130   diagnosticsIoHB =
06131     XtVaCreateManagedWidget("diagnosticsIoHB",
06132                             labelWidgetClass,
06133                             diagnosticsForm,
06134                             XtNfromVert, diagnosticsTaskHBLabel,
06135                             XtNfromHoriz, diagnosticsIoHBLabel,
06136                             NULL);
06137 
06138   diagnosticsMotionHBLabel =
06139     XtVaCreateManagedWidget("diagnosticsMotionHBLabel",
06140                             labelWidgetClass,
06141                             diagnosticsForm,
06142                             XtNfromVert, diagnosticsIoHBLabel,
06143                             XtNborderWidth, 0,
06144                             NULL);
06145 
06146   diagnosticsMotionHB =
06147     XtVaCreateManagedWidget("diagnosticsMotionHB",
06148                             labelWidgetClass,
06149                             diagnosticsForm,
06150                             XtNfromVert, diagnosticsIoHBLabel,
06151                             XtNfromHoriz, diagnosticsMotionHBLabel,
06152                             NULL);
06153 
06154   diagnosticsFerrorLabel =
06155     XtVaCreateManagedWidget("diagnosticsFerrorLabel",
06156                             labelWidgetClass,
06157                             diagnosticsForm,
06158                             XtNfromVert, diagnosticsMotionHBLabel,
06159                             XtNborderWidth, 0,
06160                             NULL);
06161 
06162   diagnosticsFerror =
06163     XtVaCreateManagedWidget("diagnosticsFerror",
06164                             labelWidgetClass,
06165                             diagnosticsForm,
06166                             XtNfromVert, diagnosticsMotionHBLabel,
06167                             XtNfromHoriz, diagnosticsFerrorLabel,
06168                             NULL);
06169 
06170   diagnosticsDone =
06171     XtVaCreateManagedWidget("diagnosticsDone",
06172                             commandWidgetClass,
06173                             diagnosticsForm,
06174                             XtNfromVert, diagnosticsFerrorLabel,
06175                             NULL);
06176 
06177   XtAddCallback(diagnosticsDone, XtNcallback, diagnosticsDoneCB, NULL);
06178 
06179   // calibration shell
06180 
06181   calibShell =
06182     XtVaCreatePopupShell("calibShell",
06183                          topLevelShellWidgetClass,
06184                          topLevel,
06185                          XtNallowShellResize, True,
06186                          NULL);
06187 
06188   calibForm =
06189     XtVaCreateManagedWidget("calibForm",
06190                             formWidgetClass,
06191                             calibShell,
06192                             NULL);
06193 
06194   calibLabel =
06195     XtVaCreateManagedWidget("calibLabel",
06196                             labelWidgetClass,
06197                             calibForm,
06198                             XtNborderWidth, 0,
06199                             NULL);
06200 
06201   calibCycleTimeLabel =
06202     XtVaCreateManagedWidget("calibCycleTimeLabel",
06203                             labelWidgetClass,
06204                             calibForm,
06205                             XtNfromVert, calibLabel,
06206                             XtNborderWidth, 0,
06207                             NULL);
06208 
06209   calibCycleTime =
06210     XtVaCreateManagedWidget("calibCycleTime",
06211                             asciiTextWidgetClass,
06212                             calibForm,
06213                             XtNeditType, XawtextEdit,
06214                             XtNfromVert, calibLabel,
06215                             XtNfromHoriz, calibCycleTimeLabel,
06216                             NULL);
06217 
06218   calibPGainLabel =
06219     XtVaCreateManagedWidget("calibPGainLabel",
06220                             labelWidgetClass,
06221                             calibForm,
06222                             XtNfromVert, calibCycleTimeLabel,
06223                             XtNborderWidth, 0,
06224                             NULL);
06225 
06226   calibPGain =
06227     XtVaCreateManagedWidget("calibPGain",
06228                             asciiTextWidgetClass,
06229                             calibForm,
06230                             XtNeditType, XawtextEdit,
06231                             XtNfromVert, calibCycleTimeLabel,
06232                             XtNfromHoriz, calibPGainLabel,
06233                             NULL);
06234 
06235   calibIGainLabel =
06236     XtVaCreateManagedWidget("calibIGainLabel",
06237                             labelWidgetClass,
06238                             calibForm,
06239                             XtNfromVert, calibPGainLabel,
06240                             XtNborderWidth, 0,
06241                             NULL);
06242 
06243   calibIGain =
06244     XtVaCreateManagedWidget("calibIGain",
06245                             asciiTextWidgetClass,
06246                             calibForm,
06247                             XtNeditType, XawtextEdit,
06248                             XtNfromVert, calibPGainLabel,
06249                             XtNfromHoriz, calibIGainLabel,
06250                             NULL);
06251 
06252   calibDGainLabel =
06253     XtVaCreateManagedWidget("calibDGainLabel",
06254                             labelWidgetClass,
06255                             calibForm,
06256                             XtNfromVert, calibIGainLabel,
06257                             XtNborderWidth, 0,
06258                             NULL);
06259 
06260   calibDGain =
06261     XtVaCreateManagedWidget("calibDGain",
06262                             asciiTextWidgetClass,
06263                             calibForm,
06264                             XtNeditType, XawtextEdit,
06265                             XtNfromVert, calibIGainLabel,
06266                             XtNfromHoriz, calibDGainLabel,
06267                             NULL);
06268 
06269   calibFF0GainLabel =
06270     XtVaCreateManagedWidget("calibFF0GainLabel",
06271                             labelWidgetClass,
06272                             calibForm,
06273                             XtNfromVert, calibDGainLabel,
06274                             XtNborderWidth, 0,
06275                             NULL);
06276 
06277   calibFF0Gain =
06278     XtVaCreateManagedWidget("calibFF0Gain",
06279                             asciiTextWidgetClass,
06280                             calibForm,
06281                             XtNeditType, XawtextEdit,
06282                             XtNfromVert, calibDGainLabel,
06283                             XtNfromHoriz, calibFF0GainLabel,
06284                             NULL);
06285 
06286   calibFF1GainLabel =
06287     XtVaCreateManagedWidget("calibFF1GainLabel",
06288                             labelWidgetClass,
06289                             calibForm,
06290                             XtNfromVert, calibFF0GainLabel,
06291                             XtNborderWidth, 0,
06292                             NULL);
06293 
06294   calibFF1Gain =
06295     XtVaCreateManagedWidget("calibFF1Gain",
06296                             asciiTextWidgetClass,
06297                             calibForm,
06298                             XtNeditType, XawtextEdit,
06299                             XtNfromVert, calibFF0GainLabel,
06300                             XtNfromHoriz, calibFF1GainLabel,
06301                             NULL);
06302 
06303   calibFF2GainLabel =
06304     XtVaCreateManagedWidget("calibFF2GainLabel",
06305                             labelWidgetClass,
06306                             calibForm,
06307                             XtNfromVert, calibFF1GainLabel,
06308                             XtNborderWidth, 0,
06309                             NULL);
06310 
06311   calibFF2Gain =
06312     XtVaCreateManagedWidget("calibFF2Gain",
06313                             asciiTextWidgetClass,
06314                             calibForm,
06315                             XtNeditType, XawtextEdit,
06316                             XtNfromVert, calibFF1GainLabel,
06317                             XtNfromHoriz, calibFF2GainLabel,
06318                             NULL);
06319 
06320   calibBacklashLabel =
06321     XtVaCreateManagedWidget("calibBacklashLabel",
06322                             labelWidgetClass,
06323                             calibForm,
06324                             XtNfromVert, calibFF2GainLabel,
06325                             XtNborderWidth, 0,
06326                             NULL);
06327 
06328 
06329   calibBacklash =
06330     XtVaCreateManagedWidget("calibBacklash",
06331                             asciiTextWidgetClass,
06332                             calibForm,
06333                             XtNeditType, XawtextEdit,
06334                             XtNstring, string,
06335                             XtNfromVert, calibFF2GainLabel,
06336                             XtNfromHoriz, calibBacklashLabel,
06337                             NULL);
06338 
06339   calibBiasLabel =
06340     XtVaCreateManagedWidget("calibBiasLabel",
06341                             labelWidgetClass,
06342                             calibForm,
06343                             XtNfromVert, calibBacklashLabel,
06344                             XtNborderWidth, 0,
06345                             NULL);
06346 
06347 
06348   calibBias =
06349     XtVaCreateManagedWidget("calibBias",
06350                             asciiTextWidgetClass,
06351                             calibForm,
06352                             XtNeditType, XawtextEdit,
06353                             XtNstring, string,
06354                             XtNfromVert, calibBacklashLabel,
06355                             XtNfromHoriz, calibBiasLabel,
06356                             NULL);
06357 
06358   calibMaxErrorLabel =
06359     XtVaCreateManagedWidget("calibMaxErrorLabel",
06360                             labelWidgetClass,
06361                             calibForm,
06362                             XtNfromVert, calibBiasLabel,
06363                             XtNborderWidth, 0,
06364                             NULL);
06365 
06366 
06367   calibMaxError =
06368     XtVaCreateManagedWidget("calibMaxError",
06369                             asciiTextWidgetClass,
06370                             calibForm,
06371                             XtNeditType, XawtextEdit,
06372                             XtNstring, string,
06373                             XtNfromVert, calibBiasLabel,
06374                             XtNfromHoriz, calibMaxErrorLabel,
06375                             NULL);
06376 
06377   calibOutputScaleLabel =
06378     XtVaCreateManagedWidget("calibOutputScaleLabel",
06379                             labelWidgetClass,
06380                             calibForm,
06381                             XtNfromVert, calibMaxErrorLabel,
06382                             XtNborderWidth, 0,
06383                             NULL);
06384 
06385 
06386   calibOutputScale =
06387     XtVaCreateManagedWidget("calibOutputScale",
06388                             asciiTextWidgetClass,
06389                             calibForm,
06390                             XtNeditType, XawtextEdit,
06391                             XtNstring, string,
06392                             XtNfromVert, calibMaxErrorLabel,
06393                             XtNfromHoriz, calibOutputScaleLabel,
06394                             NULL);
06395 
06396   calibOutputOffsetLabel =
06397     XtVaCreateManagedWidget("calibOutputOffsetLabel",
06398                             labelWidgetClass,
06399                             calibForm,
06400                             XtNfromVert, calibOutputScaleLabel,
06401                             XtNborderWidth, 0,
06402                             NULL);
06403 
06404 
06405   calibOutputOffset =
06406     XtVaCreateManagedWidget("calibOutputOffset",
06407                             asciiTextWidgetClass,
06408                             calibForm,
06409                             XtNeditType, XawtextEdit,
06410                             XtNstring, string,
06411                             XtNfromVert, calibOutputScaleLabel,
06412                             XtNfromHoriz, calibOutputOffsetLabel,
06413                             NULL);
06414 
06415   calibFerrorLabel =
06416     XtVaCreateManagedWidget("calibFerrorLabel",
06417                             labelWidgetClass,
06418                             calibForm,
06419                             XtNfromVert, calibOutputOffsetLabel,
06420                             XtNborderWidth, 0,
06421                             NULL);
06422 
06423 
06424   calibFerror =
06425     XtVaCreateManagedWidget("calibFerror",
06426                             asciiTextWidgetClass,
06427                             calibForm,
06428                             XtNeditType, XawtextEdit,
06429                             XtNstring, string,
06430                             XtNfromVert, calibOutputOffsetLabel,
06431                             XtNfromHoriz, calibFerrorLabel,
06432                             NULL);
06433 
06434   calibDone =
06435     XtVaCreateManagedWidget("calibDone",
06436                             commandWidgetClass,
06437                             calibForm,
06438                             XtNfromVert, calibFerrorLabel,
06439                             NULL);
06440 
06441   calibCancel =
06442     XtVaCreateManagedWidget("calibCancel",
06443                             commandWidgetClass,
06444                             calibForm,
06445                             XtNfromVert, calibFerrorLabel,
06446                             XtNfromHoriz, calibDone,
06447                             NULL);
06448 
06449   XtAddCallback(calibDone, XtNcallback, calibDoneCB, NULL);
06450   XtAddCallback(calibCancel, XtNcallback, calibCancelCB, NULL);
06451 
06452   loggingShell =
06453     XtVaCreatePopupShell("loggingShell",
06454                          topLevelShellWidgetClass,
06455                          topLevel,
06456                          XtNallowShellResize, True,
06457                          NULL);
06458 
06459   loggingForm =
06460     XtVaCreateManagedWidget("loggingForm",
06461                             formWidgetClass,
06462                             loggingShell,
06463                             NULL);
06464 
06465   loggingLabel =
06466     XtVaCreateManagedWidget("loggingLabel",
06467                             labelWidgetClass,
06468                             loggingForm,
06469                             XtNborderWidth, 0,
06470                             NULL);
06471 
06472   loggingFileLabel =
06473     XtVaCreateManagedWidget("loggingFileLabel",
06474                             labelWidgetClass,
06475                             loggingForm,
06476                             XtNfromVert, loggingLabel,
06477                             XtNborderWidth, 0,
06478                             NULL);
06479 
06480   loggingFile =
06481     XtVaCreateManagedWidget("loggingFile",
06482                             asciiTextWidgetClass,
06483                             loggingForm,
06484                             XtNeditType, XawtextEdit,
06485                             XtNfromVert, loggingLabel,
06486                             XtNfromHoriz, loggingFileLabel,
06487                             NULL);
06488 
06489   loggingTypeLabel =
06490     XtVaCreateManagedWidget("loggingTypeLabel",
06491                             labelWidgetClass,
06492                             loggingForm,
06493                             XtNfromVert, loggingFileLabel,
06494                             XtNborderWidth, 0,
06495                             NULL);
06496 
06497   setupMenu(&loggingTypeMenu, "loggingTypeMenu",
06498             loggingTypeMenuEntryNames,
06499             loggingForm,
06500             loggingTypeLabel, loggingFileLabel,
06501             loggingTypeMenuSelect);
06502 
06503   loggingSizeLabel =
06504     XtVaCreateManagedWidget("loggingSizeLabel",
06505                             labelWidgetClass,
06506                             loggingForm,
06507                             XtNfromVert, loggingTypeLabel,
06508                             XtNborderWidth, 0,
06509                             NULL);
06510 
06511   loggingSize =
06512     XtVaCreateManagedWidget("loggingSize",
06513                             asciiTextWidgetClass,
06514                             loggingForm,
06515                             XtNeditType, XawtextEdit,
06516                             XtNfromVert, loggingTypeLabel,
06517                             XtNfromHoriz, loggingSizeLabel,
06518                             NULL);
06519 
06520   loggingSkipLabel =
06521     XtVaCreateManagedWidget("loggingSkipLabel",
06522                             labelWidgetClass,
06523                             loggingForm,
06524                             XtNfromVert, loggingSizeLabel,
06525                             XtNborderWidth, 0,
06526                             NULL);
06527 
06528   loggingSkip =
06529     XtVaCreateManagedWidget("loggingSkip",
06530                             asciiTextWidgetClass,
06531                             loggingForm,
06532                             XtNeditType, XawtextEdit,
06533                             XtNfromVert, loggingSizeLabel,
06534                             XtNfromHoriz, loggingSkipLabel,
06535                             NULL);
06536 
06537   loggingStart =
06538     XtVaCreateManagedWidget("loggingStart",
06539                             commandWidgetClass,
06540                             loggingForm,
06541                             XtNfromVert, loggingSkipLabel,
06542                             NULL);
06543 
06544   loggingStop =
06545     XtVaCreateManagedWidget("loggingStop",
06546                             commandWidgetClass,
06547                             loggingForm,
06548                             XtNfromVert, loggingSkipLabel,
06549                             XtNfromHoriz, loggingStart,
06550                             NULL);
06551 
06552   loggingSave =
06553     XtVaCreateManagedWidget("loggingSave",
06554                             commandWidgetClass,
06555                             loggingForm,
06556                             XtNfromVert, loggingSkipLabel,
06557                             XtNfromHoriz, loggingStop,
06558                             NULL);
06559 
06560   loggingPlot =
06561     XtVaCreateManagedWidget("loggingPlot",
06562                             commandWidgetClass,
06563                             loggingForm,
06564                             XtNfromVert, loggingSkipLabel,
06565                             XtNfromHoriz, loggingSave,
06566                             NULL);
06567 
06568   loggingDone =
06569     XtVaCreateManagedWidget("loggingDone",
06570                             commandWidgetClass,
06571                             loggingForm,
06572                             XtNfromVert, loggingStart,
06573                             NULL);
06574 
06575   loggingCancel =
06576     XtVaCreateManagedWidget("loggingCancel",
06577                             commandWidgetClass,
06578                             loggingForm,
06579                             XtNfromVert, loggingStart,
06580                             XtNfromHoriz, loggingDone,
06581                             NULL);
06582 
06583   XtAddCallback(loggingStart, XtNcallback, loggingStartCB, NULL);
06584   XtAddCallback(loggingStop, XtNcallback, loggingStopCB, NULL);
06585   XtAddCallback(loggingSave, XtNcallback, loggingSaveCB, NULL);
06586   XtAddCallback(loggingPlot, XtNcallback, loggingPlotCB, NULL);
06587   XtAddCallback(loggingDone, XtNcallback, loggingDoneCB, NULL);
06588   XtAddCallback(loggingCancel, XtNcallback, loggingCancelCB, NULL);
06589 
06590   helpXemcShell =
06591     XtVaCreatePopupShell("helpXemcShell",
06592                          topLevelShellWidgetClass,
06593                          topLevel,
06594                          XtNallowShellResize, True,
06595                          NULL);
06596 
06597   helpXemcForm =
06598     XtVaCreateManagedWidget("helpXemcForm",
06599                             formWidgetClass,
06600                             helpXemcShell,
06601                             NULL);
06602 
06603   helpXemcLabel =
06604     XtVaCreateManagedWidget("helpXemcLabel",
06605                             labelWidgetClass,
06606                             helpXemcForm,
06607                             NULL);
06608 
06609   helpXemcText =
06610     XtVaCreateManagedWidget("helpXemcText",
06611                             asciiTextWidgetClass,
06612                             helpXemcForm,
06613                             XtNfromVert, helpXemcLabel,
06614                             XtNeditType, XawtextRead,
06615                             XtNtype, XawAsciiFile,
06616                             XtNstring, "doc/xemc.txt",
06617                             XtNscrollVertical, XawtextScrollWhenNeeded,
06618                             XtNscrollHorizontal, XawtextScrollWhenNeeded,
06619                             NULL);
06620 
06621   helpXemcDone =
06622     XtVaCreateManagedWidget("helpXemcDone",
06623                             commandWidgetClass,
06624                             helpXemcForm,
06625                             XtNfromVert, helpXemcText,
06626                             NULL);
06627 
06628   XtAddCallback(helpXemcDone, XtNcallback, genericDoneCB, helpXemcShell);
06629 
06630   helpAboutShell =
06631     XtVaCreatePopupShell("helpAboutShell",
06632                          transientShellWidgetClass,
06633                          topLevel,
06634                          NULL);
06635 
06636   helpAboutDialog =
06637     XtVaCreateManagedWidget("helpAboutDialog",
06638                             dialogWidgetClass,
06639                             helpAboutShell,
06640                             NULL);
06641 
06642   helpAboutDone =
06643     XtVaCreateManagedWidget("helpAboutDone",
06644                             commandWidgetClass,
06645                             helpAboutDialog,
06646                             NULL);
06647 
06648   XtAddCallback(helpAboutDone, XtNcallback, genericDoneCB, helpAboutShell);
06649 
06650   toolNumberForm =
06651     XtVaCreateManagedWidget("toolNumberForm",
06652                             formWidgetClass,
06653                             topForm,
06654                             XtNfromVert, commandMenuForm,
06655                             NULL);
06656 
06657   toolNumberFormTitle =
06658     XtVaCreateManagedWidget("toolNumberFormTitle",
06659                             labelWidgetClass,
06660                             toolNumberForm,
06661                             NULL);
06662 
06663   toolNumberFormName =
06664     XtVaCreateManagedWidget("toolNumberFormName",
06665                             labelWidgetClass,
06666                             toolNumberForm,
06667                             XtNfromHoriz, toolNumberFormTitle,
06668                             NULL);
06669 
06670   toolOffsetForm =
06671     XtVaCreateManagedWidget("toolOffsetForm",
06672                             formWidgetClass,
06673                             topForm,
06674                             XtNfromVert, toolNumberForm,
06675                             NULL);
06676 
06677   toolOffsetFormTitle =
06678     XtVaCreateManagedWidget("toolOffsetFormTitle",
06679                             labelWidgetClass,
06680                             toolOffsetForm,
06681                             NULL);
06682 
06683   toolOffsetFormName =
06684     XtVaCreateManagedWidget("toolOffsetFormName",
06685                             labelWidgetClass,
06686                             toolOffsetForm,
06687                             XtNfromHoriz, toolOffsetFormTitle,
06688                             NULL);
06689 
06690   toolSetOffsetShell =
06691     XtVaCreatePopupShell("toolSetOffsetShell",
06692                          transientShellWidgetClass,
06693                          topLevel,
06694                          NULL);
06695 
06696   toolSetOffsetForm =
06697     XtVaCreateManagedWidget("toolSetOffsetForm",
06698                             formWidgetClass,
06699                             toolSetOffsetShell,
06700                             NULL);
06701 
06702   toolSetOffsetToolLabel =
06703     XtVaCreateManagedWidget("toolSetOffsetToolLabel",
06704                             labelWidgetClass,
06705                             toolSetOffsetForm,
06706                             XtNborderWidth, 0,
06707                             NULL);
06708 
06709   toolSetOffsetTool =
06710     XtVaCreateManagedWidget("toolSetOffsetTool",
06711                             asciiTextWidgetClass,
06712                             toolSetOffsetForm,
06713                             XtNfromHoriz, toolSetOffsetToolLabel,
06714                             XtNeditType, XawtextEdit,
06715                             NULL);
06716 
06717   toolSetOffsetLengthLabel =
06718     XtVaCreateManagedWidget("toolSetOffsetLengthLabel",
06719                             labelWidgetClass,
06720                             toolSetOffsetForm,
06721                             XtNfromVert, toolSetOffsetToolLabel,
06722                             XtNborderWidth, 0,
06723                             NULL);
06724 
06725   toolSetOffsetLength =
06726     XtVaCreateManagedWidget("toolSetOffsetLength",
06727                             asciiTextWidgetClass,
06728                             toolSetOffsetForm,
06729                             XtNfromHoriz, toolSetOffsetLengthLabel,
06730                             XtNfromVert, toolSetOffsetToolLabel,
06731                             XtNeditType, XawtextEdit,
06732                             NULL);
06733 
06734   toolSetOffsetDiameterLabel =
06735     XtVaCreateManagedWidget("toolSetOffsetDiameterLabel",
06736                             labelWidgetClass,
06737                             toolSetOffsetForm,
06738                             XtNfromVert, toolSetOffsetLengthLabel,
06739                             XtNborderWidth, 0,
06740                             NULL);
06741 
06742   toolSetOffsetDiameter =
06743     XtVaCreateManagedWidget("toolSetOffsetDiameter",
06744                             asciiTextWidgetClass,
06745                             toolSetOffsetForm,
06746                             XtNfromHoriz, toolSetOffsetDiameterLabel,
06747                             XtNfromVert, toolSetOffsetLengthLabel,
06748                             XtNeditType, XawtextEdit,
06749                             NULL);
06750 
06751   toolSetOffsetDone =
06752     XtVaCreateManagedWidget("toolSetOffsetDone",
06753                             commandWidgetClass,
06754                             toolSetOffsetForm,
06755                             XtNfromVert, toolSetOffsetDiameterLabel,
06756                             NULL);
06757 
06758   toolSetOffsetCancel =
06759     XtVaCreateManagedWidget("toolSetOffsetCancel",
06760                             commandWidgetClass,
06761                             toolSetOffsetForm,
06762                             XtNfromVert, toolSetOffsetDiameterLabel,
06763                             XtNfromHoriz, toolSetOffsetDone,
06764                             NULL);
06765 
06766   XtAddCallback(toolSetOffsetDone, XtNcallback, toolSetOffsetDoneCB, NULL);
06767   XtAddCallback(toolSetOffsetCancel, XtNcallback, toolSetOffsetCancelCB, NULL);
06768 
06769   positionTypeForm =
06770     XtVaCreateManagedWidget("positionTypeForm",
06771                             formWidgetClass,
06772                             topForm,
06773                             XtNfromVert, commandMenuForm,
06774                             XtNfromHoriz, toolNumberForm,
06775                             NULL);
06776 
06777   positionTypeFormTitle =
06778     XtVaCreateManagedWidget("positionTypeFormTitle",
06779                             labelWidgetClass,
06780                             positionTypeForm,
06781                             NULL);
06782 
06783   positionTypeFormName =
06784     XtVaCreateManagedWidget("positionTypeFormName",
06785                             labelWidgetClass,
06786                             positionTypeForm,
06787                             XtNfromHoriz, positionTypeFormTitle,
06788                             NULL);
06789 
06790   workOffsetForm =
06791     XtVaCreateManagedWidget("workOffsetForm",
06792                             formWidgetClass,
06793                             topForm,
06794                             XtNfromVert, positionTypeForm,
06795                             XtNfromHoriz, toolNumberForm,
06796                             NULL);
06797 
06798   workOffsetFormTitle =
06799     XtVaCreateManagedWidget("workOffsetFormTitle",
06800                             labelWidgetClass,
06801                             workOffsetForm,
06802                             NULL);
06803 
06804   workOffsetFormName =
06805     XtVaCreateManagedWidget("workOffsetFormName",
06806                             labelWidgetClass,
06807                             workOffsetForm,
06808                             XtNfromHoriz, workOffsetFormTitle,
06809                             NULL);
06810 
06811   // set up position labels
06812 
06813   // first get the number we'll need-- must hold both joints and
06814   // marked Cartesian coordinates
06815   numPosLabels = numCoords > numJoints ? numCoords : numJoints;
06816 
06817   // create the first pos label manually, and set the next ones to be
06818   // positioned underneath the previous one
06819   posLabel[0] =
06820     XtVaCreateManagedWidget("posLabel",
06821                             labelWidgetClass,
06822                             topForm,
06823                             XtNfromVert, toolOffsetForm,
06824                             NULL);
06825   // get the width, for aligning the abort button
06826   XtVaGetValues(posLabel[0],
06827                 XtNwidth, &posw,
06828                 NULL);
06829 
06830   // do the other labels
06831   for (t = 1; t < numPosLabels; t++) {
06832     posLabel[t] =
06833       XtVaCreateManagedWidget("posLabel",
06834                               labelWidgetClass,
06835                               topForm,
06836                               XtNfromVert, posLabel[t-1],
06837                               NULL);
06838   }
06839 
06840   abortCommand =
06841     XtVaCreateManagedWidget("abortCommand",
06842                             commandWidgetClass,
06843                             commandMenuForm,
06844                             XtNheight, sh + cmfbw + cmfbw + bh,
06845                             XtNwidth, posw - (bw + mw + stw + 8 * cmfbw),
06846                             XtNfromHoriz, spindleIncLabel,
06847                             NULL);
06848 
06849   XtAddCallback(abortCommand, XtNcallback, abortCB, NULL);
06850 
06851   posOffsetShell =
06852     XtVaCreatePopupShell("posOffsetShell",
06853                          transientShellWidgetClass,
06854                          topLevel,
06855                          NULL);
06856 
06857   posOffsetDialog =
06858     XtVaCreateManagedWidget("posOffsetDialog",
06859                             dialogWidgetClass,
06860                             posOffsetShell,
06861                             NULL);
06862 
06863   jogSpeedForm =
06864     XtVaCreateManagedWidget("jogSpeedForm",
06865                             formWidgetClass,
06866                             topForm,
06867                             XtNfromVert, posLabel[numPosLabels - 1],
06868                             NULL);
06869 
06870   jogSpeedTitleLabel =
06871     XtVaCreateManagedWidget("jogSpeedTitleLabel",
06872                             labelWidgetClass,
06873                             jogSpeedForm,
06874                             NULL);
06875 
06876   jogSpeedDecLabel =
06877     XtVaCreateManagedWidget("jogSpeedDecLabel",
06878                             labelWidgetClass,
06879                             jogSpeedForm,
06880                             XtNfromVert, jogSpeedTitleLabel,
06881                             NULL);
06882 
06883   jogSpeedLabel =
06884     XtVaCreateManagedWidget("jogSpeedLabel",
06885                             labelWidgetClass,
06886                             jogSpeedForm,
06887                             XtNfromHoriz, jogSpeedDecLabel,
06888                             XtNfromVert, jogSpeedTitleLabel,
06889                             NULL);
06890 
06891   jogSpeedIncLabel =
06892     XtVaCreateManagedWidget("jogSpeedIncLabel",
06893                             labelWidgetClass,
06894                             jogSpeedForm,
06895                             XtNfromHoriz, jogSpeedLabel,
06896                             XtNfromVert, jogSpeedTitleLabel,
06897                             NULL);
06898 
06899   jogSpeedShell =
06900     XtVaCreatePopupShell("jogSpeedShell",
06901                          transientShellWidgetClass,
06902                          topLevel,
06903                          NULL);
06904 
06905   jogSpeedDialog =
06906     XtVaCreateManagedWidget("jogSpeedDialog",
06907                             dialogWidgetClass,
06908                             jogSpeedShell,
06909                             NULL);
06910 
06911   jogIncrementForm =
06912     XtVaCreateManagedWidget("jogIncrementForm",
06913                             formWidgetClass,
06914                             topForm,
06915                             XtNfromHoriz, jogSpeedForm,
06916                             XtNfromVert, posLabel[numPosLabels - 1],
06917                             NULL);
06918 
06919   jogIncrementTitleLabel =
06920     XtVaCreateManagedWidget("jogIncrementTitleLabel",
06921                             labelWidgetClass,
06922                             jogIncrementForm,
06923                             NULL);
06924 
06925   setupMenu(&jogIncrementMenu, "jogIncrementMenu",
06926             jogIncrementMenuEntryNames,
06927             jogIncrementForm,
06928             NULL, jogIncrementTitleLabel,
06929             jogIncrementMenuSelect);
06930 
06931   jogForm =
06932     XtVaCreateManagedWidget("jogForm",
06933                             formWidgetClass,
06934                             topForm,
06935                             XtNfromHoriz, jogIncrementForm,
06936                             XtNfromVert, posLabel[numPosLabels - 1],
06937                             NULL);
06938 
06939   jogTitleLabel =
06940     XtVaCreateManagedWidget("jogTitleLabel",
06941                             labelWidgetClass,
06942                             jogForm,
06943                             NULL);
06944 
06945   jogMinusLabel =
06946     XtVaCreateManagedWidget("jogMinusLabel",
06947                             labelWidgetClass,
06948                             jogForm,
06949                             XtNfromVert, jogTitleLabel,
06950                             NULL);
06951 
06952   homeCommand =
06953     XtVaCreateManagedWidget("homeCommand",
06954                             commandWidgetClass,
06955                             jogForm,
06956                             XtNfromHoriz, jogMinusLabel,
06957                             XtNfromVert, jogTitleLabel,
06958                             NULL);
06959 
06960   XtAddCallback(homeCommand, XtNcallback, homeCB, 0);
06961 
06962   jogPlusLabel =
06963     XtVaCreateManagedWidget("jogPlusLabel",
06964                             labelWidgetClass,
06965                             jogForm,
06966                             XtNfromHoriz, homeCommand,
06967                             XtNfromVert, jogTitleLabel,
06968                             NULL);
06969 
06970   feedOverrideForm =
06971     XtVaCreateManagedWidget("feedOverrideForm",
06972                             formWidgetClass,
06973                             topForm,
06974                             XtNfromHoriz, jogForm,
06975                             XtNfromVert, posLabel[numPosLabels - 1],
06976                             NULL);
06977 
06978   feedOverrideTitleLabel =
06979     XtVaCreateManagedWidget("feedOverrideTitleLabel",
06980                             labelWidgetClass,
06981                             feedOverrideForm,
06982                             NULL);
06983 
06984   feedOverrideDecLabel =
06985     XtVaCreateManagedWidget("feedOverrideDecLabel",
06986                             labelWidgetClass,
06987                             feedOverrideForm,
06988                             XtNfromVert, feedOverrideTitleLabel,
06989                             NULL);
06990 
06991   feedOverrideLabel =
06992     XtVaCreateManagedWidget("feedOverrideLabel",
06993                             labelWidgetClass,
06994                             feedOverrideForm,
06995                             XtNfromHoriz, feedOverrideDecLabel,
06996                             XtNfromVert, feedOverrideTitleLabel,
06997                             NULL);
06998 
06999   feedOverrideIncLabel =
07000     XtVaCreateManagedWidget("feedOverrideIncLabel",
07001                             labelWidgetClass,
07002                             feedOverrideForm,
07003                             XtNfromHoriz, feedOverrideLabel,
07004                             XtNfromVert, feedOverrideTitleLabel,
07005                             NULL);
07006 
07007   feedOverrideShell =
07008     XtVaCreatePopupShell("feedOverrideShell",
07009                          transientShellWidgetClass,
07010                          topLevel,
07011                          NULL);
07012 
07013   feedOverrideDialog =
07014     XtVaCreateManagedWidget("feedOverrideDialog",
07015                             dialogWidgetClass,
07016                             feedOverrideShell,
07017                             NULL);
07018 
07019   loggingStatusForm =
07020     XtVaCreateManagedWidget("loggingStatusForm",
07021                             formWidgetClass,
07022                             topForm,
07023                             XtNfromHoriz, feedOverrideForm,
07024                             XtNfromVert, posLabel[numPosLabels - 1],
07025                             NULL);
07026 
07027   loggingStatusTitleLabel =
07028     XtVaCreateManagedWidget("loggingStatusTitleLabel",
07029                             labelWidgetClass,
07030                             loggingStatusForm,
07031                             NULL);
07032 
07033   loggingStatusOpenLabel =
07034     XtVaCreateManagedWidget("loggingStatusOpenLabel",
07035                             labelWidgetClass,
07036                             loggingStatusForm,
07037                             XtNfromVert, loggingStatusTitleLabel,
07038                             NULL);
07039 
07040   loggingStatusStartedLabel =
07041     XtVaCreateManagedWidget("loggingStatusStartedLabel",
07042                             labelWidgetClass,
07043                             loggingStatusForm,
07044                             XtNfromHoriz, loggingStatusOpenLabel,
07045                             XtNfromVert, loggingStatusTitleLabel,
07046                             NULL);
07047 
07048   loggingStatusPointsLabel =
07049     XtVaCreateManagedWidget("loggingStatusPointsLabel",
07050                             labelWidgetClass,
07051                             loggingStatusForm,
07052                             XtNfromHoriz, loggingStatusStartedLabel,
07053                             XtNfromVert, loggingStatusTitleLabel,
07054                             NULL);
07055 
07056   mdiForm =
07057     XtVaCreateManagedWidget("mdiForm",
07058                             formWidgetClass,
07059                             topForm,
07060                             XtNfromVert, jogSpeedForm,
07061                             NULL);
07062 
07063   mdiFormTitle =
07064     XtVaCreateManagedWidget("mdiFormTitle",
07065                             labelWidgetClass,
07066                             mdiForm,
07067                             NULL);
07068 
07069   mdiFormText =
07070     XtVaCreateManagedWidget("mdiFormText",
07071                             asciiTextWidgetClass,
07072                             mdiForm,
07073                             XtNfromHoriz, mdiFormTitle,
07074                             XtNeditType, XawtextEdit,
07075                             NULL);
07076 
07077   mdiCodesLabel =
07078     XtVaCreateManagedWidget("mdiCodesLabel",
07079                             labelWidgetClass,
07080                             topForm,
07081                             XtNfromVert, mdiForm,
07082                             NULL);
07083 
07084   programForm =
07085     XtVaCreateManagedWidget("programForm",
07086                             formWidgetClass,
07087                             topForm,
07088                             XtNfromVert, mdiCodesLabel,
07089                             NULL);
07090 
07091   programFormTitle =
07092     XtVaCreateManagedWidget("programFormTitle",
07093                             labelWidgetClass,
07094                             programForm,
07095                             NULL);
07096 
07097   programFormName =
07098     XtVaCreateManagedWidget("programFormName",
07099                             labelWidgetClass,
07100                             programForm,
07101                             XtNfromHoriz, programFormTitle,
07102                             NULL);
07103 
07104   programFormStateTitle =
07105     XtVaCreateManagedWidget("programFormStateTitle",
07106                             labelWidgetClass,
07107                             programForm,
07108                             XtNfromHoriz, programFormName,
07109                             NULL);
07110 
07111   programFormState =
07112     XtVaCreateManagedWidget("programFormState",
07113                             labelWidgetClass,
07114                             programForm,
07115                             XtNfromHoriz, programFormStateTitle,
07116                             NULL);
07117 
07118   programOpenCommand =
07119     XtVaCreateManagedWidget("programOpenCommand",
07120                             commandWidgetClass,
07121                             programForm,
07122                             XtNfromVert, programFormTitle,
07123                             NULL);
07124 
07125   XtAddCallback(programOpenCommand, XtNcallback, dialogPopup, fileOpenShell);
07126 
07127   programRunCommand =
07128     XtVaCreateManagedWidget("programRunCommand",
07129                             commandWidgetClass,
07130                             programForm,
07131                             XtNfromHoriz, programOpenCommand,
07132                             XtNfromVert, programFormTitle,
07133                             NULL);
07134 
07135   XtAddCallback(programRunCommand, XtNcallback, programRunCB, NULL);
07136 
07137   programPauseCommand =
07138     XtVaCreateManagedWidget("programPauseCommand",
07139                             commandWidgetClass,
07140                             programForm,
07141                             XtNfromHoriz, programRunCommand,
07142                             XtNfromVert, programFormTitle,
07143                             NULL);
07144 
07145   XtAddCallback(programPauseCommand, XtNcallback, programPauseCB, NULL);
07146 
07147   programResumeCommand =
07148     XtVaCreateManagedWidget("programResumeCommand",
07149                             commandWidgetClass,
07150                             programForm,
07151                             XtNfromHoriz, programPauseCommand,
07152                             XtNfromVert, programFormTitle,
07153                             NULL);
07154 
07155   XtAddCallback(programResumeCommand, XtNcallback, programResumeCB, NULL);
07156 
07157   programStepCommand =
07158     XtVaCreateManagedWidget("programStepCommand",
07159                             commandWidgetClass,
07160                             programForm,
07161                             XtNfromHoriz, programResumeCommand,
07162                             XtNfromVert, programFormTitle,
07163                             NULL);
07164 
07165   XtAddCallback(programStepCommand, XtNcallback, programStepCB, NULL);
07166 
07167   programVerifyCommand =
07168     XtVaCreateManagedWidget("programVerifyCommand",
07169                             commandWidgetClass,
07170                             programForm,
07171                             XtNfromHoriz, programStepCommand,
07172                             XtNfromVert, programFormTitle,
07173                             NULL);
07174 
07175   XtAddCallback(programVerifyCommand, XtNcallback, programVerifyCB, NULL);
07176 
07177   programText =
07178     XtVaCreateManagedWidget("programText",
07179                             asciiTextWidgetClass,
07180                             topForm,
07181                             XtNfromVert, programForm,
07182                             NULL);
07183 
07184   // add actions table for all action functions
07185   XtAppAddActions(app_context, actionsTable, XtNumber(actionsTable));
07186 
07187   // create windows for widgets and map them
07188   XtRealizeWidget(topLevel);
07189 
07190   // init atom to catch window kills
07191   killAtom = XInternAtom(XtDisplay(topLevel), "WM_DELETE_WINDOW", False);
07192 
07193   // initialize hard-coded colors
07194   stringToPixel(topForm, "black", &pixelBlack);
07195   stringToPixel(topForm, "red", &pixelRed);
07196   stringToPixel(topForm, "yellow", &pixelYellow);
07197   stringToPixel(topForm, "green", &pixelGreen);
07198 
07199   // initialize joint frame items
07200   for (t = 0; t < numJoints; t++) {
07201     // initialize diagnostics ferrors
07202     oldAxisFerror[t] = -1.0;
07203   }
07204 
07205   // initialize position label items
07206   for (t = 0; t < numPosLabels; t++) {
07207     // get position label background and border colors for toggling
07208     getColor(posLabel[t], &posLabelBackground[t], 0);
07209     getBorderColor(posLabel[t], &posLabelBorderColor[t]);
07210     // initialize pos label colors
07211     posColor[t] = 0;
07212     // initialize label values
07213     newPosLabelValue[t] = 0.0;
07214     oldPosLabelValue[t] = DBL_MAX; // forces an update
07215   }
07216 
07217   // get border color for dialog buttons, for de-highlighting
07218 
07219   getBorderColor(fileOpenDialog, &fileOpenBorderColor);
07220   setBorderColor(fileOpenDone, pixelRed);
07221 
07222   getBorderColor(fileEditDialog, &fileEditBorderColor);
07223   setBorderColor(fileEditDone, pixelRed);
07224 
07225   getBorderColor(fileQuitDialog, &fileQuitBorderColor);
07226   setBorderColor(fileQuitDone, pixelRed);
07227 
07228   getBorderColor(toolSetOffsetForm, &toolSetOffsetFormBorderColor);
07229   setBorderColor(toolSetOffsetDone, pixelRed);
07230 
07231   getBorderColor(calibForm, &calibFormBorderColor);
07232   setBorderColor(calibDone, pixelRed);
07233 
07234   getBorderColor(loggingForm, &loggingFormBorderColor);
07235   setBorderColor(loggingDone, pixelRed);
07236 
07237   // set labels for dynamic labels we can't init in timeoutCB
07238   sprintf(string, "%d", jogSpeed);
07239   setLabel(jogSpeedLabel, string);
07240 
07241   // start X interval timer
07242   XtAppAddTimeOut(app_context, UPDATE_MSECS, timeoutCB, NULL);
07243 
07244   // trap window kill for top level
07245   XSetWMProtocols(XtDisplay(topLevel), XtWindow(topLevel), &killAtom, 1);
07246 
07247   // loop for events
07248   XtAppMainLoop(app_context);
07249 
07250   return 0;
07251 }

Generated on Sun Dec 2 15:27:45 2001 for EMC by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001