Finally got around to fixing the "logcommands" command, which has
been broken ever since moving to the Tcl/Tk wrapped version. Added some new features that allow background commands from the window handling (like pointer tracking) to be omitted from the log file via a suspend/resume function. Added a header file and a few commands at the top of the log file that align the log file contents with the screen and box state at the start of logging. This makes a log file which can be "played back" by sourcing it from the magic console prompt. Per request from Harald Pretl.
This commit is contained in:
parent
ca469510d5
commit
c8a2d06e08
|
|
@ -20,10 +20,20 @@
|
|||
|
||||
<H2>logcommands</H2>
|
||||
<HR>
|
||||
Log all commands into a file
|
||||
Log all commands and mouse button actions into a file
|
||||
<HR>
|
||||
|
||||
<H3>Usage:</H3>
|
||||
<BLOCKQUOTE>
|
||||
<B>logcommands</B> <I>option</I> [<I>file</I>] <BR><BR>
|
||||
<BLOCKQUOTE>
|
||||
where <I>option</I> is one of: <B>start</B>, <B>stop</B>,
|
||||
<B>update</B>, <B>suspend</B>, or <B>resume</B>, and
|
||||
<I>file</I> is the name of the log file to write to.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
or (legacy usage):
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<B>logcommands</B> [<I>file</I> [<B>update</B>]] <BR><BR>
|
||||
<BLOCKQUOTE>
|
||||
|
|
@ -33,10 +43,53 @@ Log all commands into a file
|
|||
|
||||
<H3>Summary:</H3>
|
||||
<BLOCKQUOTE>
|
||||
The <B>logcommands</B> command tells magic to write all
|
||||
command-line commands and button pushes to the log file
|
||||
named <I>file</I>. If <B>update</B> is specified, a
|
||||
screen update is generated after each command executes.
|
||||
The <B>logcommands</B> command creates and manages a file
|
||||
containing all of the command-line commands and button actions
|
||||
as they occur while file writing is active. This creates a
|
||||
recording of the layout session which can be "played back" by
|
||||
sourcing the log file. Behavior is controlled by one of the
|
||||
command options, as follows:
|
||||
<DL>
|
||||
<DT><B>start</B> <I>filename</I>
|
||||
<DD> This opens the log file named <I>filename</I>, writes
|
||||
a header and issues a few rudimentary commands to
|
||||
align the file with the current window size and zoom
|
||||
factor, and the cursor box position. Then it starts
|
||||
recording commands, not including the <B>logcommands</B>
|
||||
command itself.
|
||||
<DT><B>stop</B>
|
||||
<DD> This command closes any open log file and stops recording
|
||||
commands.
|
||||
<DT><B>suspend</B>
|
||||
<DD> This command stops recording commands until the
|
||||
<B>logcommands resume</B> command is issued, without
|
||||
ending or closing the file. This is used by the wrapper
|
||||
script code to prevent some commands such as those that
|
||||
track pointer movement from being added to the log file.
|
||||
<DT><B>resume</B>
|
||||
<DD> This command resumes recording after it has been suspended.
|
||||
<DT><B>update</B>
|
||||
<DD> This command sets a flag that issues a display update
|
||||
command after every command recorded in the log file.
|
||||
This usage is largely deprecated, since sourcing the
|
||||
log file for playback will refresh the display as usual.
|
||||
</DL>
|
||||
|
||||
The legacy syntax "<B>logcommands</B> [<I>file</I> [<B>update</B>]]"
|
||||
will open a new command log file if <I>file</I> is given, optionally
|
||||
with the "update" feature (see above) if the <B>update</B> keyword
|
||||
is added. With no arguments, the log file is ended and closed.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3>Caveats:</H3>
|
||||
<BLOCKQUOTE>
|
||||
The initial header and setup in the log file is rudimentary. It
|
||||
will not attempt to load a technology file, load a layout, or
|
||||
edit some part of a layout to match what is in the layout window
|
||||
at the time that the log file was created. The best usage is to
|
||||
start the log file immediately after starting magic, and only
|
||||
play back the log file in the tech file environment in which it
|
||||
was created.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3>Implementation Notes:</H3>
|
||||
|
|
|
|||
|
|
@ -243,10 +243,14 @@ proc magic::drcupdate { option } {
|
|||
}
|
||||
|
||||
proc magic::drcstate { status } {
|
||||
logcommands suspend
|
||||
set winlist [*bypass windownames layout]
|
||||
foreach lwin $winlist {
|
||||
set framename [winfo parent $lwin]
|
||||
if {$framename == "."} {return}
|
||||
if {$framename == "."} {
|
||||
logcommands resume
|
||||
return
|
||||
}
|
||||
switch $status {
|
||||
idle {
|
||||
set dct [*bypass drc list count total]
|
||||
|
|
@ -260,6 +264,7 @@ proc magic::drcstate { status } {
|
|||
busy { ${framename}.titlebar.drcbutton configure -selectcolor yellow }
|
||||
}
|
||||
}
|
||||
logcommands resume
|
||||
}
|
||||
|
||||
# Create the menu of windows. This is kept separate from the cell manager,
|
||||
|
|
@ -502,6 +507,7 @@ proc magic::captions {{subcommand {}}} {
|
|||
if {$subcommand != {} && $subcommand != "writeable" && $subcommand != "load"} {
|
||||
return
|
||||
}
|
||||
logcommands suspend
|
||||
set winlist [magic::windownames layout]
|
||||
foreach winpath $winlist {
|
||||
set framename [winfo parent $winpath]
|
||||
|
|
@ -521,6 +527,7 @@ proc magic::captions {{subcommand {}}} {
|
|||
"Loaded: ${subcaption1} Editing: ${subcaption2} Tool: $Opts(tool) \
|
||||
Technology: ${techname}"
|
||||
}
|
||||
logcommands resume
|
||||
}
|
||||
|
||||
# Allow captioning in the title window by tagging the "load" and "edit" commands
|
||||
|
|
@ -655,8 +662,12 @@ proc magic::cursorview {win} {
|
|||
if {$win == {}} {
|
||||
return
|
||||
}
|
||||
logcommands suspend
|
||||
set framename [winfo parent $win]
|
||||
if {[catch {set cr [*bypass cif scale out]}]} {return}
|
||||
if {[catch {set cr [*bypass cif scale out]}]} {
|
||||
logcommands resume
|
||||
return
|
||||
}
|
||||
if {$cr == 0} {return}
|
||||
set olst [${win} cursor internal]
|
||||
|
||||
|
|
@ -671,7 +682,10 @@ proc magic::cursorview {win} {
|
|||
if {[catch {
|
||||
set olstx [expr {$olstx * $cr}]
|
||||
set olsty [expr {$olsty * $cr}]
|
||||
}]} {return}
|
||||
}]} {
|
||||
logcommands resume
|
||||
return
|
||||
}
|
||||
|
||||
if {[${win} box exists]} {
|
||||
set dlst [${win} box position]
|
||||
|
|
@ -685,20 +699,24 @@ proc magic::cursorview {win} {
|
|||
set titletext [format "(%+g %+g) microns" $olstx $olsty]
|
||||
${framename}.titlebar.pos configure -text $titletext
|
||||
}
|
||||
logcommands resume
|
||||
}
|
||||
|
||||
proc magic::toolupdate {win {yesno "yes"} {layerlist "none"}} {
|
||||
global Winopts
|
||||
|
||||
if {[magic::display] == "NULL"} {return}
|
||||
logcommands suspend
|
||||
if {$win == {}} {
|
||||
set win [magic::windownames]
|
||||
}
|
||||
|
||||
# Wind3d has a "see" function, so make sure this is not a 3d window
|
||||
if {$win == [magic::windownames wind3d]} {
|
||||
logcommands resume
|
||||
return
|
||||
}
|
||||
logcommands resume
|
||||
|
||||
set topname [winfo toplevel $win]
|
||||
set framename [winfo parent $win]
|
||||
|
|
@ -939,11 +957,15 @@ proc magic::techrebuild {winpath {cmdstr ""}} {
|
|||
proc magic::setscrollvalues {win} {
|
||||
global Opts
|
||||
|
||||
logcommands suspend
|
||||
set svalues [${win} view get]
|
||||
set bvalues [${win} view bbox]
|
||||
|
||||
set framename [winfo parent ${win}]
|
||||
if {$framename == "."} {return}
|
||||
if {$framename == "."} {
|
||||
logcommands resume
|
||||
return
|
||||
}
|
||||
|
||||
set bwidth [expr {[lindex $bvalues 2] - [lindex $bvalues 0]}]
|
||||
set bheight [expr {[lindex $bvalues 3] - [lindex $bvalues 1]}]
|
||||
|
|
@ -985,6 +1007,7 @@ proc magic::setscrollvalues {win} {
|
|||
|
||||
proc magic::scrollupdate {win} {
|
||||
|
||||
logcommands suspend
|
||||
if {[magic::display] == "NULL"} {return}
|
||||
if {[info level] <= 1} {
|
||||
|
||||
|
|
@ -1001,6 +1024,7 @@ proc magic::scrollupdate {win} {
|
|||
magic::setscrollvalues $win
|
||||
}
|
||||
}
|
||||
logcommands resume
|
||||
}
|
||||
|
||||
# scrollview: update the magic display to match the
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ extern unsigned char TxInputRedirect;
|
|||
|
||||
#endif
|
||||
|
||||
#define TX_LOG_UPDATE 1 /* Update display after every log command */
|
||||
#define TX_LOG_SUSPEND 2 /* Suspend output logging */
|
||||
|
||||
extern int TxCurButtons;
|
||||
|
||||
/* These should really be defined by the application, not hard-coded */
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/t
|
|||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "tcltk/tclmagic.h"
|
||||
#include "utils/magsgtty.h"
|
||||
|
|
@ -614,11 +615,11 @@ TxClearPoint()
|
|||
}
|
||||
|
||||
static FILE *txLogFile = NULL;
|
||||
bool txLogUpdate;
|
||||
unsigned char txLogFlags;
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* TxLogCommands --
|
||||
* TxLogStart --
|
||||
*
|
||||
* Log all further commands to the given file name. If the file is NULL,
|
||||
* turn off logging.
|
||||
|
|
@ -632,21 +633,165 @@ bool txLogUpdate;
|
|||
*/
|
||||
|
||||
void
|
||||
TxLogCommands(fileName, update)
|
||||
TxLogStart(fileName, mw)
|
||||
char *fileName;
|
||||
bool update; /* Request a screen update after each command */
|
||||
MagWindow *mw; /* Window commands are logged from */
|
||||
{
|
||||
if (txLogFile != NULL)
|
||||
{
|
||||
(void) fclose(txLogFile);
|
||||
txLogFile = NULL;
|
||||
TxError("There is already a log file (%s) open!\n", txLogFile);
|
||||
return;
|
||||
}
|
||||
if (fileName == NULL) return;
|
||||
|
||||
txLogUpdate = update;
|
||||
txLogFlags = 0;
|
||||
txLogFile = fopen(fileName, "w");
|
||||
if (txLogFile == NULL)
|
||||
TxError("Could not open file '%s' for writing.\n", fileName);
|
||||
else
|
||||
{
|
||||
time_t t_stamp = time((time_t *)NULL);
|
||||
struct tm *clock = localtime(&t_stamp);
|
||||
char *now = ctime(&t_stamp);
|
||||
|
||||
TxPrintf("Logging commands to file \"%s\"\n", fileName);
|
||||
/* Write comment line header into command file and log the current
|
||||
* window view position so that cursor positions in the file match
|
||||
* the layout. If the cursor box is defined, then issue a "box
|
||||
* values" command so that relative box adjustments are correct.
|
||||
*/
|
||||
#ifdef MAGIC_WRAPPER
|
||||
fprintf(txLogFile, "# Magic command log file\n");
|
||||
fprintf(txLogFile, "# Using technology: %s\n", DBTechName);
|
||||
if (mw != NULL)
|
||||
fprintf(txLogFile, "# Title: %s\n", mw->w_caption);
|
||||
fprintf(txLogFile, "# Date: %s", now);
|
||||
#endif
|
||||
if (mw != NULL)
|
||||
{
|
||||
CellDef *rootBoxDef;
|
||||
Rect rootBox;
|
||||
|
||||
#ifndef MAGIC_WRAPPER
|
||||
// Colon preceeds commands in the non-Tcl verson of the log file.
|
||||
fprintf(txLogFile, ":");
|
||||
#endif
|
||||
fprintf(txLogFile, "view %di %di %di %di\n",
|
||||
mw->w_surfaceArea.r_xbot, mw->w_surfaceArea.r_ybot,
|
||||
mw->w_surfaceArea.r_xtop, mw->w_surfaceArea.r_ytop);
|
||||
if (ToolGetBox(&rootBoxDef, &rootBox))
|
||||
{
|
||||
fprintf(txLogFile, "box values %di %di %di %di\n",
|
||||
rootBox.r_xbot, rootBox.r_ybot,
|
||||
rootBox.r_xtop, rootBox.r_ytop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* TxLogStop --
|
||||
*
|
||||
* Turn off logging.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* File IO.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
TxLogStop()
|
||||
{
|
||||
if (txLogFile != NULL)
|
||||
{
|
||||
TxPrintf("Ending command logging to file.\n");
|
||||
fclose(txLogFile);
|
||||
txLogFile = NULL;
|
||||
txLogFlags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* TxLogUpdate --
|
||||
*
|
||||
* Set the log file flags to force a display refresh after logged commands
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* File IO.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
TxLogUpdate()
|
||||
{
|
||||
if (txLogFile == NULL)
|
||||
{
|
||||
TxError("There is no log file to set an update flag on.\n");
|
||||
return;
|
||||
}
|
||||
if (txLogFlags & TX_LOG_UPDATE)
|
||||
{
|
||||
txLogFlags &= ~TX_LOG_UPDATE;
|
||||
TxPrintf("No display refresh after logged commands.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
txLogFlags |= TX_LOG_UPDATE;
|
||||
TxPrintf("Forcing display refresh after logged commands.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* TxLogSuspend --
|
||||
*
|
||||
* Suspend command logging
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* File IO.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
TxLogSuspend()
|
||||
{
|
||||
if (txLogFile == NULL)
|
||||
return;
|
||||
|
||||
txLogFlags |= TX_LOG_SUSPEND;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* TxLogResume --
|
||||
*
|
||||
* Resume command logging
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* File IO.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
TxLogResume()
|
||||
{
|
||||
if (txLogFile == NULL)
|
||||
return;
|
||||
|
||||
txLogFlags &= ~TX_LOG_SUSPEND;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -681,25 +826,61 @@ txLogCommand(cmd)
|
|||
0
|
||||
};
|
||||
|
||||
#ifdef MAGIC_WRAPPER
|
||||
char *pfix = "";
|
||||
#else
|
||||
char *pfix = ":";
|
||||
#endif
|
||||
|
||||
/* Do not do anything if there is no log file */
|
||||
if (txLogFile == (FILE *) NULL) return;
|
||||
|
||||
if (cmd->tx_wid >= 0) {
|
||||
/* Command has a window associated with it. */
|
||||
fprintf(txLogFile, ":setpoint %d %d %d\n",
|
||||
cmd->tx_p.p_x, cmd->tx_p.p_y, cmd->tx_wid);
|
||||
} else {
|
||||
/* No window associated with the command. */
|
||||
fprintf(txLogFile, ":setpoint %d %d\n",
|
||||
cmd->tx_p.p_x, cmd->tx_p.p_y);
|
||||
}
|
||||
/* Do not write anything if the log file is suspended */
|
||||
if (txLogFlags & TX_LOG_SUSPEND) return;
|
||||
|
||||
if (cmd->tx_argc > 0)
|
||||
{
|
||||
int i;
|
||||
fprintf(txLogFile, ":%s", cmd->tx_argv[0]);
|
||||
char *postns;
|
||||
|
||||
/* Do not output "logcommand" commands to the log file.
|
||||
* Do not output "*bypass" commands to the log file.
|
||||
*/
|
||||
postns = strstr(cmd->tx_argv[0], "::");
|
||||
if (postns == NULL)
|
||||
postns = cmd->tx_argv[0];
|
||||
else
|
||||
postns += 2;
|
||||
|
||||
if (!strncmp(postns, "logc", 4))
|
||||
return;
|
||||
else if (!strcmp(postns, "*bypass"))
|
||||
return;
|
||||
|
||||
/* Commands ending in "cursor" should be preceeded by a set point */
|
||||
/* to indicate where the pointer was at the time of the command. */
|
||||
|
||||
if (!strcmp(cmd->tx_argv[cmd->tx_argc - 1], "cursor"))
|
||||
{
|
||||
if (cmd->tx_wid >= 0)
|
||||
{
|
||||
/* Command has a window associated with it. */
|
||||
fprintf(txLogFile, "%ssetpoint %d %d %d\n",
|
||||
pfix, cmd->tx_p.p_x, cmd->tx_p.p_y, cmd->tx_wid);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No window associated with the command. */
|
||||
fprintf(txLogFile, "%ssetpoint %d %d\n",
|
||||
pfix, cmd->tx_p.p_x, cmd->tx_p.p_y);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(postns, "setpoint")) return;
|
||||
|
||||
fprintf(txLogFile, "%s%s", pfix, cmd->tx_argv[0]);
|
||||
for (i = 1; i < cmd->tx_argc; i++)
|
||||
{
|
||||
fprintf(txLogFile, " '%s'", cmd->tx_argv[i]);
|
||||
fprintf(txLogFile, " %s", cmd->tx_argv[i]);
|
||||
}
|
||||
fprintf(txLogFile, "\n");
|
||||
}
|
||||
|
|
@ -722,12 +903,13 @@ txLogCommand(cmd)
|
|||
default: {ASSERT(FALSE, "txLogCommand"); break; };
|
||||
}
|
||||
|
||||
fprintf(txLogFile, ":pushbutton %s %s\n",
|
||||
txButTable[but], txActTable[act]);
|
||||
fprintf(txLogFile, "%spushbutton %s %s\n",
|
||||
pfix, txButTable[but], txActTable[act]);
|
||||
}
|
||||
if (txLogUpdate)
|
||||
fprintf(txLogFile, ":updatedisplay\n");
|
||||
(void) fflush(txLogFile);
|
||||
if (txLogFlags & TX_LOG_UPDATE)
|
||||
fprintf(txLogFile, "%supdatedisplay\n", pfix);
|
||||
|
||||
fflush(txLogFile);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1183,6 +1365,8 @@ TxTclDispatch(clientData, argc, argv, quiet)
|
|||
|
||||
result = WindSendCommand((MagWindow *)clientData, tclcmd, quiet);
|
||||
|
||||
if (txLogFile != NULL) txLogCommand(tclcmd);
|
||||
|
||||
TxFreeCommand(tclcmd);
|
||||
|
||||
// Don't update the command number on bypass commands, or else
|
||||
|
|
|
|||
|
|
@ -130,9 +130,13 @@ extern void TxSetPoint();
|
|||
extern int TxGetPoint();
|
||||
extern void TxClearPoint();
|
||||
|
||||
/* Routine to set up command logging.
|
||||
/* Routines to handle command logging.
|
||||
*/
|
||||
extern void TxLogCommands();
|
||||
extern void TxLogStart();
|
||||
extern void TxLogStop();
|
||||
extern void TxLogUpdate();
|
||||
extern void TxLogSuspend();
|
||||
extern void TxLogResume();
|
||||
|
||||
|
||||
/* Routines for handling input events. A typical device driver in the
|
||||
|
|
|
|||
|
|
@ -863,18 +863,23 @@ windHelpCmd(w, cmd)
|
|||
ASSERT(FALSE, windHelpCmd);
|
||||
}
|
||||
|
||||
static char *logKeywords[] =
|
||||
{
|
||||
"update",
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* windLogCommandsCmd --
|
||||
*
|
||||
* Log the commands and button pushes in a file.
|
||||
*
|
||||
* Syntax:
|
||||
* logcommands start <filename> Open and start a new command log file
|
||||
* logcommands stop End and close a command log file
|
||||
* logcommands update Refresh display after each log command
|
||||
* logcommands suspend Suspend logging of commands
|
||||
* logcommands resume Resume logging of commands
|
||||
*
|
||||
* Legacy syntax:
|
||||
* logcommands <filename> [update] Start a new command log file with updating
|
||||
* logcommands End and close a command log file
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
|
|
@ -883,35 +888,74 @@ static char *logKeywords[] =
|
|||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define LOG_CMD_START 0 // Create a new log file (default behavior)
|
||||
#define LOG_CMD_STOP 1 // End a log file and stop logging.
|
||||
#define LOG_CMD_UPDATE 2 // Update display after every logged command.
|
||||
#define LOG_CMD_SUSPEND 3 // Suspend command logging.
|
||||
#define LOG_CMD_RESUME 4 // Resume command logging.
|
||||
|
||||
void
|
||||
windLogCommandsCmd(w, cmd)
|
||||
MagWindow *w;
|
||||
TxCommand *cmd;
|
||||
{
|
||||
char *fileName;
|
||||
bool update;
|
||||
char *fileName = NULL;
|
||||
unsigned char flags = 0;
|
||||
int idx = LOG_CMD_STOP;
|
||||
|
||||
static char *logKeywords[] = {"start", "stop", "update", "suspend", "resume", 0};
|
||||
|
||||
if ((cmd->tx_argc < 1) || (cmd->tx_argc > 3)) goto usage;
|
||||
|
||||
update = FALSE;
|
||||
|
||||
if (cmd->tx_argc == 1)
|
||||
fileName = NULL;
|
||||
else
|
||||
fileName = cmd->tx_argv[1];
|
||||
|
||||
if (cmd->tx_argc == 3) {
|
||||
int i;
|
||||
i = Lookup(cmd->tx_argv[cmd->tx_argc - 1], logKeywords);
|
||||
if (i != 0) goto usage;
|
||||
update = TRUE;
|
||||
if (cmd->tx_argc > 1)
|
||||
{
|
||||
idx = Lookup(cmd->tx_argv[1], logKeywords);
|
||||
if (idx < 0) fileName = cmd->tx_argv[1];
|
||||
}
|
||||
|
||||
TxLogCommands(fileName, update);
|
||||
return;
|
||||
if (cmd->tx_argc == 3)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (fileName == NULL)
|
||||
fileName = cmd->tx_argv[2];
|
||||
else
|
||||
{
|
||||
/* Legacy behavior: Allow "logcommands <filename> update"
|
||||
* to mean "logcommands start <filename> ; logcommands update"
|
||||
*/
|
||||
i = Lookup(cmd->tx_argv[2], logKeywords);
|
||||
if (i != LOG_CMD_UPDATE) goto usage;
|
||||
flags = TX_LOG_UPDATE;
|
||||
idx = LOG_CMD_START;
|
||||
}
|
||||
}
|
||||
|
||||
switch (idx)
|
||||
{
|
||||
case LOG_CMD_START:
|
||||
if (fileName == NULL) break;
|
||||
TxLogStart(fileName, w);
|
||||
if (flags & TX_LOG_UPDATE)
|
||||
TxLogUpdate();
|
||||
return;
|
||||
case LOG_CMD_STOP:
|
||||
TxLogStop();
|
||||
return;
|
||||
case LOG_CMD_UPDATE:
|
||||
TxLogUpdate();
|
||||
return;
|
||||
case LOG_CMD_SUSPEND:
|
||||
TxLogSuspend();
|
||||
return;
|
||||
case LOG_CMD_RESUME:
|
||||
TxLogResume();
|
||||
return;
|
||||
}
|
||||
|
||||
usage:
|
||||
TxError("Usage: %s [filename [update]]\n", cmd->tx_argv[0]);
|
||||
TxError("Usage: %s [start|stop|update|suspend|resume [filename]]\n",
|
||||
cmd->tx_argv[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -311,6 +311,24 @@ WindSendCommand(w, cmd, quiet)
|
|||
if ((WindNewButtons == 0) && (windGrabber != (WindClient) NULL))
|
||||
WindReleaseInput((WindClient) rc);
|
||||
|
||||
/* This is a bit of a hack, because it shouldn't be done in so many
|
||||
* places, but the command logging needs to regenerate the setpoint
|
||||
* positions as commands, and it needs the command's Y value to be
|
||||
* correct for the command. It is okay to modify the command's
|
||||
* recorded position value, because logging the command is the only
|
||||
* other thing done with the structure.
|
||||
*/
|
||||
if (w != NULL)
|
||||
{
|
||||
switch (WindPackageType)
|
||||
{
|
||||
case WIND_X_WINDOWS:
|
||||
/* Windows have origin at lower-left corner */
|
||||
cmd->tx_p.p_y = w->w_allArea.r_ytop - cmd->tx_p.p_y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue