home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Applications / Nuntius 1.2 / src / Nuntius / UMailCmds.cp < prev    next >
Encoding:
Text File  |  1994-02-20  |  6.3 KB  |  298 lines  |  [TEXT/MPS ]

  1. // Copyright © 1992 Peter Speck, speck@dat.ruc.dk. All rights reserved.
  2. // UMailCmds.cp
  3.  
  4. #include "UMailCmds.h"
  5. #include "Tools.h"
  6. #include "XTypes.h"
  7. #include "UArticleListView.h"
  8. #include "UArticle.h"
  9. #include "UArticleCache.h"
  10. #include "UGroupDoc.h"
  11. #include "ProcessTools.h"
  12. #include "NetAsciiTools.h"
  13. #include "UPrefsDatabase.h"
  14.  
  15. #include <RsrcGlobals.h>
  16. #include <ErrorGlobals.h>
  17.  
  18. #include <OSEvents.h>
  19.  
  20. #pragma segment MyArticle
  21.  
  22. //StdAlert(phNoMailYet);
  23. //GetListOfSelectedArticles
  24.  
  25.  
  26. const long kEudoraSignature = 'CSOm';
  27.  
  28. struct KeyInfo
  29. {
  30.     long charCode;
  31.     long modifiers;
  32. };
  33.  
  34. TMailToAuthorCommand::TMailToAuthorCommand()
  35. {
  36. }
  37.  
  38. pascal void TMailToAuthorCommand::Initialize()
  39. {
  40.     inherited::Initialize();
  41.     fQuoteH = nil;
  42.     fTypeH = nil;
  43.     fDoc = nil;
  44.     fArticleListView = nil;
  45.     fArticleIDList = nil;
  46.     fArticle = nil;
  47. }
  48.  
  49. void TMailToAuthorCommand::IMailToAuthorCommand(TGroupDoc *doc, TArticleListView *articleListView, Boolean asQuote, Boolean addHeader)
  50. {
  51.     inherited::ICommand(cMailToAuthors, nil, false, false, nil);
  52.     fDoc = doc;
  53.     fArticleListView = articleListView;
  54.     fAsQuote = asQuote;
  55.     fAddHeader = addHeader;
  56. }
  57.  
  58. pascal void TMailToAuthorCommand::Free()
  59. {
  60.     gArticleCache->ReturnArticle(fArticle); fArticle = nil;
  61.     fQuoteH = DisposeIfHandle(fQuoteH);
  62.     FreeIfObject(fArticleIDList); fArticleIDList = nil;
  63.     fTypeH = DisposeIfHandle(fTypeH);
  64.     inherited::Free();
  65. }
  66.  
  67. void WaitLong()
  68. {
  69.     short i = 0;
  70.     while (i <= 2)
  71.     {
  72.         gApplication->PollToolboxEvent(false);
  73.         EventRecord event;
  74.         if (EventAvail(activMask | updateMask | osMask, event))
  75.             i = 0;
  76.         else
  77.             i++;
  78.     }
  79. }
  80.  
  81. void WaitABit()
  82. {
  83.     short i = 0;
  84.     EventRecord event;
  85.     while (OSEventAvail(everyEvent, event))
  86.     {
  87.         WaitNextEvent(0, event, 1, nil);
  88.         i++;
  89.         if (i > 15)
  90.             Failure(minErr, 0);
  91.     }
  92. }
  93.  
  94. void PostKey(char key, Boolean commandKey)
  95. {
  96.     KeyInfo *const ki = (KeyInfo*)0x174;
  97.     ki->charCode = 0;
  98.     ki->modifiers = commandKey ? 0x8000 : 0;
  99.     long msg = key;
  100.     if (key == chEscape)
  101.         msg |= kEscapeVirtualCode << 8;
  102.     PostEvent(3, msg);
  103.     ki->charCode = 0;
  104.     ki->modifiers = 0;
  105. }
  106.  
  107. pascal void TMailToAuthorCommand::DoIt()
  108. {
  109.     FailInfo fi;
  110.     if (fi.Try())
  111.     {
  112. // test for OS
  113.         if (gConfiguration.hasAUX)
  114.             FailOSErr(errCannotUseAUX);
  115.         if (!gPrefs->PrefExists('EuAp'))
  116.             FailOSErr(errNoMailer);
  117.         PutQuoteIntoScrap();
  118.         CreateTypeText();
  119.         LaunchEudora();
  120.         ExecuteHack();
  121.         fi.Success();
  122.     }
  123.     else // fail
  124.     {
  125.         FailNewMessage(fi.error, fi.message, messageReplyWithLetter);
  126.     }
  127. }
  128.  
  129. void TMailToAuthorCommand::LaunchEudora()
  130. {
  131.     FailInfo fi;
  132.     if (fi.Try())
  133.     {
  134.         FSSpec spec;
  135.         ProcessSerialNumber eudoraPSN, myPSN;
  136.         FailOSErr(GetCurrentProcess(myPSN));
  137.         if (FindProcessBySignature(kEudoraSignature, eudoraPSN, &spec) != noErr)
  138.         {
  139.             FSSpec euSpec;
  140.             gPrefs->GetAliasPrefs('EuAp', euSpec);
  141.             if (gPrefs->GetBooleanPrefs('EuOp'))
  142.             {
  143.                 if (!gPrefs->PrefExists('Eudo'))
  144.                     FailOSErr(errNoMailerDoc);
  145.                 FSSpec spec;
  146.                 gPrefs->GetAliasPrefs('Eudo', spec);
  147.                 AliasHandle alias;
  148.                 FailOSErr(NewAliasMinimal(spec, alias));
  149.                 OpenApplicationDocument(euSpec, alias, true);
  150.             }
  151.             else
  152.                 LaunchApplication(euSpec, true);
  153.         }
  154.     
  155.         unsigned long startTick = TickCount();
  156.         while (true)
  157.         {
  158.             Boolean timeout = TickCount() - startTick > 10 * 60;
  159.             WaitLong();    
  160.             if (FindProcessBySignature(kEudoraSignature, eudoraPSN, &spec) != noErr)
  161.                 if (timeout)
  162.                     FailOSErr(errLaunchEudoraTimeout);
  163.                 else
  164.                     continue;
  165.             if (SetFrontProcess(eudoraPSN) != noErr)
  166.                 if (timeout)
  167.                     FailOSErr(errBringEudoraToFrontTimeout);
  168.                 else
  169.                     continue;
  170.             if (!ApplicationIsInfront(eudoraPSN))
  171.                 if (timeout)
  172.                     FailOSErr(errBringEudoraToFrontTimeout);
  173.                 else
  174.                     continue;
  175.             break;
  176.         }
  177.         fi.Success();
  178.     }
  179.     else // fail
  180.     {
  181.         FailNewMessage(fi.error, fi.message, msgLaunchEudora);
  182.     }
  183. }
  184.  
  185. Boolean TMailToAuthorCommand::ApplicationIsInfront(ProcessSerialNumber &appPSN)
  186. {
  187.     ProcessSerialNumber frontPSN;
  188.     FailOSErr(GetFrontProcess(frontPSN));
  189.     Boolean isSame;
  190.     FailOSErr(SameProcess(appPSN, frontPSN, isSame));
  191.     return isSame;
  192. }
  193.  
  194. void TMailToAuthorCommand::PutQuoteIntoScrap()
  195. {
  196. //    fQuoteH = fArticleListView->GetSelectionAsTextForClipboard(fAsQuote, fAddHeader, true);
  197.     fQuoteH = fArticleListView->GetSelectionAsQuotedTextForMail();
  198.     HLock(fQuoteH);
  199.     ZeroScrap();
  200.     PutScrap(GetHandleSize(fQuoteH), 'TEXT', *fQuoteH);
  201.     fQuoteH = DisposeIfHandle(fQuoteH);
  202. }
  203.  
  204. void TMailToAuthorCommand::CreateTypeText()
  205. {
  206.     fTypeH = NewPermHandle(0);
  207.     fArticleIDList = fArticleListView->GetListOfSelectedArticles();
  208.     {
  209.         CLongintIterator iter(fArticleIDList);
  210.         Boolean gotOne = false;
  211.         for (long id = iter.FirstLong(); iter.More(); id = iter.NextLong())
  212.         {
  213.             gArticleCache->ReturnArticle(fArticle); fArticle = nil;
  214.             FailInfo fi;
  215.             if (fi.Try())
  216.             {
  217.                 CStr255 groupDotName;
  218.                 fDoc->GetGroupDotName(groupDotName);
  219.                 fArticle = gArticleCache->GetArticle(groupDotName, id);
  220.                 fi.Success();
  221.             }
  222.             else // fail
  223.             {
  224.                 if (fi.error == errNoSuchArticle)
  225.                     continue;
  226.                 fi.ReSignal();
  227.             }
  228.             CStr255 name, email, text;
  229.             if (!fArticle->GetHeader("Reply-to", text))
  230.                 if (!fArticle->GetHeader("From", text))
  231.                     continue;
  232.             GetAuthorName(text, name, email);
  233.             if (gotOne)
  234.                 email.Insert(", ", 1);
  235.             if (name.Length())
  236.             {
  237.                 email += " (";
  238.                 email += name;
  239.                 email += ")";
  240.             }
  241.             AppendStringToHandle(email, fTypeH);
  242.             gotOne = true;
  243.         }
  244.         gArticleCache->ReturnArticle(fArticle); fArticle = nil;
  245.     }
  246.     AppendStringToHandle("\x9", fTypeH);
  247.     {
  248.         CLongintIterator iter(fArticleIDList);
  249.         for (long id = iter.FirstLong(); iter.More(); id = iter.NextLong())
  250.         {
  251.             if (id < fDoc->GetFirstArticleID() || id > fDoc->GetLastArticleID())
  252.                 continue;
  253.             CStr255 subject, pre, post;
  254.             HandleOffsetLength hol;
  255.             if (!fDoc->GetSubject(id, hol))
  256.                 continue;
  257.             CopyHolToCStr255(hol, subject);
  258.             MyGetIndString(pre, kMailPreSubject);
  259.             MyGetIndString(post, kMailPostSubject);
  260.             AppendStringToHandle(pre, fTypeH);
  261.             AppendStringToHandle(subject, fTypeH);
  262.             AppendStringToHandle(post, fTypeH);
  263.             break;
  264.         }
  265.     }
  266.     AppendStringToHandle("\x9\x9\x9", fTypeH);
  267. }
  268.  
  269. void TMailToAuthorCommand::ExecuteHack()
  270. {
  271. // Abort Ask-Password dialog, if any
  272.     PostKey('.', true);
  273.     WaitLong();
  274.  
  275. // Make new letter
  276.     PostKey('N', true);
  277.     WaitLong();
  278.  
  279. // Make headers
  280.     HLock(fTypeH);
  281.     Ptr p = *fTypeH;
  282.     long len = GetHandleSize(fTypeH);
  283.     short numSaved = 0;
  284.     for (long i = 1; i <= len; i++)
  285.     {
  286.         PostKey(*p++, false);
  287.         ++numSaved;
  288.         if (numSaved > 10)
  289.         {
  290.             WaitABit();
  291.             numSaved = 0;
  292.         }
  293.     }
  294.  
  295. // Body
  296.     PostKey('V', true);
  297. }
  298.