home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 26
/
CD_ASCQ_26_1295.iso
/
vrac
/
tvme30.zip
/
TMACRO.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1995-08-02
|
8KB
|
206 lines
// File : TMACRO.CPP
// Author : Eric Woodruff, CIS ID: 72134,1150
// Updated : Wed 08/02/95 17:54:19
// Note : Copyright 1994-95, Eric Woodruff, All rights reserved
// Compiler: Borland C++ 3.1 to 4.xx
//
// This is a replacement TApplication::getEvent() member function that will
// allow the implementation of simple macro recording and playback. It
// isn't perfect, but works fairly well. It is best to use ALT+R to start
// and stop recording instead of ALT+O, and Enter (when Record is the
// default menu item). The final Enter sometimes causes the wrong thing to
// display after the macro has finished. Ah well, this is only a demo.
//
// NOTE: This expects to have the static data members MacroFile and
// MacroStatus defined in the TApplication class.
//
#include <dir.h>
#include <dos.h>
#include <io.h>
#include <stdio.h>
#include <string.h>
#define Uses_MsgBox
#define Uses_TApplication
#define Uses_TEvent
#define Uses_TEventQueue
#define Uses_TFileDialog
#define Uses_TKeys
#include <tv.h>
// NOTE: For each application, these will have to change. #include the
// header that defines your application class. You will also need
// to change all "TxxxxApp::" references to name your application
// class.
#define Uses_TVMEditorApp
#include "tvedit.h"
FILE * _NEAR TVMEditorApp::MacroFile = NULL; // Macro function is off
ushort _NEAR TVMEditorApp::MacroStatus = 0; // to start with.
// A version string was added to the macro file because there are
// significant differences between the TV 1.03 and TV 2.0 TEvent structures.
#if _TV_VERSION == 0x0103
char VersionString[] = "TVMEditor Macro File\x1A\x01\x03";
#else
char VersionString[] = "TVMEditor Macro File\x1A\x02\x00";
#endif
void TVMEditorApp::getEvent(TEvent &event)
{
static char macroName[MAXPATH] = "*.MAC";
char verCheck[30];
//
// In TV 2.0, the control key states *are* in the TEvent structure.
//
#if _TV_VERSION == 0x0103
// Ideally the shift state would be in the TEvent structure. However, it
// isn't, I don't want to modify it and all classes that may need it, and
// the following method works well. If not accounted for, stuff like
// sizing the window with the keyboard or selecting text in an editor
// won't work.
unsigned char *kbFlagsPtr = (uchar *)MK_FP(0x40, 0x17);
#endif
// Get the next event from the file if playing a macro.
if(MacroStatus == cmPlay && MacroFile)
{
#if _TV_VERSION == 0x0103
char keyState;
if(fread(&event, sizeof(event), 1, MacroFile) != 1 ||
fread(&keyState, sizeof(char), 1, MacroFile) != 1)
#else
if(fread(&event, sizeof(event), 1, MacroFile) != 1)
#endif
{
fclose(MacroFile); // End of file or error.
MacroFile = NULL;
MacroStatus = 0;
#if _TV_VERSION == 0x0103
*kbFlagsPtr &= 0xF0; // Reset Shift/Alt/Ctrl status bits.
#endif
// If that was the end of the file, chances are that the
// last event was a keyboard or mouse event that will now
// generate another cmRecord event. If so, get rid of it.
TApplication::getEvent(event);
// Put it back if it is not.
if(event.what != evCommand || (event.message.command != cmRecord &&
event.message.command != cmPlay))
putEvent(event);
}
else
{
delay(100);
putEvent(event);
#if _TV_VERSION == 0x0103
// Set keyboard flags for the event. It's okay to do this because
// it is the keyboard interrupt that adjusts it. The only thing
// to remember is that before returning control to the user, turn
// off the Shift/Alt/Ctrl bits incase they were left on by the
// last event.
*kbFlagsPtr = keyState;
#endif
}
clearEvent(event);
}
TApplication::getEvent(event);
// Save all but evNothing, cmRecord, and cmPlay events.
//
// NOTE: Using the mouse will cause hundreds of events to be recorded
// and the macro file will be very large!
// If possible, avoid using the mouse when recording macros.
// Another problem with the mouse in macros is that objects
// (such as editors) might not be in the proper place and
// a mouse event might miss its intended target.
// Optionally, you could suspend the mouse handler when
// recording starts and resume it when recording is finished.
if(MacroStatus == cmRecord && event.what != evNothing)
if(event.what != evCommand || (event.message.command != cmRecord
&& event.message.command != cmPlay))
#if _TV_VERSION == 0x0103
{
fwrite(&event, sizeof(TEvent), 1, MacroFile);
fwrite(kbFlagsPtr, sizeof(char), 1, MacroFile);
}
#else
fwrite(&event, sizeof(TEvent), 1, MacroFile);
#endif
if(event.what == evCommand)
{
if(!MacroStatus && event.message.command == cmPlay)
{
clearEvent(event);
if(executeDialog(new TFileDialog(macroName, "Play Macro",
"~N~ame", fdOpenButton, 100), macroName) != cmCancel)
{
MacroFile = fopen(macroName, "rb");
if(MacroFile)
{
fread(verCheck, sizeof(VersionString), 1, MacroFile);
if(strncmp(verCheck, VersionString, sizeof(VersionString)))
messageBox("Incompatible macro file",
mfError | mfCancelButton);
else
MacroStatus = cmPlay;
}
}
}
else
if(event.message.command == cmRecord)
{
clearEvent(event);
if(!MacroStatus && !MacroFile)
{
if(executeDialog(new TFileDialog(macroName, "Record Macro",
"~N~ame", fdOpenButton, 100), macroName) != cmCancel)
{
// Start event recording.
ushort result = cmYes;
if(!access(macroName, 0))
result = messageBox("File exists. OVERWRITE?",
mfConfirmation | mfYesNoCancel);
// Create a new file.
if(result == cmYes)
MacroFile = fopen(macroName, "wb");
// Append commands to an existing file.
if(result == cmNo)
MacroFile = fopen(macroName, "ab");
if(MacroFile)
{
// TEventQueue::suspend(); // Suspend mouse.
MacroStatus = cmRecord;
fwrite(VersionString, sizeof(VersionString), 1, MacroFile);
}
}
}
else
{
// End event recording.
fclose(MacroFile);
MacroFile = NULL;
MacroStatus = 0;
// TEventQueue::resume(); // Resume mouse.
}
}
}
}