home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Applications / Muddweller 1.2 / source code / Main / Macros.cp < prev    next >
Encoding:
Text File  |  1994-02-21  |  26.9 KB  |  1,182 lines  |  [TEXT/MPS ]

  1. /* Macros - Implementation of the login/logout macros and key bindings        */
  2.  
  3. #include "Macros.h"
  4.  
  5.         // • Toolbox
  6. #ifndef __CTYPE__
  7. #include "CType.h"
  8. #endif
  9.  
  10. #ifndef __ERRORS__
  11. #include "Errors.h"
  12. #endif
  13.  
  14. #ifndef __STDLIB__
  15. #include "StdLib.h"
  16. #endif
  17.  
  18. #ifndef __TOOLUTILS__
  19. #include "ToolUtils.h"
  20. #endif
  21.  
  22.         // • Implementation use
  23. #ifndef __GLOBALS__
  24. #include "Globals.h"
  25. #endif
  26.  
  27. #ifndef __MUDDOC__
  28. #include "MUDDoc.h"
  29. #endif
  30.  
  31.  
  32. //------------------------------------------------------------------------------
  33.  
  34. const short iLogin = 1;
  35. const short iLogout = 2;
  36. const short iSeparator = 3;
  37. const short kMaxItems = 250;
  38. const short kUpKeyMask = 0x80;
  39. const short kMAsmKeyCache = 38; // is this ok (system 7.0 headers)?
  40.  
  41. short gNumKeyMacros;
  42. Boolean gCmdInhibit;
  43.  
  44.  
  45. //------------------------------------------------------------------------------
  46.  
  47. #pragma segment SDocDialogs
  48.  
  49. pascal void AppendStr (Str255 str, Str255 add)
  50. {
  51.     int len, ip, op;
  52.     
  53.     ip = str [0];
  54.     op = 0;
  55.     len = add [0];
  56.     if (ip + len > 255) len = 255 - ip;
  57.     while (len > 0) {
  58.         ip += 1;
  59.         op += 1;
  60.         str [ip] = add [op];
  61.         len -= 1;
  62.     }
  63.     str [0] = ip;
  64. }
  65.  
  66.  
  67. //------------------------------------------------------------------------------
  68.  
  69. #pragma segment SDocDialogs
  70.  
  71. pascal void AppendNum (Str255 str, unsigned char num)
  72. {
  73.     Str255 tmp;
  74.     int i;
  75.     
  76.     i = 1;
  77.     if (num >= 100) tmp [i++] = '0' + num / 100;
  78.     if (num >= 10) tmp [i++] = '0' + (num % 100) / 10;
  79.     tmp [i++] = '0' + num % 10;
  80.     tmp [0] = i - 1;
  81.     AppendStr (str, tmp);
  82. }
  83.  
  84.  
  85. //------------------------------------------------------------------------------
  86.  
  87. #pragma segment SDocDialogs
  88.  
  89. pascal void GetKeyName (MHandle mh, Str255 keyName)
  90. {
  91.     Str255 tmp;
  92.     
  93.     keyName [0] = 1;
  94.     keyName [1] = '[';
  95.     AppendNum (keyName, (**mh).mCode);
  96.     keyName [++keyName [0]] = ']';
  97.     keyName [++keyName [0]] = ' ';
  98.     if ((**mh).mShift) {
  99.         GetIndString (tmp, kMUDStrings, kmsShift);
  100.         AppendStr (keyName, tmp);
  101.     }
  102.     if ((**mh).mOption) {
  103.         GetIndString (tmp, kMUDStrings, kmsOption);
  104.         AppendStr (keyName, tmp);
  105.     }
  106.     if ((**mh).mControl) {
  107.         GetIndString (tmp, kMUDStrings, kmsControl);
  108.         AppendStr (keyName, tmp);
  109.     }
  110.     switch ((**mh).mCode) {
  111.     case kClearVirtualCode:
  112.         GetIndString (tmp, kMUDStrings, kmsClear);
  113.         break;
  114.     case kEscapeVirtualCode:
  115.         GetIndString (tmp, kMUDStrings, kmsEscape);
  116.         break;
  117.     case kF1VirtualCode:
  118.         GetIndString (tmp, kMUDStrings, kmsF1);
  119.         break;
  120.     case kF2VirtualCode:
  121.         GetIndString (tmp, kMUDStrings, kmsF2);
  122.         break;
  123.     case kF3VirtualCode:
  124.         GetIndString (tmp, kMUDStrings, kmsF3);
  125.         break;
  126.     case kF4VirtualCode:
  127.         GetIndString (tmp, kMUDStrings, kmsF4);
  128.         break;
  129.     case kF5VirtualCode:
  130.         GetIndString (tmp, kMUDStrings, kmsF5);
  131.         break;
  132.     case kF6VirtualCode:
  133.         GetIndString (tmp, kMUDStrings, kmsF6);
  134.         break;
  135.     case kF7VirtualCode:
  136.         GetIndString (tmp, kMUDStrings, kmsF7);
  137.         break;
  138.     case kF8VirtualCode:
  139.         GetIndString (tmp, kMUDStrings, kmsF8);
  140.         break;
  141.     case kF9VirtualCode:
  142.         GetIndString (tmp, kMUDStrings, kmsF9);
  143.         break;
  144.     case kF10VirtualCode:
  145.         GetIndString (tmp, kMUDStrings, kmsF10);
  146.         break;
  147.     case kF11VirtualCode:
  148.         GetIndString (tmp, kMUDStrings, kmsF11);
  149.         break;
  150.     case kF12VirtualCode:
  151.         GetIndString (tmp, kMUDStrings, kmsF12);
  152.         break;
  153.     case kF13VirtualCode:
  154.         GetIndString (tmp, kMUDStrings, kmsF13);
  155.         break;
  156.     case kF14VirtualCode:
  157.         GetIndString (tmp, kMUDStrings, kmsF14);
  158.         break;
  159.     case kF15VirtualCode:
  160.         GetIndString (tmp, kMUDStrings, kmsF15);
  161.         break;
  162.     case kFwdDelVirtualCode:
  163.         GetIndString (tmp, kMUDStrings, kmsFwdDel);
  164.         break;
  165.     default:
  166.         if ((**mh).mChar <= 32)
  167.             GetIndString (tmp, kKeyStrings, (**mh).mChar + 1);
  168.         else {
  169.             tmp [0] = 1;
  170.             tmp [1] = (**mh).mChar;
  171.         }
  172.         break;
  173.     }
  174.     AppendStr (keyName, tmp);
  175. }
  176.  
  177.  
  178. //------------------------------------------------------------------------------
  179.  
  180. #pragma segment SDocDialogs
  181.  
  182. class TMacroTEView: public TTEView {
  183. public:
  184.  
  185.     virtual pascal void ComputeSize (VPoint *newSize);
  186. };
  187.  
  188. pascal void TMacroTEView::ComputeSize (VPoint *newSize)
  189. {
  190.     inherited::ComputeSize (newSize);
  191.     if (newSize->v < fSuperView->fSize.v) newSize->v = fSuperView->fSize.v;
  192. }
  193.  
  194.  
  195. //------------------------------------------------------------------------------
  196.  
  197. #pragma segment SDocDialogs
  198.  
  199. Boolean gShift;
  200. Boolean gOption;
  201. Boolean gControl;
  202. unsigned char gChar;
  203. unsigned char gCode;
  204.  
  205. typedef struct MAExpandMemRec *MAExpandMemRecPtr, **MAExpandMemRecHandle;
  206.  
  207. struct MAExpandMemRec {
  208.     short emVersion;
  209.     long emSize;
  210.     long emIntlGlobals;
  211.     long emKeyDeadState;
  212.     Ptr emKeyCache;
  213.     long emIntlDef;
  214.     Boolean emFirstKeyboard;
  215.     Boolean emAlign;
  216.     long emItlCache [4];
  217.     Boolean emItlNeedUnlock;
  218.     Boolean emItlDirectGetIntl;
  219.     unsigned char emFiller [22];
  220. };
  221.  
  222. class TNewDialogView: public TDialogView {
  223. public:
  224.  
  225.     virtual pascal TCommand *DoKeyCommand (short ch, short aKeyCode,
  226.         EventInfo *info);
  227. };
  228.  
  229. pascal TCommand *TNewDialogView::DoKeyCommand (short ch, short aKeyCode,
  230.         EventInfo *info)
  231. {
  232.     short keyCode;
  233.     long state, keyInfo;
  234.     Ptr keyTransTable;
  235.     
  236.     gChar = (unsigned char) ch;
  237.     gCode = (unsigned char) aKeyCode;
  238.     gShift = info->theShiftKey;
  239.     gOption = info->theOptionKey;
  240.     gControl = info->theControlKey;
  241.     if (gConfiguration.hasScriptManager) {
  242.         keyCode = gCode + kUpKeyMask; // all modifiers stripped, upKey set
  243.         state = 0;
  244.         if (gConfiguration.systemVersion >= 0x700)
  245.             keyTransTable = (Ptr) GetEnvirons (kMAsmKeyCache);
  246.         else
  247.             keyTransTable = (Ptr)(**(MAExpandMemRecHandle)ExpandMem).emKeyCache;
  248.         keyInfo = KeyTrans (keyTransTable, keyCode, &state);
  249.         gChar = (unsigned char) keyInfo;
  250.         if (gChar == 0) gChar = (unsigned char) (keyInfo >> 16);
  251.     }
  252.     fDismissed = TRUE;
  253.     fDismisser = 'OK  ';
  254.     return NULL;
  255. }
  256.  
  257.  
  258. //------------------------------------------------------------------------------
  259.  
  260. #pragma segment SDocDialogs
  261.  
  262. class TNewMacButton: public TButton {
  263. public:
  264.     TMUDDoc *fMUDDoc;
  265.  
  266.     virtual pascal void DoChoice (TView *origView, short itsChoice);
  267. };
  268.  
  269. pascal void TNewMacButton::DoChoice (TView *, short)
  270. {
  271.     TWindow *aWindow;
  272.     TDialogView *aDialogView;
  273.     TPopup *aPopup;
  274.     Boolean cancelled;
  275.     MHandle mh, oh, nh;
  276.     short item;
  277.     int mval, val;
  278.     Str255 keyName;
  279.     
  280.     aWindow = NewTemplateWindow (kTypeKeyID, NULL);
  281.     FailNIL (aWindow);
  282.     aDialogView = (TDialogView *) aWindow->FindSubView ('DLOG');
  283.     cancelled = (aDialogView->PoseModally () == 'cncl');
  284.     aWindow->Close ();
  285.     if (cancelled) Failure (noErr, msgCancelled);
  286.     mh = NewMacroRec ();
  287.     (**mh).mChar = gChar;
  288.     (**mh).mCode = gCode;
  289.     (**mh).mShift = gShift;
  290.     (**mh).mOption = gOption;
  291.     (**mh).mControl = gControl;
  292.     item = iSeparator;
  293.     nh = fMUDDoc->fMacroList;
  294.     oh = nh;
  295.     mval = (gCode << 3) + (gShift << 2) + (gOption << 1) + gControl;
  296.     while (nh) {
  297.         val = ((**nh).mCode << 3) + ((**nh).mShift << 2) +
  298.             ((**nh).mOption << 1) + (**nh).mControl;
  299.         if (val >= mval) break;
  300.         item += 1;
  301.         oh = nh;
  302.         nh = (**nh).mNext;
  303.     }
  304.     aPopup = (TPopup *) GetWindow ()->FindSubView ('popu');
  305.     if (oh && (val == mval))
  306.         DisposMacroRec (mh);
  307.     else {
  308.         if (nh == fMUDDoc->fMacroList) {
  309.             (**mh).mNext = nh;
  310.             fMUDDoc->fMacroList = mh;
  311.         } else {
  312.             (**mh).mNext = (**oh).mNext;
  313.             (**oh).mNext = mh;
  314.         }
  315.         GetKeyName (mh, keyName);
  316.         SetItemMark (aPopup->fMenuHandle, aPopup->fCurrentItem, ' ');
  317.         InsMenuItem (aPopup->fMenuHandle, keyName, item);
  318.         SetItem (aPopup->fMenuHandle, item + 1, keyName);
  319.         aPopup->fCurrentItem = 0;
  320.         aPopup->AdjustBotRight ();
  321.         gNumKeyMacros += 1;
  322.         if (gNumKeyMacros >= kMaxItems) DimState (TRUE, kRedraw);
  323.     }
  324.     aPopup->SetCurrentItem (item + 1, kRedraw);
  325.     aPopup->DoChoice (aPopup, aPopup->fDefChoice);
  326. }
  327.  
  328.  
  329. //------------------------------------------------------------------------------
  330.  
  331. #pragma segment SDocDialogs
  332.  
  333. class TRemoveButton: public TButton {
  334. public:
  335.     TMUDDoc *fMUDDoc;
  336.  
  337.     virtual pascal void DoChoice (TView *origView, short itsChoice);
  338. };
  339.  
  340. pascal void TRemoveButton::DoChoice (TView *, short)
  341. {
  342.     TPopup *aPopup;
  343.     TNewMacButton *aNewMacButton;
  344.     short item, i;
  345.     MHandle mh, oh;
  346.     
  347.     aPopup = (TPopup *) GetWindow ()->FindSubView ('popu');
  348.     item = aPopup->fCurrentItem;
  349.     mh = fMUDDoc->fMacroList;
  350.     if (mh && (item > iSeparator)) {
  351.         DelMenuItem (aPopup->fMenuHandle, item);
  352.         aPopup->ForceRedraw ();
  353.         aPopup->AdjustBotRight ();
  354.         i = iSeparator + 1;
  355.         if (item == i)
  356.             fMUDDoc->fMacroList = (**mh).mNext;
  357.         else {
  358.             while (mh && (i < item)) {
  359.                 oh = mh;
  360.                 mh = (**mh).mNext;
  361.                 i += 1;
  362.             }
  363.             (**oh).mNext = (**mh).mNext;
  364.         }
  365.         DisposMacroRec (mh);
  366.         if (item >= iSeparator + gNumKeyMacros) item -= 1;
  367.         if (item == iSeparator) item = iLogout;
  368.         gNumKeyMacros -= 1;
  369.         aNewMacButton = (TNewMacButton *) GetWindow ()->FindSubView ('new ');
  370.         if (gNumKeyMacros < kMaxItems) aNewMacButton->DimState (FALSE, kRedraw);
  371.         aPopup->fCurrentItem = 0;
  372.         aPopup->SetCurrentItem (item, kDontRedraw);
  373.         aPopup->DoChoice (aPopup, aPopup->fDefChoice);
  374.     }
  375. }
  376.  
  377.  
  378. //------------------------------------------------------------------------------
  379.  
  380. #pragma segment SDocDialogs
  381.  
  382. class TMacroPopup: public TPopup {
  383. public:
  384.     TMUDDoc *fMUDDoc;
  385.  
  386.     virtual pascal void DoChoice (TView *origView, short itsChoice);
  387. };
  388.  
  389. pascal void TMacroPopup::DoChoice (TView *origView, short itsChoice)
  390. {
  391.     MHandle mh;
  392.     Handle th;
  393.     TMacroTEView *aMacroTEView;
  394.     TRemoveButton *aRemoveButton;
  395.     int i;
  396.     
  397.     if (fCurrentItem == iLogin)
  398.         mh = fMUDDoc->fLogin;
  399.     else if (fCurrentItem == iLogout)
  400.         mh = fMUDDoc->fLogout;
  401.     else {
  402.         i = iSeparator + 1;
  403.         mh = fMUDDoc->fMacroList;
  404.         while (mh && (fCurrentItem > i)) {
  405.             mh = (**mh).mNext;
  406.             i += 1;
  407.         }
  408.     }
  409.     if (mh) {
  410.         th = (**mh).mText;
  411.         aMacroTEView = (TMacroTEView *) GetWindow ()->FindSubView ('text');
  412.         if (aMacroTEView->fText != th) {
  413.             (**aMacroTEView->fHTE).hText = th;
  414.             (**aMacroTEView->fHTE).teLength = (short) GetHandleSize (th);
  415.             aMacroTEView->fText = th;
  416.             aMacroTEView->RecalcText ();
  417.             aMacroTEView->ForceRedraw ();
  418.             TESetSelect(0, 0, aMacroTEView->fHTE);
  419.         }
  420.     }
  421.     aRemoveButton = (TRemoveButton *) GetWindow ()->FindSubView ('remv');
  422.     aRemoveButton->DimState (fCurrentItem <= iSeparator, kRedraw);
  423.     inherited::DoChoice (origView, itsChoice);
  424. }
  425.  
  426.  
  427. //------------------------------------------------------------------------------
  428.  
  429. #pragma segment SMacros
  430.  
  431. pascal void DisposMacroRec (MHandle theRec)
  432. {
  433.     if (theRec) {
  434.         DisposIfHandle ((**theRec).mText);
  435.         DisposIfHandle (theRec);
  436.     }
  437. }
  438.  
  439.  
  440. //------------------------------------------------------------------------------
  441.  
  442. #pragma segment MAReadFile
  443.  
  444. pascal long MacroRecSize (MHandle theRec)
  445. {
  446.     return sizeof (MacroDiskRec) + GetHandleSize ((**theRec).mText);
  447. }
  448.  
  449.  
  450. //------------------------------------------------------------------------------
  451.  
  452. #pragma segment SMacros
  453.  
  454. pascal MHandle NewMacroRec (void)
  455. {
  456.     MHandle mh;
  457.     
  458.     mh = (MHandle) NewPermHandle (sizeof (MacroRec));
  459.     FailNIL (mh);
  460.     (**mh).mNext = NULL;
  461.     (**mh).mText = NewPermHandle (0);
  462.     if (!(**mh).mText) {
  463.         DisposIfHandle (mh);
  464.         Failure (memFullErr, 0);
  465.     }
  466.     (**mh).mShift = FALSE;
  467.     (**mh).mOption = FALSE;
  468.     (**mh).mControl = FALSE;
  469.     (**mh).mChar = 0;
  470.     (**mh).mCode = 0;
  471.     return mh;
  472. }
  473.  
  474.  
  475. //------------------------------------------------------------------------------
  476.  
  477. #pragma segment SMacros
  478.  
  479. pascal MHandle ReadMacroRec (short theRefNum)
  480. {
  481.     MHandle mh;
  482.     Handle th;
  483.     MacroDiskRec diskRec;
  484.     OSErr err;
  485.     long count;
  486.     
  487.     mh = (MHandle) NewPermHandle (sizeof (MacroRec));
  488.     FailNIL (mh);
  489.     count = sizeof (diskRec);
  490.     err = FSRead (theRefNum, &count, (Ptr) &diskRec);
  491.     if (err != noErr) {
  492.         DisposIfHandle (mh);
  493.         FailOSErr (err);
  494.     }
  495.     (**mh).mNext = NULL;
  496.     (**mh).mShift = diskRec.shift;
  497.     (**mh).mOption = diskRec.option;
  498.     (**mh).mControl = diskRec.control;
  499.     (**mh).mChar = diskRec.ch;
  500.     (**mh).mCode = diskRec.code;
  501.     th = NewPermHandle (diskRec.textLen);
  502.     if (!th) {
  503.         DisposIfHandle (mh);
  504.         Failure (memFullErr, 0);
  505.     }
  506.     HLock (th);
  507.     count = diskRec.textLen;
  508.     err = FSRead (theRefNum, &count, *th);
  509.     HUnlock (th);
  510.     if (err != noErr) {
  511.         DisposMacroRec (mh);
  512.         FailOSErr (err);
  513.     }
  514.     (**mh).mText = th;
  515.     return mh;
  516. }
  517.  
  518.  
  519. //------------------------------------------------------------------------------
  520.  
  521. #pragma segment SMacros
  522.  
  523. pascal void WriteMacroRec (short theRefNum, MHandle theRec)
  524. {
  525.     MacroDiskRec diskRec;
  526.     long count;
  527.     SignedByte oldState;
  528.     
  529.     diskRec.shift = (**theRec).mShift;
  530.     diskRec.option = (**theRec).mOption;
  531.     diskRec.control = (**theRec).mControl;
  532.     diskRec.filler1 = 0;
  533.     diskRec.ch = (**theRec).mChar;
  534.     diskRec.code = (**theRec).mCode;
  535.     diskRec.textLen = (short) GetHandleSize ((**theRec).mText);
  536.     count = sizeof (diskRec);
  537.     FailOSErr (FSWrite (theRefNum, &count, (Ptr) &diskRec));
  538.     oldState = HGetState ((**theRec).mText);
  539.     HLock ((**theRec).mText);
  540.     count = diskRec.textLen;
  541.     FailOSErr (FSWrite (theRefNum, &count, *(**theRec).mText));
  542.     HSetState ((**theRec).mText, oldState);
  543. }
  544.  
  545.  
  546. //------------------------------------------------------------------------------
  547.  
  548. #pragma segment SDocDialogs
  549.  
  550. pascal void SetupDialog (TMUDDoc *aMUDDoc, TWindow *aWindow)
  551. {
  552.     TMacroTEView *aMacroTEView;
  553.     TMacroPopup *aMacroPopup;
  554.     TNewMacButton *aNewMacButton;
  555.     TRemoveButton *aRemoveButton;
  556.     Handle h;
  557.     MHandle mh;
  558.     Str255 keyName;
  559.     short item;
  560.     
  561.     aMacroPopup = (TMacroPopup *) aWindow->FindSubView ('popu');
  562.     aMacroPopup->fMUDDoc = aMUDDoc;
  563.     gNumKeyMacros = 0;
  564.     item = aMUDDoc->fLastMacItem;
  565.     if (item == iLogin)
  566.         h = (**(aMUDDoc->fLogin)).mText;
  567.     else if (item == iLogout)
  568.         h = (**(aMUDDoc->fLogout)).mText;
  569.     else
  570.         h = NULL;
  571.     item -= iSeparator;
  572.     mh = aMUDDoc->fMacroList;
  573.     while (mh) {
  574.         GetKeyName (mh, keyName);
  575.         InsMenuItem (aMacroPopup->fMenuHandle, keyName, iSeparator +
  576.             gNumKeyMacros);
  577.         SetItem (aMacroPopup->fMenuHandle, iSeparator + gNumKeyMacros + 1,
  578.             keyName);
  579.         gNumKeyMacros += 1;
  580.         if (--item == 0) h = (**mh).mText;
  581.         mh = (**mh).mNext;
  582.     }
  583.     aMacroPopup->AdjustBotRight ();
  584.     aMacroPopup->SetCurrentItem (aMUDDoc->fLastMacItem, kDontRedraw);
  585.     aNewMacButton = (TNewMacButton *) aWindow->FindSubView ('new ');
  586.     aNewMacButton->fMUDDoc = aMUDDoc;
  587.     aNewMacButton->DimState (gNumKeyMacros >= kMaxItems, kDontRedraw);
  588.     aRemoveButton = (TRemoveButton *) aWindow->FindSubView ('remv');
  589.     aRemoveButton->fMUDDoc = aMUDDoc;
  590.     aRemoveButton->DimState (aMUDDoc->fLastMacItem < iSeparator, kDontRedraw);
  591.     aMacroTEView = (TMacroTEView *) aWindow->FindSubView ('text');
  592.     if (h) aMacroTEView->StuffText (h);
  593.     aMacroTEView->RecalcText ();
  594. }
  595.  
  596.  
  597. //------------------------------------------------------------------------------
  598.  
  599. #pragma segment SDocDialogs
  600.  
  601. pascal void EditMacros (TDocument *aDocument)
  602. {
  603.     TWindow *aWindow;
  604.     TDialogView *aDialogView;
  605.     TMacroPopup *aMacroPopup;
  606.     
  607.     aWindow = NewTemplateWindow (kMacrosID, NULL);
  608.     FailNIL (aWindow);
  609.     SetupDialog ((TMUDDoc *) aDocument, aWindow);
  610.     aDialogView = (TDialogView *) aWindow->FindSubView ('DLOG');
  611.     aDialogView->PoseModally ();
  612.     aMacroPopup = (TMacroPopup *) aWindow->FindSubView ('popu');
  613.     ((TMUDDoc *) aDocument)->fLastMacItem = aMacroPopup->GetCurrentItem ();
  614.     aWindow->Close ();
  615.     aDocument->fChangeCount += 1;
  616. }
  617.  
  618.  
  619. //------------------------------------------------------------------------------
  620.  
  621. #pragma segment MAInit
  622.  
  623. pascal void InitMacros (void)
  624. {
  625.     gCmdInhibit = FALSE;
  626.     if (gDeadStripSuppression) {
  627.         TMacroTEView *aMacroTEView = new TMacroTEView;
  628.         TMacroPopup *aMacroPopup = new TMacroPopup;
  629.         TNewMacButton *aNewMacButton = new TNewMacButton;
  630.         TRemoveButton *aRemoveButton = new TRemoveButton;
  631.         TNewDialogView *aNewDialogView = new TNewDialogView;
  632.     }
  633. }
  634.  
  635.  
  636. //------------------------------------------------------------------------------
  637.  
  638. #pragma segment SMacros
  639.  
  640. pascal long GetCmdStr (Handle theText, long pos, Str255 cmd, Str255 parm)
  641. {
  642.     long size;
  643.     unsigned char **th, ch;
  644.     int i;
  645.     
  646.     size = GetHandleSize (theText);
  647.     th = (unsigned char **) theText;
  648.     ch = *(*th + pos);
  649.     while ((pos < size) && ((ch == '#') || isspace (ch))) {
  650.         if ((pos < size) && (ch == '#')) {
  651.             ch = *(*th + ++pos);
  652.             while ((pos < size) && (ch != '\n')) ch = *(*th + ++pos);
  653.         }
  654.         while ((pos < size) && isspace (ch)) ch = *(*th + ++pos);
  655.     }
  656.     ch = toupper (ch);
  657.     i = 0;
  658.     while ((pos < size) && (i < 255) && !isspace (ch)) {
  659.         cmd [++i] = ch;
  660.         ch = toupper (*(*th + ++pos));
  661.     }
  662.     cmd [0] = (unsigned char) i;
  663.     while ((pos < size) && ((ch == ' ') || (ch == '\t'))) ch = *(*th + ++pos);
  664.     i = 0;
  665.     while ((pos < size) && (i < 255) && (ch != '\n')) {
  666.         parm [++i] = ch;
  667.         ch = *(*th + ++pos);
  668.     }
  669.     parm [0] = (unsigned char) i;
  670.     while ((pos < size) && (ch != '\n')) ch = *(*th + ++pos);
  671.     return pos;
  672. }
  673.  
  674.  
  675. //------------------------------------------------------------------------------
  676.  
  677. #pragma segment SMacros
  678.  
  679. pascal void ParseCmdHandler (short , long , void * )
  680. {
  681.     gCmdInhibit = FALSE;
  682. }
  683.  
  684. pascal long ParseCmd (TMUDDoc *doc, Handle theText, long pos, int *cmd,
  685.         Str255 parm)
  686. {
  687.     Str255 cmdstr, parmstr, tmp;
  688.     int i, j, k, l, len;
  689.     FailInfo fi;
  690.     unsigned char ch, *cp, c;
  691.     
  692.     pos = GetCmdStr (theText, pos, cmdstr, parmstr);
  693.     if (cmdstr [0] == 0) {
  694.         *cmd = kCmdNone;
  695.         parm [0] = 0;
  696.         return pos;
  697.     }
  698.     for (i = 1; i <= kLastCmd; i++) {
  699.         GetIndString (tmp, kCmdStrings, (short) i);
  700.         if (CompareStrings (cmdstr, tmp) == 0) break;
  701.     }
  702.     if (i > kLastCmd) {
  703.         CatchFailures (&fi, ParseCmdHandler, kDummyLink);
  704.         gCmdInhibit = TRUE;
  705.         ParamText (cmdstr, "\p", "\p", "\p");
  706.         MacAppAlert (phCmdErrID, NULL);
  707.         gCmdInhibit = FALSE;
  708.         Success (&fi);
  709.         *cmd = kCmdNone;
  710.         parm [0] = 0;
  711.         return GetHandleSize (theText);
  712.     }
  713.     *cmd = i;
  714.     len = parmstr [0];
  715.     i = 0;
  716.     j = 0;
  717.     while ((i < 255) && (j < len)) {
  718.         ch = parmstr [++j];
  719.         if (ch == '$') {
  720.             ch = parmstr [++j];
  721.             l = 0;
  722.             if (j <= len) {
  723.                 switch (ch) {
  724.                 case 'n':
  725.                 case 'N':
  726.                     cp = doc->fPlayer;
  727.                     l = *cp++;
  728.                     break;
  729.                 case 'p':
  730.                 case 'P':
  731.                     cp = doc->fPasswd;
  732.                     l = *cp++;
  733.                     break;
  734.                 case '$':
  735.                     parm [++i] = ch;
  736.                     break;
  737.                 }
  738.             }
  739.             if (l > 0) {
  740.                 k = 0;
  741.                 while ((i < 255) && (k < l)) {
  742.                     parm [++i] = *cp++;
  743.                     k += 1;
  744.                 }
  745.             }
  746.         } else if (ch == '\\') {
  747.             ch = parmstr [++j];
  748.             if (j <= len) {
  749.                 switch (ch) {
  750.                 case 'b':
  751.                     ch = '\b';
  752.                     break;
  753.                 case 't':
  754.                     ch = '\t';
  755.                     break;
  756.                 case 'n':
  757.                     ch = '\n';
  758.                     break;
  759.                 case 'f':
  760.                     ch = '\f';
  761.                     break;
  762.                 case '0':
  763.                 case '1':
  764.                 case '2':
  765.                 case '3':
  766.                 case '4':
  767.                 case '5':
  768.                 case '6':
  769.                 case '7':
  770.                     c = ch - '0';
  771.                     ch = parmstr [++j];
  772.                     if ((j <= len) && (ch >= '0') && (ch <= '7'))
  773.                         c = c * 8 + ch - '0';
  774.                     else
  775.                         j -= 1;
  776.                     ch = parmstr [++j];
  777.                     if ((j <= len) && (ch >= '0') && (ch <= '7'))
  778.                         c = c * 8 + ch - '0';
  779.                     else
  780.                         j -= 1;
  781.                     ch = c;
  782.                     break;
  783.                 }
  784.                 parm [++i] = ch;
  785.             }
  786.         } else
  787.             parm [++i] = ch;
  788.     }
  789.     parm [0] = (unsigned char) i;
  790.     return pos;
  791. }
  792.  
  793.  
  794. //------------------------------------------------------------------------------
  795.  
  796. #pragma segment SMacros
  797.  
  798. pascal void TMacro::DoEcho (void)
  799. {
  800.     Str255 tmp;
  801.     long act, count;
  802.     
  803.     CopyStr255 (fParm, tmp);
  804.     act = 1;
  805.     count = tmp [0] + 1;
  806.     while (act < count)
  807.         act += ((TMUDDoc *) fDocument)->fEchoFilter->Filter (tmp + act,
  808.             count - act);
  809. }
  810.  
  811.  
  812. //------------------------------------------------------------------------------
  813.  
  814. #pragma segment SMacros
  815.  
  816. pascal void TMacro::DoIdle (void)
  817. {
  818.     int cmd;
  819.     Str255 parm, tmp;
  820.     long size;
  821.     
  822.     if (gCmdInhibit) return;
  823.     if (!((TMUDDoc *) fDocument)->fConnected || gStop) {
  824.         ((TMUDDoc *) fDocument)->fMacroFilter->fScan = FALSE;
  825.         MacroDone ();
  826.     } else {
  827.         size = GetHandleSize ((**fMRec).mText);
  828.         do {
  829.             if (fCmdDone && (fMPos < size)) {
  830.                 fMPos = ParseCmd ((TMUDDoc *) fDocument, (**fMRec).mText,
  831.                     fMPos, &cmd, parm);
  832.                 fCmd = cmd;
  833.                 CopyStr255 (parm, fParm);
  834.             }
  835.             switch (fCmd) {
  836.             case kCmdSend:
  837.                 DoSend ();
  838.                 break;
  839.             case kCmdMatch:
  840.                 DoMatch ();
  841.                 break;
  842.             case kCmdWait:
  843.                 DoWait ();
  844.                 break;
  845.             case kCmdPasswd:
  846.                 DoPasswd ();
  847.                 break;
  848.             case kCmdQuiet:
  849.                 DoQuiet ();
  850.                 break;
  851.             case kCmdEcho:
  852.                 DoEcho ();
  853.                 break;
  854.             }
  855.         } while (fCmdDone && (fMPos < size));
  856.         if (fCmdDone && (fMPos >= size)) MacroDone ();
  857.     }
  858. }
  859.  
  860.  
  861. //------------------------------------------------------------------------------
  862.  
  863. #pragma segment SMacros
  864.  
  865. pascal void TMacro::DoMatch (void)
  866. {
  867.     TMacroFilter *filter;
  868.     
  869.     if (fCmdDone && (fParm [0] > 0)) {
  870.         filter = ((TMUDDoc *) fDocument)->fMacroFilter;
  871.         CopyStr255 (fParm, filter->fStr);
  872.         filter->fPos = 1;
  873.         filter->fScan = TRUE;
  874.         fCmdDone = FALSE;
  875.     }
  876. }
  877.  
  878.  
  879. //------------------------------------------------------------------------------
  880.  
  881. #pragma segment SMacros
  882.  
  883. pascal void TMacro::DoPasswd (void)
  884. {
  885.     TWindow *aWindow;
  886.     TDialogView *aDialogView;
  887.     TEditText *aEditText;
  888.     Str255 tmp;
  889.     FailInfo fi;
  890.     
  891.     aWindow = NewTemplateWindow (kPasswordID, NULL);
  892.     FailNIL (aWindow);
  893.     if (fParm [0] > 0) {
  894.         aEditText = (TEditText *) aWindow->FindSubView ('text');
  895.         CopyStr255 (fParm, tmp);
  896.         aEditText->SetText (tmp, kDontRedraw);
  897.     }
  898.     CatchFailures (&fi, ParseCmdHandler, kDummyLink);
  899.     gCmdInhibit = TRUE;
  900.     aDialogView = (TDialogView *) aWindow->FindSubView ('DLOG');
  901.     aDialogView->PoseModally ();
  902.     aEditText = (TEditText *) aWindow->FindSubView ('pass');
  903.     aEditText->GetText (tmp);
  904.     aWindow->Close ();
  905.     gCmdInhibit = FALSE;
  906.     Success (&fi);
  907.     if (tmp [0] < 255) tmp [++tmp [0]] = chReturn;
  908.     ((TMUDDoc *) fDocument)->Send (tmp + 1, tmp [0]);
  909. }
  910.  
  911.  
  912. //------------------------------------------------------------------------------
  913.  
  914. #pragma segment SMacros
  915.  
  916. pascal void TMacro::DoQuiet (void)
  917. {
  918.     Str255 tmp, off;
  919.     int i, len;
  920.     
  921.     CopyStr255 (fParm, tmp);
  922.     len = tmp [0];
  923.     i = 0;
  924.     while ((i < len) && !isspace (tmp [i + 1])) i += 1;
  925.     tmp [0] = i;
  926.     for (i = 1; i <= len; i++) tmp [i] = toupper (tmp [i]);
  927.     GetIndString (off, kMUDStrings, kmsOff);
  928.     if (CompareStrings (tmp, off) == 0)
  929.         ((TMUDDoc *) fDocument)->fQuiet = FALSE;
  930.     else
  931.         ((TMUDDoc *) fDocument)->fQuiet = TRUE;
  932. }
  933.  
  934.  
  935. //------------------------------------------------------------------------------
  936.  
  937. #pragma segment SMacros
  938.  
  939. pascal void TMacro::DoSend (void)
  940. {
  941.     Str255 tmp;
  942.     
  943.     CopyStr255 (fParm, tmp);
  944.     ((TMUDDoc *) fDocument)->Send (tmp + 1, tmp [0]);
  945. }
  946.  
  947.  
  948. //------------------------------------------------------------------------------
  949.  
  950. #pragma segment SMacros
  951.  
  952. pascal void TMacro::DoWait (void)
  953. {
  954.     Str255 tmp;
  955.     int i;
  956.     
  957.     if (fCmdDone) {
  958.         CopyStr255 (fParm, tmp);
  959.         if (tmp [0] == 0)
  960.             i = 0;
  961.         else {
  962.             if (tmp [0] < 255)
  963.                 tmp [tmp [0] + 1] = 0;
  964.             else
  965.                 tmp [255] = 0;
  966.             i = atoi ((char *) (tmp + 1));
  967.         }
  968.         fWaitEnd = TickCount () + 60 * i;
  969.         fCmdDone = FALSE;
  970.     } else if (TickCount () >= fWaitEnd)
  971.         fCmdDone = TRUE;
  972. }
  973.  
  974.  
  975. //------------------------------------------------------------------------------
  976.  
  977. #pragma segment SMacros
  978.  
  979. pascal void TMacro::Free (void)
  980. {
  981.     TMacro *aMacro;
  982.     
  983.     if (((TMUDDoc *)fDocument)->fRunList == this)
  984.         ((TMUDDoc *)fDocument)->fRunList = fNext;
  985.     else {
  986.         aMacro = ((TMUDDoc *)fDocument)->fRunList;
  987.         while (aMacro && (aMacro->fNext != this)) aMacro = aMacro->fNext;
  988.         if (aMacro) aMacro->fNext = fNext;
  989.     }
  990.     ((TMUDDoc *)fDocument)->fRunning =
  991.         (((TMUDDoc *)fDocument)->fRunList != NULL);
  992.     ((TMUDDoc *) fDocument)->fQuiet = FALSE;
  993.     InvalidateMenuBar ();
  994.     gApplication->SetupTheMenus ();
  995.     inherited::Free ();
  996. }
  997.  
  998.  
  999. //------------------------------------------------------------------------------
  1000.  
  1001. #pragma segment SMacros
  1002.  
  1003. pascal void TMacro::IMacro (TDocument *itsDoc, MHandle itsRec)
  1004. {
  1005.     TMacro *aMacro;
  1006.     
  1007.     fNext = NULL;
  1008.     IObject ();
  1009.     fDocument = itsDoc;
  1010.     fMRec = itsRec;
  1011.     fMPos = 0;
  1012.     fCmd = kCmdNone;
  1013.     fParm [0] = 0;
  1014.     fCmdDone = TRUE;
  1015.     if (((TMUDDoc *)itsDoc)->fRunList) {
  1016.         aMacro = ((TMUDDoc *)itsDoc)->fRunList;
  1017.         while (aMacro->fNext) aMacro = aMacro->fNext;
  1018.         aMacro->fNext = this;
  1019.     } else
  1020.         ((TMUDDoc *)itsDoc)->fRunList = this;
  1021.     ((TMUDDoc *)fDocument)->fRunning = TRUE;
  1022.     gBusyState = 0;
  1023.     gLastBusyTick = 0;
  1024.     gApplication->InvalidateCursorRgn ();
  1025.     InvalidateMenuBar ();
  1026.     gApplication->SetupTheMenus ();
  1027. }
  1028.  
  1029.  
  1030. //------------------------------------------------------------------------------
  1031.  
  1032. #pragma segment SMacros
  1033.  
  1034. pascal void TMacro::MacroDone (void)
  1035. {
  1036.     Free ();
  1037. }
  1038.  
  1039.  
  1040. //------------------------------------------------------------------------------
  1041.  
  1042. #pragma segment SMacros
  1043.  
  1044. pascal void TLoginMacro::DoIdle (void)
  1045. {
  1046.     OSErr err;
  1047.     IOBlock *block;
  1048.     
  1049.     if (!fOpenDone) {
  1050.         block = ((TMUDDoc *)fDocument)->fBlock;
  1051.         if (gStop) {
  1052.             PBKillIO ((ParamBlockRec *) &block->pb, FALSE);
  1053.             block->pb.ioNamePtr = NULL;
  1054.             block->pb.ioCRefNum = gTCPRef;
  1055.             block->pb.tcpStream = ((TMUDDoc *)fDocument)->fTCPStream;
  1056.             block->pb.csCode = TCPAbort;
  1057.             PBControl ((ParamBlockRec *) &block->pb, FALSE);
  1058.             ((TMUDDoc *)fDocument)->fConnected = FALSE;
  1059.             Free ();
  1060.             return;
  1061.         } else if ((block->pb.ioResult != 1) || (block->ioError != noErr)) {
  1062.             if (block->ioError != noErr)
  1063.                 err = block->ioError;
  1064.             else
  1065.                 err = block->pb.ioResult;
  1066.             if (err != noErr) {
  1067.                 if (TickCount () - fStartTicks + 30 > kTCPTimeout * 60)
  1068.                     err = errOpenTimeout;
  1069.                 Free ();
  1070.                 FailOSErr (err);
  1071.             }
  1072.             fOpenDone = TRUE;
  1073.             ((TMUDDoc *)fDocument)->fConnected = TRUE;
  1074.             ((TMUDDoc *)fDocument)->fDoConnect = TRUE;
  1075.         }
  1076.     }
  1077.     if (fOpenDone) inherited::DoIdle ();
  1078. }
  1079.  
  1080.  
  1081. //------------------------------------------------------------------------------
  1082.  
  1083. #pragma segment SMacros
  1084.  
  1085. pascal void TLoginMacro::IMacro (TDocument *itsDoc, MHandle itsRec)
  1086. {
  1087.     inherited::IMacro (itsDoc, itsRec);
  1088.     fOpenDone = ((TMUDDoc *)itsDoc)->fUseCTB;
  1089. }
  1090.  
  1091.  
  1092. //------------------------------------------------------------------------------
  1093.  
  1094. #pragma segment SMacros
  1095.  
  1096. pascal void TLogoutMacro::DoIdle (void)
  1097. {
  1098.     TCloseWindowCommand *aCloseWindowCommand;
  1099.     TQuitCommand *aQuitCommand;
  1100.     IOBlock *block;
  1101.     
  1102.     if (fMacroDone || gStop) {
  1103.         block = ((TMUDDoc *)fDocument)->fBlock;
  1104.         if (!fClosing && !gStop) {
  1105.             block->pb.ioCompletion = NULL;
  1106.             block->pb.ioNamePtr = NULL;
  1107.             block->pb.ioCRefNum = gTCPRef;
  1108.             block->pb.tcpStream = ((TMUDDoc *)fDocument)->fTCPStream;
  1109.             block->pb.csCode = TCPClose;
  1110.             block->pb.csParam.open.ulpTimeoutValue = kTCPTimeout;
  1111.             block->pb.csParam.open.ulpTimeoutAction = 1;
  1112.             block->pb.csParam.open.validityFlags = timeoutValue + timeoutAction;
  1113.             block->pb.csParam.open.commandTimeoutValue = kTCPTimeout;
  1114.             block->pb.csParam.open.userDataPtr =
  1115.                 (Ptr) ((TMUDDoc *)fDocument)->fBlock;
  1116.             PBControl ((ParamBlockRec *) &block->pb, TRUE);
  1117.             fClosing = TRUE;
  1118.         } else if (gStop) {
  1119.             if (fClosing) PBKillIO ((ParamBlockRec *) &block->pb, FALSE);
  1120.             block->pb.ioResult = 0;
  1121.         }
  1122.         if ((block->pb.ioResult != 1) || (block->ioError != noErr))
  1123.             ((TMUDDoc *)fDocument)->Disconnect ();
  1124.         if (!((TMUDDoc *)fDocument)->fConnected) {
  1125.             if (fDoneCmd == cClose) {
  1126.                 aCloseWindowCommand = new TCloseWindowCommand;
  1127.                 if (aCloseWindowCommand) { // don't fail if NIL
  1128.                     aCloseWindowCommand->ICloseWindowCommand (cClose,
  1129.                         ((TMUDDoc *) fDocument)->fLogWindow);
  1130.                     gApplication->PostCommand (aCloseWindowCommand);
  1131.                 }
  1132.             } else if (fDoneCmd == cQuit) {
  1133.                 aQuitCommand = new TQuitCommand;
  1134.                 if (aQuitCommand) { // don't fail if NIL
  1135.                     aQuitCommand->IQuitCommand (cQuit);
  1136.                     gApplication->PostCommand (aQuitCommand);
  1137.                 }
  1138.             }
  1139.             Free ();
  1140.         }
  1141.     } else
  1142.         inherited::DoIdle ();
  1143. }
  1144.  
  1145.  
  1146. //------------------------------------------------------------------------------
  1147.  
  1148. #pragma segment SMacros
  1149.  
  1150. pascal void TLogoutMacro::Free (void)
  1151. {
  1152.     ((TMUDDoc *)fDocument)->fClosing = FALSE;
  1153.     inherited::Free ();
  1154. }
  1155.  
  1156.  
  1157. //------------------------------------------------------------------------------
  1158.  
  1159. #pragma segment SMacros
  1160.  
  1161. pascal void TLogoutMacro::IMacro (TDocument *itsDoc, MHandle itsRec)
  1162. {
  1163.     inherited::IMacro (itsDoc, itsRec);
  1164.     fMacroDone = FALSE;
  1165.     fClosing = FALSE;
  1166.     fDoneCmd = cNoCommand;
  1167.     ((TMUDDoc *)itsDoc)->fClosing = TRUE;
  1168. }
  1169.  
  1170.  
  1171. //------------------------------------------------------------------------------
  1172.  
  1173. #pragma segment SMacros
  1174.  
  1175. pascal void TLogoutMacro::MacroDone (void)
  1176. {
  1177.     fMacroDone = TRUE;
  1178. }
  1179.  
  1180.  
  1181. //------------------------------------------------------------------------------
  1182.