home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 26 / CD_ASCQ_26_1295.iso / vrac / tvme30.zip / TMACRO.CPP < prev    next >
C/C++ Source or Header  |  1995-08-02  |  8KB  |  206 lines

  1. // File    : TMACRO.CPP
  2. // Author  : Eric Woodruff,  CIS ID: 72134,1150
  3. // Updated : Wed 08/02/95 17:54:19
  4. // Note    : Copyright 1994-95, Eric Woodruff, All rights reserved
  5. // Compiler: Borland C++ 3.1 to 4.xx
  6. //
  7. // This is a replacement TApplication::getEvent() member function that will
  8. // allow the implementation of simple macro recording and playback.  It
  9. // isn't perfect, but works fairly well.  It is best to use ALT+R to start
  10. // and stop recording instead of ALT+O, and Enter (when Record is the
  11. // default menu item).  The final Enter sometimes causes the wrong thing to
  12. // display after the macro has finished.  Ah well, this is only a demo.
  13. //
  14. // NOTE:  This expects to have the static data members MacroFile and
  15. //        MacroStatus defined in the TApplication class.
  16. //
  17.  
  18. #include <dir.h>
  19. #include <dos.h>
  20. #include <io.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23.  
  24. #define Uses_MsgBox
  25. #define Uses_TApplication
  26. #define Uses_TEvent
  27. #define Uses_TEventQueue
  28. #define Uses_TFileDialog
  29. #define Uses_TKeys
  30. #include <tv.h>
  31.  
  32. // NOTE: For each application, these will have to change.  #include the
  33. //       header that defines your application class.  You will also need
  34. //       to change all "TxxxxApp::" references to name your application
  35. //       class.
  36. #define Uses_TVMEditorApp
  37. #include "tvedit.h"
  38.  
  39. FILE * _NEAR TVMEditorApp::MacroFile = NULL;     // Macro function is off
  40. ushort _NEAR TVMEditorApp::MacroStatus = 0;      // to start with.
  41.  
  42. // A version string was added to the macro file because there are
  43. // significant differences between the TV 1.03 and TV 2.0 TEvent structures.
  44. #if _TV_VERSION == 0x0103
  45. char VersionString[] = "TVMEditor Macro File\x1A\x01\x03";
  46. #else
  47. char VersionString[] = "TVMEditor Macro File\x1A\x02\x00";
  48. #endif
  49.  
  50. void TVMEditorApp::getEvent(TEvent &event)
  51. {
  52.     static char macroName[MAXPATH] = "*.MAC";
  53.     char verCheck[30];
  54.  
  55. //
  56. // In TV 2.0, the control key states *are* in the TEvent structure.
  57. //
  58. #if _TV_VERSION == 0x0103
  59.     // Ideally the shift state would be in the TEvent structure.  However, it
  60.     // isn't, I don't want to modify it and all classes that may need it, and
  61.     // the following method works well.  If not accounted for, stuff like
  62.     // sizing the window with the keyboard or selecting text in an editor
  63.     // won't work.
  64.     unsigned char *kbFlagsPtr = (uchar *)MK_FP(0x40, 0x17);
  65. #endif
  66.  
  67.     // Get the next event from the file if playing a macro.
  68.     if(MacroStatus == cmPlay && MacroFile)
  69.     {
  70. #if _TV_VERSION == 0x0103
  71.         char keyState;
  72.  
  73.         if(fread(&event, sizeof(event), 1, MacroFile) != 1 ||
  74.            fread(&keyState, sizeof(char), 1, MacroFile) != 1)
  75. #else
  76.         if(fread(&event, sizeof(event), 1, MacroFile) != 1)
  77. #endif
  78.         {
  79.             fclose(MacroFile);      // End of file or error.
  80.             MacroFile = NULL;
  81.             MacroStatus = 0;
  82.  
  83. #if _TV_VERSION == 0x0103
  84.             *kbFlagsPtr &= 0xF0;    // Reset Shift/Alt/Ctrl status bits.
  85. #endif
  86.  
  87.             // If that was the end of the file, chances are that the
  88.             // last event was a keyboard or mouse event that will now
  89.             // generate another cmRecord event.  If so, get rid of it.
  90.             TApplication::getEvent(event);
  91.  
  92.             // Put it back if it is not.
  93.             if(event.what != evCommand || (event.message.command != cmRecord &&
  94.               event.message.command != cmPlay))
  95.                 putEvent(event);
  96.         }
  97.         else
  98.         {
  99.             delay(100);
  100.             putEvent(event);
  101.  
  102. #if _TV_VERSION == 0x0103
  103.             // Set keyboard flags for the event.  It's okay to do this because
  104.             // it is the keyboard interrupt that adjusts it.  The only thing
  105.             // to remember is that before returning control to the user, turn
  106.             // off the Shift/Alt/Ctrl bits incase they were left on by the
  107.             // last event.
  108.             *kbFlagsPtr = keyState;
  109. #endif
  110.         }
  111.  
  112.         clearEvent(event);
  113.     }
  114.  
  115.     TApplication::getEvent(event);
  116.  
  117.     // Save all but evNothing, cmRecord, and cmPlay events.
  118.     //
  119.     // NOTE:  Using the mouse will cause hundreds of events to be recorded
  120.     //        and the macro file will be very large!
  121.     //        If possible, avoid using the mouse when recording macros.
  122.     //        Another problem with the mouse in macros is that objects
  123.     //        (such as editors) might not be in the proper place and
  124.     //        a mouse event might miss its intended target.
  125.     //        Optionally, you could suspend the mouse handler when
  126.     //        recording starts and resume it when recording is finished.
  127.  
  128.     if(MacroStatus == cmRecord && event.what != evNothing)
  129.         if(event.what != evCommand || (event.message.command != cmRecord
  130.           && event.message.command != cmPlay))
  131. #if _TV_VERSION == 0x0103
  132.         {
  133.             fwrite(&event, sizeof(TEvent), 1, MacroFile);
  134.             fwrite(kbFlagsPtr, sizeof(char), 1, MacroFile);
  135.         }
  136. #else
  137.             fwrite(&event, sizeof(TEvent), 1, MacroFile);
  138. #endif
  139.  
  140.     if(event.what == evCommand)
  141.     {
  142.         if(!MacroStatus && event.message.command == cmPlay)
  143.         {
  144.             clearEvent(event);
  145.  
  146.             if(executeDialog(new TFileDialog(macroName, "Play Macro",
  147.                 "~N~ame", fdOpenButton, 100), macroName) != cmCancel)
  148.             {
  149.                 MacroFile = fopen(macroName, "rb");
  150.  
  151.                 if(MacroFile)
  152.                 {
  153.                     fread(verCheck, sizeof(VersionString), 1, MacroFile);
  154.                     if(strncmp(verCheck, VersionString, sizeof(VersionString)))
  155.                         messageBox("Incompatible macro file",
  156.                             mfError | mfCancelButton);
  157.                     else
  158.                         MacroStatus = cmPlay;
  159.                 }
  160.             }
  161.         }
  162.         else
  163.             if(event.message.command == cmRecord)
  164.             {
  165.                 clearEvent(event);
  166.                 if(!MacroStatus && !MacroFile)
  167.                 {
  168.                     if(executeDialog(new TFileDialog(macroName, "Record Macro",
  169.                         "~N~ame", fdOpenButton, 100), macroName) != cmCancel)
  170.                     {
  171.                         // Start event recording.
  172.                         ushort result = cmYes;
  173.  
  174.                         if(!access(macroName, 0))
  175.                             result = messageBox("File exists. OVERWRITE?",
  176.                                 mfConfirmation | mfYesNoCancel);
  177.  
  178.                         // Create a new file.
  179.                         if(result == cmYes)
  180.                             MacroFile = fopen(macroName, "wb");
  181.  
  182.                         // Append commands to an existing file.
  183.                         if(result == cmNo)
  184.                             MacroFile = fopen(macroName, "ab");
  185.  
  186.                         if(MacroFile)
  187.                         {
  188. //                            TEventQueue::suspend();    // Suspend mouse.
  189.                             MacroStatus = cmRecord;
  190.                             fwrite(VersionString, sizeof(VersionString), 1, MacroFile);
  191.                         }
  192.                     }
  193.                 }
  194.                 else
  195.                 {
  196.                     // End event recording.
  197.                     fclose(MacroFile);
  198.                     MacroFile = NULL;
  199.                     MacroStatus = 0;
  200.  
  201. //                    TEventQueue::resume();        // Resume mouse.
  202.                 }
  203.             }
  204.     }
  205. }
  206.