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

  1. // Copyright © 1992 Peter Speck, speck@dat.ruc.dk. All rights reserved.
  2. // UProgress.cp
  3.  
  4. #include "UProgress.h"
  5. #include "UThread.h"
  6. #include "Tools.h"
  7. #include "FontTools.h"
  8. #include "UFatalError.h"
  9.  
  10. #include <RsrcGlobals.h>
  11. #include <ProgressGlobals.h>
  12.  
  13. #include <UDialogBehavior.h>
  14. #include <UDialog.h>
  15. #include <Resources.h>
  16. #include <ToolUtils.h>
  17. #include <Script.h>
  18.  
  19. const short kNoCandyStribes = 4;
  20. const long kCandyTicks = 15;
  21. const long kCandyTimeout = 4 * 60;
  22.  
  23. #define qDebugProgressText qDebug & 0
  24. #define qDebugCandy qDebug & 0
  25. #define qDebugProgressCreate qDebug & 0
  26. #define qDebugAbortDisable qDebug & 0
  27.  
  28.  
  29. #pragma segment MyThread
  30.  
  31. // Note: The Windows should not be free'd when they are closed 
  32. // as this is managed by TProgressCache.
  33.  
  34.  
  35. #define macroCheckIterator()                                                    \
  36. if (GetWindow() && GetWindow()->fIteratorPtr)                    \
  37.     fprintf(stderr, "Got fIteratorPtr at $%lx\n", long(fWindow->fIteratorPtr); \
  38.     ProgramBreak(gEmptyString);
  39.  
  40. //------------------------- TProgressMeter --------------------------------
  41.  
  42. class TProgressMeterView : public TView
  43. {
  44.     public:
  45.         void SetMax(long max);
  46.         long GetMax();
  47.         void SetValue(long value); // updates screen
  48.         void DeltaValue(long delta); // updates screen
  49.         long GetValue();
  50.         
  51.         pascal void Draw(const VRect &area);
  52.         
  53.         void UpdateCandy();
  54.         
  55.         TProgressMeterView();
  56.         pascal void Initialize();
  57.         pascal void ReadFields(TStream *aStream);
  58.         pascal void DoPostCreate(TDocument *itsDocument);
  59.         pascal void Free();
  60.     private:
  61.         TWindow *fWindow;
  62.         long fValue, fMax;
  63.         long fLastCandyTick;
  64.         short fCandyIndex;
  65.         short fPixels;
  66. };
  67.  
  68. TProgressMeterView::TProgressMeterView()
  69. {
  70. }
  71.  
  72. pascal void TProgressMeterView::Initialize()
  73. {
  74.     inherited::Initialize();
  75.     fMax = kCandyStribes;
  76.     fValue = 0;
  77.     fPixels = 0;
  78.     fCandyIndex = 0;
  79.     fLastCandyTick = 0;
  80.     fWindow = nil;
  81. }
  82.  
  83. pascal void TProgressMeterView::ReadFields(TStream *aStream)
  84. {
  85.     inherited::ReadFields(aStream);
  86. }
  87.  
  88. pascal void TProgressMeterView::Free()
  89. {
  90.     inherited::Free();
  91. }
  92.  
  93. pascal void TProgressMeterView::DoPostCreate(TDocument *itsDocument)
  94. {
  95.     inherited::DoPostCreate(itsDocument);
  96.     fWindow = GetWindow();
  97. }
  98.  
  99. void TProgressMeterView::SetMax(long max)
  100. {
  101.     fLastCandyTick = 0;
  102.     fValue = 0;
  103.     if (max == kCandyStribes)
  104.     {
  105.         if (fMax != kCandyStribes)
  106.         {
  107.             // the candy stribes are too short for one-line progress windows, so erase unused area
  108.             Focus();
  109.             EraseRect(CRect(0, 0, short(fSize.h), short(fSize.v)));
  110.         }
  111.     }
  112.     else
  113.     {
  114.         fValue = 0;
  115.         fPixels = 0;
  116.     }
  117.     fMax = max;
  118.     Focus();
  119.     Draw(VRect(gZeroVPt, fSize));
  120. }
  121.  
  122. long TProgressMeterView::GetMax()
  123. {
  124.     return fMax;
  125. }
  126.  
  127. pascal void TProgressMeterView::Draw(const VRect& /* area */)
  128. {
  129.     if (fMax == kCandyStribes) // candy
  130.     {
  131.         Boolean gotColor = false;
  132.         if (gConfiguration.hasColorQD)
  133.         {
  134.             VRect vr(VPoint(0, 0), fWindow->fSize);
  135.             vr += fWindow->fLocation;
  136.             GDHandle dev = GetMaxDevice(vr.ToRect());
  137.             if (dev)
  138.             {
  139.                 PixMapHandle pixMap = (**dev).gdPMap;
  140.                 gotColor = (**pixMap).pixelSize > 1;
  141.             }
  142.         }
  143.         Handle h;
  144.         if (gotColor)
  145.             h = GetResource('PICT', kFirstProgressCandyPictID + fCandyIndex);
  146.         else
  147.             h = GetResource('PICT', kFirstProgressCandyBWPictID + fCandyIndex);
  148.         FailNILResource(h);
  149.         PicHandle ph = PicHandle(h);
  150.         CRect r = (*ph)->picFrame;
  151.         r -= r[topLeft];
  152.         DrawPicture(ph, r);
  153.         return;
  154.     }
  155.     CRect fr(0, 0, short(fSize.h), short(fSize.v));
  156.     FrameRect(fr);
  157.     CRect r(1, 1, fPixels, short(fSize.v) - 1);
  158.     if (fPixels > 1)
  159.     {
  160.         RGBForeColor(CRGBColor(0x4000, 0x4000, 0x4000));
  161.         FillRect(r, &qd.black);
  162.     }
  163.     MoveTo(r.right, r.top - 1);
  164.     LineTo(r.right, r.bottom - 1);
  165.     r.left = r.right + 1;
  166.     r.right = short(fSize.h) - 1;
  167.     if (r.right > r.left)
  168.     {
  169.         RGBForeColor(CRGBColor(0xCCCC, 0xCCCC, 0xFFFF));
  170.         FillRect(r, &qd.white);
  171.     }
  172.     RGBForeColor(CRGBColor(0, 0, 0));
  173. }
  174.  
  175. void TProgressMeterView::SetValue(long value)
  176. {
  177.     if (fMax == kCandyStribes)
  178.         return;
  179.     if (value > fMax)
  180.         value = fMax;
  181.     fValue = value;
  182.     short newPixels = short(value * (fSize.h - 2) / fMax);
  183.     if (newPixels == fPixels)
  184.         return;
  185.     fPixels = newPixels;
  186.     Focus();
  187.     Draw(VRect(gZeroVPt, fSize));
  188. }
  189.  
  190. void TProgressMeterView::DeltaValue(long delta)
  191. {
  192.     SetValue(fValue + delta);
  193. }
  194.  
  195. long TProgressMeterView::GetValue()
  196. {
  197.     return fValue;
  198. }
  199.  
  200. void TProgressMeterView::UpdateCandy()
  201. {
  202.     long currTick = TickCount();
  203.     if (currTick < fLastCandyTick + (kCandyTicks - 1)) 
  204.         return; // don't miss one due to round-of error
  205.     fCandyIndex++;
  206.     if (fCandyIndex == kNoCandyStribes)
  207.         fCandyIndex = 0;
  208.     Focus();
  209.     Draw(VRect(gZeroVPt, fSize));
  210.     fLastCandyTick = currTick;
  211. }
  212.  
  213. //--------------------- TProgressDialogView -------------------------------
  214. class TProgressAbortButton : public TButton
  215. {
  216.     public:
  217.         void SetProgressRef(TProgress *progress);
  218.  
  219.         virtual pascal void DoEvent(EventNumber eventNumber, 
  220.                             TEventHandler *source, TEvent *event);
  221.  
  222.         TProgressAbortButton();
  223.         virtual pascal void Initialize();
  224.     private:
  225.         TProgress *fProgress;
  226. };
  227.  
  228. TProgressAbortButton::TProgressAbortButton()
  229. {
  230. }
  231.  
  232. pascal void TProgressAbortButton::Initialize()
  233. {
  234.     inherited::Initialize();
  235.     fProgress = nil;
  236. }
  237.  
  238. void TProgressAbortButton::SetProgressRef(TProgress *progress)
  239. {
  240.     fProgress = progress;
  241. }
  242.  
  243. pascal void TProgressAbortButton::DoEvent(EventNumber eventNumber, 
  244.                                 TEventHandler *source, TEvent *event)
  245. {
  246.     inherited::DoEvent(eventNumber, source, event);
  247.     if (fProgress && eventNumber == fEventNumber)
  248.         fProgress->Abort();
  249. }
  250. //--------------------------- TProgress -----------------------------------
  251.  
  252. TProgress::TProgress()
  253. {
  254. }
  255.  
  256. pascal void TProgress::Initialize()
  257. {
  258.     inherited::Initialize();
  259.     macroDontDeadStrip(TProgressMeterView);
  260.     macroDontDeadStrip(TProgressAbortButton);
  261.     fThread = nil;
  262.     fWindow = nil;
  263.     fDialogBehavior = nil;
  264.     fProgressMeterView = nil;
  265.     fUpperText = nil;
  266.     fLowerText = nil;
  267.     fAbortButton = nil;
  268.     fIsWorking = false;
  269.     fIsModal = false;
  270.     fIsTwoLine = false;
  271.     fCoHandlerInstalled = false;
  272.     fLastWorkTick = 0;
  273.     fIsCandy = true;
  274.     fAbortIsDisabled = false;
  275. }
  276.  
  277. void TProgress::IProgress()
  278. {
  279.     inherited::IObject();
  280. #if qDebugProgressCreate
  281.     fprintf(stderr, "TProgress created at $%lx\n", long(this));
  282. #endif
  283.     FailInfo fi;
  284.     if (fi.Try())
  285.     {
  286.         CreateNewWindow();
  287.         fi.Success();
  288.     }
  289.     else // fail
  290.     {
  291.         Free();
  292.         fi.ReSignal();
  293.     }
  294. }
  295.  
  296. pascal void TProgress::Free()
  297. {
  298. #if qDebugProgressCreate
  299.     fprintf(stderr, "TProgress free'd  at $%lx\n", long(this));
  300. #endif
  301.     RemoveIdleUpdating();
  302.     if (fWindow)
  303.         fWindow->CloseByUser();
  304.     inherited::Free();
  305. }
  306.  
  307. void TProgress::SetThread(TThread *thread)
  308. {
  309. #if qDebug
  310.     if (thread && !IsObject(thread))
  311.         ProgramBreak("thread is not object");
  312. #endif
  313.     fThread = thread;
  314. }
  315.  
  316. void TProgress::SetStandardProgressType()
  317. {
  318.     SetProgressType(false, false);
  319. }
  320.  
  321. void TProgress::SetProgressType(Boolean modal, Boolean twoLineWindow)
  322. {
  323. #if qDebugProgressText
  324.     fprintf(stderr, "TProgress at $%lx, SetProgressType: modal = %hd, twoLine = %hd\n", long(this), modal, twoLineWindow);
  325. #endif
  326.     fIsWorking = false;
  327.     if (modal != fIsModal || twoLineWindow != fIsTwoLine)
  328.     {
  329.         if (fIsWorking)
  330.             WorkDone();
  331.         fIsModal = modal;
  332.         fIsTwoLine = twoLineWindow;
  333.         CreateNewWindow();
  334.     }
  335.     ClearTexts();
  336.     SetAbortDisable(false);
  337. }
  338.  
  339. Boolean TProgress::SetAbortDisable(Boolean disableAbort)
  340. {
  341.     if (fWindow && fDialogBehavior)
  342.         fDialogBehavior->fDismissed = false;
  343.     if (disableAbort == fAbortIsDisabled)
  344.         return disableAbort;
  345.     fAbortIsDisabled = disableAbort;
  346.     FailInfo fi; // we have promised not to fail (maybe SetPermAlloc(false)???)
  347.     if (fi.Try())
  348.     {
  349.         fAbortButton->DimState(disableAbort, kRedraw);
  350.         fAbortButton->SetEnable(!disableAbort);
  351.         fWindow->Update();
  352. #if qDebugAbortDisable
  353.         fprintf(stderr, "Changed abort disable for progress at $%lx: new state = %ld\n", long(this), long(disableAbort));
  354. #endif
  355.         fi.Success();
  356.         return !disableAbort; // swapped state
  357.     }
  358.     else // fail
  359.     {
  360. #if qDebug
  361.         ProgramBreak("Failed in TProgress::SetAbortDisable (but OK, just very unexpected)\n");
  362. #endif
  363.     }
  364. }
  365.  
  366. void TProgress::CreateNewWindow()
  367. {
  368.     if (fWindow)
  369.     {
  370.         fWindow->CloseByUser();
  371.         fWindow = nil;
  372.     }
  373. #if qDebug
  374. #define macroCheckSubView(view, x) if (!view) ProgramBreak(x);
  375. #else
  376. #define macroCheckSubView(view, x) FailNonObject(view)
  377. #endif
  378.     CRect oldResize = gStandardWindowSizeRect;
  379.     gStandardWindowSizeRect[topLeft] = CPoint(0, 0);
  380.     short id;
  381.     if (fIsModal)
  382.         id = fIsTwoLine ? kModalProgressTwoLineView : kModalProgressOneLineView;
  383.     else
  384.         id = fIsTwoLine ? kProgressTwoLineView : kProgressOneLineView;
  385.     fWindow = gViewServer->NewTemplateWindow(id, nil);
  386.     macroCheckSubView(fWindow, "did not find subview: window");
  387.     gStandardWindowSizeRect = oldResize;
  388.  
  389.     fProgressMeterView = (TProgressMeterView*)fWindow->FindSubView(kProgressMeter);
  390.     macroCheckSubView(fProgressMeterView, "did not find subview: kProgressMeter");
  391.  
  392.     fUpperText = (TStaticText*)fWindow->FindSubView(kProgressUpperText);
  393.     macroCheckSubView(fUpperText, "did not find subview: kProgressUpperText");
  394.  
  395.     if (fIsTwoLine)
  396.     {
  397.         fLowerText = (TStaticText*)fWindow->FindSubView(kProgressLowerText);
  398.         macroCheckSubView(fLowerText, "did not find subview: kProgressLowerText");
  399.     }
  400.     else
  401.         fLowerText = nil;
  402.  
  403.     fAbortButton = (TProgressAbortButton*)fWindow->FindSubView('cncl');
  404.     macroCheckSubView(fAbortButton, "did not find subview: cncl");
  405.     fAbortButton->SetProgressRef(this);
  406.  
  407. #if 1
  408.     fWindow->SetDialogItems(kNoIdentifier, fAbortButton->fIdentifier);
  409.     fDialogBehavior = fWindow->GetDialogBehavior();
  410.     fDialogBehavior->fDismissed = false;
  411. #else
  412.     TDialogBehavior *dbe = new TDialogBehavior();
  413.     dbe->IDialogBehavior(fIsModal, kNoIdentifier, fAbortButton->fIdentifier);
  414.     fWindow->AddBehavior(dbe);
  415.     fDialogBehavior = dbe;
  416. #endif
  417. }
  418.  
  419. //...................................................................... Housekeeping
  420. void TProgress::StartProgress(Boolean windowToFront)
  421. {
  422. #if qDebugProgressText
  423.     fprintf(stderr, "TProgress::StartProgress at $%lx, windowToFront = %hd\n", long(this), windowToFront);
  424. #endif
  425.     gApplication->UpdateAllWindows();
  426.     fIsWorking = true;
  427.     if (windowToFront)
  428.         fWindow->Select();
  429.     fWindow->Open();
  430.     fWindow->Show(true, kRedraw);
  431.     gApplication->UpdateAllWindows();
  432.     InvalidateMenus(); // for windows menu
  433.     fLastWorkTick = TickCount();
  434. }
  435.  
  436. void TProgress::UpdateCandyState()
  437. {
  438.     if (fIsCandy)
  439.     {
  440.         fLastWorkTick = TickCount();
  441.         InstallIdleUpdating();
  442.         SetIdleFreq(kCandyTicks);
  443.     }
  444.     else
  445.     {
  446.         RemoveIdleUpdating();
  447.         SetIdleFreq(kMaxIdleTime);
  448.     }
  449. }
  450.  
  451. void TProgress::SetWorkToDo(long todo)
  452. {
  453. #if qDebugProgressText
  454.     fprintf(stderr, "TProgress::SetWorkToDo at $%lx, todo = %ld\n", long(this), todo);
  455. #endif
  456.     fIsCandy = (todo == kCandyStribes);
  457.     UpdateCandyState();
  458.     fProgressMeterView->SetMax(todo);
  459. }
  460.  
  461. void TProgress::WorkDone()
  462. {
  463. #if qDebugProgressText
  464.     fprintf(stderr, "TProgress::WorkDone at $%lx\n", long(this));
  465. #endif
  466.     if (!fIsWorking)
  467.         return;
  468.     FailInfo fi; // we have promised not to fail (maybe SetPermAlloc(false)???)
  469.     if (fi.Try())
  470.     {
  471.         RemoveIdleUpdating();
  472.         SetIdleFreq(kMaxIdleTime);
  473.         fIsWorking = false;
  474. #if qDebug
  475.         if (!VerboseIsObject(fWindow))
  476.             ProgramBreak("fWindow is not object");
  477. #endif
  478.         fWindow->Show(false, kDontRedraw);
  479.         fi.Success();
  480.     }
  481.     else // fail
  482.     {
  483. #if qDebug
  484.         ProgramBreak("Fail in TProgress::WorkDone (OK, but very unexpected");
  485. #endif
  486.         fi.ReSignal();
  487.     }
  488. }
  489.  
  490. void TProgress::Worked(long delta)
  491. {
  492.     if (!fIsWorking)
  493.     {
  494. #if qDebug & 0
  495.         ProgramBreak("Worked called for non-working TProgress");
  496. #endif
  497.         return;
  498.     }
  499.     if (fIsCandy)
  500.         UpdateCandyState();
  501.     else
  502.         fProgressMeterView->DeltaValue(delta);
  503. }
  504.  
  505. long TProgress::GetWork()
  506. {
  507.     if (!fIsWorking)
  508.     {
  509. #if qDebug
  510.         ProgramBreak("GetWork called for non-working TProgress");
  511. #endif
  512.     }
  513.     return fProgressMeterView->GetValue();
  514. }
  515.  
  516. void TProgress::SetWorkDone(long work)
  517. {
  518. #if 0
  519.     fprintf(stderr, "TProgress::SetWorkDone at $%lx, work = %ld\n", long(this), work);
  520. #endif
  521.     if (!fIsWorking)
  522.     {
  523. #if qDebug & 0
  524.         ProgramBreak("SetWorkDone called for non-working TProgress");
  525. #endif
  526.         return;
  527.     }
  528.     UpdateCandyState();
  529.     fProgressMeterView->SetValue(work);
  530. }
  531.  
  532. long TProgress::GetWorkDone()
  533. {
  534.     return fProgressMeterView->GetValue();
  535. }
  536.  
  537. pascal Boolean TProgress::DoIdle(IdlePhase phase)
  538. {
  539.     fProgressMeterView->UpdateCandy();
  540.     if (fCoHandlerInstalled && TickCount() - fLastWorkTick > kCandyTimeout)
  541.         RemoveIdleUpdating();
  542.     return inherited::DoIdle(phase);
  543. }
  544.  
  545. void TProgress::InstallIdleUpdating()
  546. {
  547.     if (!fCoHandlerInstalled)
  548.     {
  549. #if qDebugCandy
  550.         fprintf(stderr, "TProgress at $%lx, Installs cohandler\n", long(this));
  551. #endif
  552.         gApplication->InstallCohandler(this, true);
  553.         fCoHandlerInstalled = true;
  554.     }
  555. }
  556.  
  557. void TProgress::RemoveIdleUpdating()
  558. {
  559.     if (fCoHandlerInstalled)
  560.     {
  561. #if qDebugCandy
  562.         fprintf(stderr, "TProgress at $%lx, removes cohandler\n", long(this));
  563. #endif
  564.         gApplication->InstallCohandler(this, false);
  565.         fCoHandlerInstalled = false;
  566.     }
  567. }
  568.  
  569. //......................................................... Texts
  570. void TruncProgressText(TStaticText *st, CStr255 &s)
  571. {
  572.     GrafPtr oldPort;
  573.     GetPort(oldPort);
  574.     SetPort(gWorkPort);
  575.     TextStyle ts = st->fTextStyle;
  576.     SetPortTextStyle(ts);
  577.     TruncString(short(st->fSize.h), s, smTruncEnd);
  578.     SetPort(oldPort);
  579. }
  580.  
  581. void TProgress::SetUpperText(const CStr255 &msg)
  582. {
  583. #if qDebugProgressText
  584.     fprintf(stderr, "TProgress::SetUpperText at $%lx, text = '%s'\n", long(this), (char*)msg);
  585. #endif
  586.     if (fUpperText)
  587.     {
  588.         CStr255 text(msg);
  589.         TruncProgressText(fUpperText, text);
  590.         fUpperText->SetText(text, kRedraw);
  591.     }
  592.     else
  593.     {
  594. #if qDebug
  595.         fprintf(stderr, "TProgress::SetUpperText at $%lx called when fUpperText == nil\n", long(this));
  596. #endif
  597.     }
  598.     if (fIsWorking)
  599.         fWindow->Update();
  600. }
  601.  
  602. void TProgress::SetUpperText(short id)
  603. {
  604.     CStr255 s;
  605.     MyGetIndString(s, id);
  606.     SetUpperText(s);
  607. }
  608.  
  609. void TProgress::SetLowerText(const CStr255 &msg)
  610. {
  611. #if qDebugProgressText
  612.     fprintf(stderr, "TProgress::SetLowerText at $%lx, text = '%s'\n", long(this), (char*)msg);
  613. #endif
  614.     if (fLowerText)
  615.     {
  616.         CStr255 text(msg);
  617.         TruncProgressText(fLowerText, text);
  618.         fLowerText->SetText(text, kRedraw);
  619.     }
  620.     else
  621.     {
  622. #if qDebug
  623.         fprintf(stderr, "TProgress::SetLowerText at $%lx called when fLowerText == nil\n", long(this));
  624. #endif
  625.     }
  626.     if (fIsWorking)
  627.         fWindow->Update();
  628. }
  629.  
  630. void TProgress::SetLowerText(short id)
  631. {
  632.     CStr255 s;
  633.     MyGetIndString(s, id);
  634.     SetLowerText(s);
  635. }
  636.  
  637. void TProgress::SetText(const CStr255 &msg)
  638. {
  639.     if (fIsTwoLine)
  640.         SetLowerText(msg);
  641.     else
  642.         SetUpperText(msg);
  643. }
  644.  
  645. void TProgress::SetText(short id)
  646. {
  647.     if (fIsTwoLine)
  648.         SetLowerText(id);
  649.     else
  650.         SetUpperText(id);
  651. }
  652.  
  653. void TProgress::ClearTexts()
  654. {
  655.     if (fUpperText)
  656.         fUpperText->SetText(gEmptyString, kRedraw);
  657.     if (fLowerText)
  658.         fLowerText->SetText(gEmptyString, kRedraw);
  659.     if (fIsWorking)
  660.         fWindow->Update();
  661. }
  662.  
  663. void TProgress::SetTitle(const CStr255 &title)
  664. {
  665. #if qDebugProgressText
  666.     fprintf(stderr, "TProgress::SetTitle at $%lx, title = '%s'\n", long(this), (char*)title);
  667. #endif
  668.     if (fWindow)
  669.     {
  670.         CStr255 text(title);
  671.         TruncSystemFontString(short(fWindow->fSize.h - 64), text, smTruncEnd);
  672.         fWindow->SetTitle(text);
  673.     }
  674.     else
  675.     {
  676. #if qDebug
  677.         fprintf(stderr, "TProgress::SetTitle at $%lx called when fWindow == nil\n", long(this));
  678. #endif
  679.     }
  680. }
  681.  
  682. void TProgress::SetTitle(short id)
  683. {
  684.     CStr255 s;
  685.     MyGetIndString(s, id);
  686.     SetTitle(s);
  687. }
  688.  
  689. void TProgress::Abort()
  690. {
  691.     if (fWindow && fDialogBehavior)
  692.         fDialogBehavior->fDismissed = false;
  693.     if (!fIsWorking)
  694.     {
  695. #if qDebug
  696.         ProgramBreak("Abort called for non-working TProgress");
  697. #endif
  698.         return;
  699.     }
  700.     if (fAbortIsDisabled)
  701.         PanicExitToShell("Abort called for TProgress with fAbortIsDisabled == TRUE");
  702. #if qDebug
  703.     fprintf(stderr, "TProgress at %lx: aborting\n", long(this));
  704. #endif
  705.     if (fThread)
  706.         fThread->Abort();
  707.     else
  708.     {
  709. #if qDebug
  710.         ProgramBreak("Abort called for TProgress without a thread");
  711. #endif
  712.         Failure(minErr, 0);
  713.     }
  714. }
  715.  
  716. TWindow *TProgress::GetWindow()
  717. {
  718.     if (fWindow)
  719.         return fWindow;
  720.     else
  721.         PanicExitToShell("TProgress::GetWindow called when fWindow == nil");
  722. }
  723.  
  724. Boolean TProgress::IsWorking()
  725. {
  726.     return fIsWorking;
  727. }
  728.