home *** CD-ROM | disk | FTP | other *** search
- /* A diagnostic display (a Director). */
-
- #include <TCL>
- #include "GLOBAL.h"
- #include "commands.h"
- #include "CDiagnostic.h"
- #include "CUtility.h"
- #include "CPanelMenus.h"
- #include "CLoader.h"
- #include "WIND.h"
- #include "SCPN.h"
- #include "STTX.h"
- #include "STR.h"
- #include "sizes.h"
- #include "chars.h"
- #include <stdio.h>
- #include <string.h>
-
- #define BUFFSIZE 1000 /* Max characters of text buffered. We have
- a fixed size buffer (handle). */
-
- LOCAL enum {
- NOT_INITIALISED,
- RUNNING,
- DISABLED,
- TERMINATED
- } theState = NOT_INITIALISED;
-
- LOCAL CDiagnostic *theDiagnostic;
-
- NEW void CDiagnostic::IDiagnostic()
- {
- Str255 buff;
- int size;
- Handle han;
-
- inherited::IDirector(gApplication);
-
- /*Create and initialise the director's window. */
- itsWindow = new(CWindow);
- itsWindow->IWindow(DIAGNOSTIC_wind, FALSE, gDesktop, this);
-
- /*We don't use the decorator for this window: we want it placed at the
- bottom right of the screen, as per the WIND resource. */
-
- /*Create and set up the scroll-pane. */
- itsScrollPane = new(CScrollPane);
- itsScrollPane->IViewRes('ScPn', DIAGNOSTIC_scpn, itsWindow, gApplication);
- /* The enclosure is the diagnostic window.
- The supervisor (to which we pass
- everything) is the application. */
-
- itsScrollPane->FitToEnclFrame(TRUE, TRUE);
-
- itsStaticText = new(CStaticText);
- itsStaticText->IViewRes('StTx', DIAGNOSTIC_sttx, itsScrollPane, gApplication);
-
- itsStaticText->FitToEnclosure(TRUE, TRUE);
- itsScrollPane->InstallPanorama(itsStaticText);
-
- gUtility->GetFontAndSize(DIAGNOSTIC_index, buff, &size);
- itsStaticText->SetFontName(buff);
- itsStaticText->SetFontSize(size);
-
- /*Allocate the buffer for the text. */
- han = gUtility->MustNewHandle(BUFFSIZE);
- itsTextHan = han;
- itsTextInUse = 0L;
-
- /*Force the first refresh. */
- needUpdate = TRUE;
- Update();
-
- itsWindow->Show();
- itsWindow->Select();
- }
-
- /* Dispose() clears down the state flag so that any trailing diagnostics
- are discarded. */
-
- OVERRIDE void CDiagnostic::Dispose()
- {
- theState = TERMINATED;
- inherited::Dispose();
- }
-
- OVERRIDE void CDiagnostic::UpdateMenus()
- {
- inherited::UpdateMenus();
- gBartender->DisableCmd(cmdClose);
- }
-
- /* FlushLine - get rid of the leading line of text in the buffer, copying
- all the following stuff down. */
-
- PRIVATE void CDiagnostic::FlushLine()
- {
- char *p0, *p;
-
- HLock(itsTextHan);
-
- gUtility->Assert("CDiagnostic::FlushLine", itsTextInUse > 0L);
-
- /*Point p0 at the start, advance p to the start of the second line.*/
- p0 = *itsTextHan;
- p = p0;
-
- while (*p != '\r') p++;
- p++;
-
- /*Move the text we want (everything except the stuff between p0 and p) down
- to p0:*/
- BlockMove(p, p0, itsTextInUse - (p - p0));
-
- itsTextInUse -= (p - p0);
-
- HUnlock(itsTextHan);
- }
-
- PRIVATE void CDiagnostic::AppendText(char *text) /* text is a C string. */
- {
- char *p;
- Size len = strlen(text);
-
- HLock(itsTextHan);
-
- p = (char *)(*itsTextHan) + itsTextInUse; /* p := free space. */
-
- if (itsTextInUse > 0L) {
- *p++ = '\r'; /* CR after previous line. */
- itsTextInUse++;
- }
-
- BlockMove(text, p, len); /* p[1...] := text. */
- itsTextInUse += len;
-
- HUnlock(itsTextHan);
- }
-
- NEW void CDiagnostic::Update()
- {
- if (needUpdate) {
- HLock(itsTextHan);
- itsStaticText->SetTextPtr(*itsTextHan, itsTextInUse);
- HUnlock(itsTextHan);
-
- itsStaticText->ScrollToSelection();
-
- needUpdate = FALSE;
- }
- }
-
- /* The main method: Diagnose takes arguments just like printf(), and sends them
- to the diagnostic window. */
-
- NEW void CDiagnostic::Diagnose(char *text)
- {
- Size thisLen = strlen(text);
-
- while (itsTextInUse + thisLen >= BUFFSIZE)
- /* Don't forget that we need space for separating CR
- (except if this is the first message). */
- FlushLine();
-
- AppendText(text);
- needUpdate = TRUE;
- }
-
- /* Vanilla procedures for the outside world. Note the local CDiagnostic object
- and the locally-remembered state of the diagnostic machinery. */
-
- GLOBAL void g_Diagnostic(format, a, b, c, d, e, f, g)
- char *format;
- {
- char buffer[256];
-
- switch (theState) {
- case NOT_INITIALISED:
- if (Count1Resources('CODE') == 0) { /* Under THINK C. */
- theState = DISABLED; /* ARGH! Creating the diagnostic window
- might generate diagnostics from
- another director (e.g. dashboard). */
- theDiagnostic = new(CDiagnostic);
- theDiagnostic->IDiagnostic();
- theState = RUNNING;
- } else { /* We're a compiled app. */
- theState = DISABLED;
- return;
- }
-
- break;
-
- case RUNNING:
- break; /* No problem. */
-
- case DISABLED:
- case TERMINATED:
- return; /* Can't do any diagnostics. */
- }
-
- sprintf(buffer, format, a, b, c, d, e, f, g);
- theDiagnostic->Diagnose(buffer);
- }
-
- GLOBAL void g_UpdateDiags()
- {
- if (theState == RUNNING) theDiagnostic->Update();
- }
-