home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-09-29 | 20.5 KB | 782 lines | [TEXT/MMCC] |
- /**********************************************************************
- CNeoWindow.cp
-
- This window behaves differently than CWindow when it is Zoomed.
- It is supposed to move to the center of the screen when the Zoom
- button is pressed. So no matter where it is, it will always
- center when Zoom is pressed.
-
- The "Direction" argument to Zoom is meaningless and is ignored.
- **********************************************************************/
-
- #include "NeoTypes.h"
- #include "CNeoWindow.h"
- #include CNeoDocNativeH
- #include CNeoDatabaseNativeH
- #include CNeoMetaClassH
- #include CNeoIndexIteratorH
- #include CNeoPersistNativeH
- #include "CRawText.h"
- #include <stdlib.h>
- #include <Timer.h>
- #include <Fonts.h>
- #include <UDrawingState.h>
- #include "LEditField.h"
- #include "LButton.h"
- #include "CFiller.h"
-
- #include "CIDIndex.h"
-
- #ifdef qNeoThreads
- static short default_threads[kMaxPhase + 1] = { 1, 2, 2, 2, 2 };
- #endif
-
- long gLoopOverhead; // Timer Manager Overhead
-
- CNeoWindow::CNeoWindow(const ResIDT aResID, CNeoDocPP *aDocument)
- : LWindow(aResID, windAttr_Regular + windAttr_Enabled + windAttr_Targetable, aDocument)
- {
- short height;
- short index, j;
- short hpos;
- short vpos;
- long value;
- Point pt;
- Rect bounds;
- Rect rect;
-
- #ifdef qNeoThreads
- fThreadCount = 0;
- for (index = 0; index < kMaxThreads; index++)
- fThreadInfo[index].thread = nil;
- #endif
-
- fRefresh = TRUE;
- fIterator = nil;
-
- /**
- ** Set the Min and Max value the window can be resized.
- ** Note that we really don't want the user to resize it
- ** so we make the min and max numbers the same.
- **/
- SetRect(&bounds, 0, 0, 390, 200);
- pt.h = (qd.screenBits.bounds.right - (bounds.right - bounds.left)) / 2;
- pt.v = (qd.screenBits.bounds.bottom - (bounds.bottom - bounds.top)) / 3;
- height = GetMBarHeight() + 1;
- pt.v = (pt.v > height ? pt.v : height);
- rect.top = pt.v;
- rect.bottom = bounds.bottom + (pt.v - bounds.top);
- rect.left = pt.h;
- rect.right = bounds.right + (pt.h - bounds.left);
- DoSetBounds(rect);
-
- // -----------------------------------------------------------
- // Set the thread counts for each phase
- // -----------------------------------------------------------
-
- for (index = kMinPhase; index <= kMaxPhase; index++) {
- fPhaseInfo[index].dirty = FALSE;
- #ifdef qNeoThreads
- NeoAssert(default_threads[index] <= kMaxThreads);
- fPhaseInfo[index].threadCount = default_threads[index];
- #endif
- }
-
- // -----------------------------------------------------------
- // Make the Stat Text Phase names going down
- // -----------------------------------------------------------
- vpos = V_TOTAL;
-
- for (index = kMinPhase; index <= kMaxPhase; index++) {
- NeoPhaseNames[index] = new CRawText(this, PhaseNames[index], LEFT_STAT, vpos, PHASE_NAME_WID, STAT_HGT);
- NeoPhaseNames[index]->SetTextTraitsID(NeoLeftStyleID);
- vpos += V_DIST;
- }
-
- // -----------------------------------------------------------
- // Make the object size static text item.
- // -----------------------------------------------------------
-
- vpos += 14;
- fSizeStatic = new CRawText(this, "\pObject Size:", LEFT_STAT +75, vpos, PHASE_NAME_WID, STAT_HGT);
- fSizeStatic->SetTextTraitsID(NeoLeftStyleID);
-
- // -----------------------------------------------------------
- // Make the Editable Text boxes going down
- // -----------------------------------------------------------
- vpos = V_TOTAL;
-
- for (index = kMinPhase; index <= kMaxPhase; index++) {
- NeoEditTexts[index] = new LEditField();
- NeoEditTexts[index]->SetTextTraitsID(NeoTextStyleID);
- NeoEditTexts[index]->SetKeyFilter((KeyFilterFunc)UKeyFilters::IntegerField);
- NeoEditTexts[index]->Enable();
- NeoEditTexts[index]->SelectAll();
- NeoEditTexts[index]->PutInside(this);
- NeoEditTexts[index]->SetDescriptor(Txts);
- NeoEditTexts[index]->ResizeFrameTo(TOT_WID, TOT_HGT, FALSE);
- NeoEditTexts[index]->PlaceInSuperImageAt(H_TOTAL, vpos, FALSE);
- NeoEditTexts[index]->SetSuperCommander(this);
- value = default_vals[index];
- NeoEditTexts[index]->SetValue(value);
- vpos += V_DIST;
- }
- NeoEditTexts[kMinPhase]->Activate();
-
- // -----------------------------------------------------------
- // Make the object size static text items.
- // -----------------------------------------------------------
-
- vpos += 14;
- fSizeText = new LEditField();
- fSizeText->SetTextTraitsID(NeoTextStyleID);
- fSizeText->SetKeyFilter((KeyFilterFunc)UKeyFilters::IntegerField);
- fSizeText->Enable();
- fSizeText->SelectAll();
- fSizeText->PutInside(this);
- fSizeText->SetDescriptor(Txts);
- fSizeText->ResizeFrameTo(SIZE_WID, TOT_HGT, FALSE);
- fSizeText->PlaceInSuperImageAt(H_TOTAL +75, vpos, FALSE);
- fSizeText->SetSuperCommander(this);
- value = CFiller::GetLength();
- fSizeText->SetValue(value);
-
- // -----------------------------------------------------------
- // Make the Stat Text boxes going down and across
- // -----------------------------------------------------------
- vpos = V_STAT_START;
-
- for (index = kMinPhase; index <= kMaxPhase; index++) {
- hpos = H_STAT_START;
- for (j = kSoFar; j <= kMaxCol; j++) {
- switch (j) {
- case kSoFar:
- case kPerObject:
- NeoRawTexts[index][j] = new CRawText(this, Txts, hpos, vpos, STAT_WID, STAT_HGT);
- break;
-
- case kTotal:
- NeoRawTexts[index][j] = new CTimeText(this, Txts, hpos, vpos, STAT_WID, STAT_HGT);
- break;
- }
- NeoRawTexts[index][j]->SetTextTraitsID(NeoRightStyleID);
- hpos += H_DIST;
- }
- vpos += V_DIST;
- }
-
- // -----------------------------------------------------------
- // Create the Go button and disable it.
- // -----------------------------------------------------------
- NeoGoButton = new LButton();
- NeoGoButton->PutInside(this);
- NeoGoButton->SetGraphics(GO_RES_ID, GO_RES_ID +1);
- NeoGoButton->PlaceInSuperImageAt(GO_LFT, GO_TOP, FALSE);
- NeoGoButton->ResizeFrameTo(GO_WID, GO_HGT, FALSE);
- NeoGoButton->SetValueMessage(cmdGO);
- NeoGoButton->Show();
- NeoGoButton->Activate();
- NeoGoButton->Enable();
- NeoGoButton->AddListener(this);
-
- // -----------------------------------------------------------
- // Create the Stop button, and disable it.
- // -----------------------------------------------------------
- NeoStopButton = new LButton();
- NeoStopButton->PutInside(this);
- NeoStopButton->SetGraphics(STOP_RES_ID, STOP_RES_ID +1);
- NeoStopButton->PlaceInSuperImageAt(STOP_LFT, STOP_TOP, FALSE);
- NeoStopButton->ResizeFrameTo(STOP_WID, STOP_HGT, FALSE);
- NeoStopButton->SetValueMessage(cmdSTOP);
- NeoStopButton->Show();
- NeoStopButton->Activate();
- NeoStopButton->Disable();
- NeoStopButton->AddListener(this);
-
- //------------------------------------------------------------
- // Now put in the default max value
- //------------------------------------------------------------
- for (index = kMinPhase; index <= kMaxPhase; index++) {
- maxValue[index] = default_maxs[index];
- minValue[index] = 0;
- }
-
- ClearStatPanes();
-
- /**
- ** Set the button state flag
- **/
- fState = kStop;
-
- fPhase = kNoPhase; /* No phase yet */
-
- // These three values are the running values that change
- col_index = kMinCol;
- for (index = kMinCol; index <= kMinCol; index++)
- col_value[index] = 0;
-
- //
- // Init the fields in the array. The default values
- // will be coming from the text in the TextEdit boxes.
- //
- for (index = kMinPhase; index <= kMaxPhase; index++) {
- fPhaseInfo[index].target = 0;
- fPhaseInfo[index].done = 0;
- fPhaseInfo[index].committed = 0;
- fPhaseInfo[index].soFar = 0;
- }
-
- srand((unsigned int)clock());
-
- Enable();
- Select();
- Show();
-
- NeoStopButton->Disable();
- NeoGoButton->Disable();
- NeoGoButton->Enable();
- }
-
- CNeoWindow::~CNeoWindow(void)
- {
- #ifdef qNeoThreads
- killThreads();
- #endif
- }
-
- /***
- * DrawSelf
- *
- * In this method, you draw whatever you need to display in
- * your pane. The area parameter gives the portion of the
- * pane that needs to be redrawn. Area is in frame coordinates.
- *
- ***/
-
- void CNeoWindow::DrawSelf(void)
- {
- Rect rect;
- Rect frame;
- PicHandle pict;
-
- CalcLocalFrameRect(frame);
- StColorPenState::Normalize();
-
- pict = ::GetPicture(kTitlePICTID);
- NeoFailNil(pict);
- rect = (*pict)->picFrame;
- ::OffsetRect(&rect, -rect.left, -rect.top);
- ::OffsetRect(&rect, H_TOTAL, 15);
- ::DrawPicture(pict, &rect);
- }
-
- /********************************************************************
- For a particular index, get the total number converted from the
- TextBox string, and compare it with the limits, and if out of
- limits, adjust them to be back within the given limits.
- ********************************************************************/
- long CNeoWindow::GetTotalNum(short index)
- {
- long value;
-
- if (index < kMinPhase || index > kMaxPhase)
- return 0;
-
- value = NeoEditTexts[index]->GetValue();
- if (value > maxValue[index]) {
- NeoEditTexts[index]->SetValue(maxValue[index]);
- value = maxValue[index];
- }
- if (value < minValue[index]) {
- NeoEditTexts[index]->SetValue(minValue[index]);
- value = minValue[index];
-
- }
- return(value);
- }
-
- /*******************************************************************
- ClearStatPanes - Clears out the Stat text panes containing the
- numbers calculated from the run. Sets the numbers to Zero
- in preparation for the run.
- *******************************************************************/
- void CNeoWindow::ClearStatPanes(void)
- {
- short row;
- short column;
-
- for (row = kMinPhase; row <= kMaxPhase; row++)
- for (column = kSoFar; column <= kMaxCol; column++) {
- NeoRawTexts[row][column]->SetValue(0);
- NeoRawTexts[row][column]->Refresh();
- }
- }
-
- /*******************************************************************
- UpdateCol - Given an index into the phase array ( 0 - 4), and
- an index into the row (0 - 2), we put the value into the
- static text area of the dialog box.
- *******************************************************************/
- void CNeoWindow::UpdateCol(short aPhase, short aRow, long aValue)
- {
- // Do error bounds checking, because it spits and sparksten
- // if these arrays are out of bounds.
-
- if (aPhase > kMaxPhase || aPhase < kMinPhase || aRow > kMaxCol || aRow < kMinCol)
- return;
-
- NeoRawTexts[aPhase][aRow]->SetValue(aValue);
- NeoRawTexts[aPhase][aRow]->Refresh();
- }
-
-
- short CNeoWindow::getPhase(void) const
- {
- return fPhase;
- }
-
- long CNeoWindow::getPhaseTarget(const short aPhase) const
- {
- return fPhaseInfo[aPhase].target;
- }
-
- Boolean CNeoWindow::getState(void) const
- {
- return fState;
- }
-
- #define CR 0x24
- /*******************************************************************
-
- *******************************************************************/
- Boolean CNeoWindow::HandleKeyPress(const EventRecord &aEvent)
- {
- Boolean handled;
-
- if ((aEvent.message&charCodeMask) == CR) {
- if (fState == kStop)
- ListenToMessage(cmdGO, nil);
- else
- ListenToMessage(cmdSTOP, nil);
- handled = TRUE;
- }
- else
- handled = LCommander::HandleKeyPress(aEvent);
-
- return handled;
- }
-
- #ifdef qNeoThreads
- void CNeoWindow::killThreads(void)
- {
- short index;
-
- for (index = 0; index < kMaxThreads; index++) {
- if (fThreadInfo[index].state == kAlive) {
- NeoAssert(fThreadInfo[index].thread);
- fThreadInfo[index].state = kDie;
- CNeoThreadNative::Yield(fThreadInfo[index].thread);
- fThreadInfo[index].thread = nil;
- }
- }
- }
- #endif
-
- void CNeoWindow::ListenToMessage(MessageT aMessage, void *aParam)
- {
- switch (aMessage) {
- case cmdGO:
- setState(kStart);
- break;
-
- case cmdSTOP:
- setState(kStop);
- break;
- }
- }
-
- void CNeoWindow::setDocument(CNeoDocPP *aDocument)
- {
- CNeoDatabasePP * database;
-
- database = aDocument->getDatabase();
-
- if (database)
- checkDatabaseState();
- }
-
- void CNeoWindow::checkDatabaseState(void)
- {
- long tryFor;
- long actual;
- CNeoDocPP * document = (CNeoDocPP *)GetSuperCommander();
- CNeoDatabase * database = document->getDatabase();
-
- fPhaseInfo[kInsert].delta = database->getObjectCount(kFillerID, FALSE);
- if (fPhaseInfo[kInsert].delta) {
- UpdateCol(kInsert, kSoFar, fPhaseInfo[kInsert].delta);
- tryFor = database->getVersion();
- actual = CFiller::SetLength(tryFor);
- NeoAssert(actual <= tryFor);
- fSizeText->SetValue(actual);
- }
- else {
- tryFor = fSizeText->GetValue();
- actual = CFiller::SetLength(tryFor);
- database->setVersion(actual);
- if (actual != tryFor)
- fSizeText->SetValue(actual);
- }
- }
-
- void CNeoWindow::setPhase(const short aPhase)
- {
- #ifdef qNeoThreads
- short index;
- short count;
-
- if (aPhase >= kMinPhase &&
- aPhase <= kMaxPhase)
- count = fPhaseInfo[aPhase].threadCount;
- else {
- if (fIterator) {
- delete fIterator;
- fIterator = nil;
- }
- count = 0;
- }
-
- for (index = 0; index < count; index++) {
- fThreadInfo[index].window = this;
- fThreadInfo[index].phase = aPhase;
- fThreadInfo[index].state = kAlive;
- if (index >= fThreadCount) {
- fThreadInfo[index].thread = new CBenchThread(&fThreadInfo[index]);
- fThreadCount++;
- fThreadInfo[index].thread->Resume();
- }
- }
-
- for (index = fThreadCount; index > count; index--)
- fThreadInfo[index].state = kDie;
- #endif
-
- fPhase = aPhase;
- }
-
- void CNeoWindow::setState(const Boolean aState)
- {
- short index;
- short phase;
-
- if (aState == kStop) {
- #ifdef qNeoThreads
- killThreads();
- #endif
- StopIdling();
- phase = kNoPhase;
- NeoStopButton->Disable();
- NeoGoButton->Enable();
- }
- else {
- for (index = kMinPhase; index <= kMaxPhase; index++) {
- fPhaseInfo[index].target = GetTotalNum(index);
- fPhaseInfo[index].done = 0;
- fPhaseInfo[index].delta = 0;
- fPhaseInfo[index].committed = 0;
- fPhaseInfo[index].soFar = 0;
- }
-
- checkDatabaseState();
-
- if (fPhaseInfo[kInsert].delta < fPhaseInfo[kInsert].target)
- phase = kMinPhase;
- else
- phase = kRandomly;
-
- StartIdling();
- NeoGoButton->Disable();
- NeoStopButton->Enable();
- }
- NeoGoButton->Refresh();
- NeoStopButton->Refresh();
-
- fState = aState;
-
- setPhase(phase);
- }
-
- /******************************************************************************
- SpendTime
- ******************************************************************************/
- void CNeoWindow::SpendTime(const EventRecord &aEvent)
- {
- short index;
- long loops = 0;
- CNeoDocPP * document = (CNeoDocPP *)GetSuperCommander();
- CNeoDatabase * database = document->getDatabase();
-
- NeoUsed(aEvent);
- NeoUsed(loops);
-
- #ifndef qNeoThreads
- TMTask timer;
-
- doSomeWork(fPhase, &timer);
- #endif
-
- for (index = kMinPhase; index <= kMaxPhase; index++) {
- if (fPhaseInfo[index].dirty) {
- UpdateCol(index, kSoFar, fPhaseInfo[index].delta + fPhaseInfo[index].committed);
- UpdateCol(index, kPerObject, ((double)fPhaseInfo[index].committed / (double)(fPhaseInfo[index].soFar ? fPhaseInfo[index].soFar : 1)) * 1000000);
- UpdateCol(index, kTotal, fPhaseInfo[index].soFar);
- fPhaseInfo[index].dirty = FALSE;
- }
- fRefresh = FALSE;
- }
-
- if (fPhase > kMaxPhase)
- setState(kStop);
-
- #ifdef qNeoThreads
- loops = 0;
- while (!fRefresh) {
- LThread::Yield();
- #ifdef qNeoDebug
- loops++;
- if (loops > 1000) {
- loops = 0;
- break;
- }
- #endif
- }
- #endif
- }
-
- /******************************************************************************
- doSomeWork
- ******************************************************************************/
- void CNeoWindow::doSomeWork(const short aPhase, TMTask *aTimer)
- {
- long done;
- long IveDone = 0;
- long delta;
- long quantum;
- NeoID id;
- CNeoPersist * object;
- CNeoDocPP * document = (CNeoDocPP *)GetSuperCommander();
- CNeoDatabase * oldDatabase = gNeoDatabase;
- CNeoDatabase * database = document->getDatabase();
- TMTask updateTask;
-
- #ifdef qNeoThreads
- quantum = 500 * fPhaseInfo[aPhase].threadCount;
- #else
- quantum = 500;
- #endif
- if (fPhaseInfo[aPhase].delta + fPhaseInfo[aPhase].done < fPhaseInfo[aPhase].target) {
- gNeoDatabase = database;
-
- updateTask.tmAddr = nil;
- updateTask.qType = 0;
- updateTask.tmCount = 0;
- updateTask.tmWakeUp = 0;
- updateTask.tmReserved = 0;
- InsXTime((QElem *)&updateTask);
- PrimeTime((QElem *)&updateTask, quantum);
-
- aTimer->tmAddr = nil;
- aTimer->qType = 0;
- aTimer->tmCount = 0;
- aTimer->tmWakeUp = 0;
- aTimer->tmReserved = 0;
- InsXTime((QElem *)aTimer);
- PrimeTime((QElem *)aTimer, k30MicroMinutes);
-
- while ((updateTask.qType&0x8000) &&
- (fPhaseInfo[aPhase].delta + fPhaseInfo[aPhase].done < fPhaseInfo[aPhase].target)) {
-
- fPhaseInfo[aPhase].done++;
- IveDone++;
-
- switch (aPhase) {
- case kInsert:
- /*------------------------------------------------------*/
- /* Perform the code for record insertion sequence */
- /*------------------------------------------------------*/
- object = new CFiller;
- FailNIL(object);
- delta = fPhaseInfo[kInsert].delta;
- done = fPhaseInfo[kInsert].done;
- object->fID = delta + done;
- database->addObject(object);
- document->setDirty();
- object->unrefer();
- break;
-
- case kRandomly:
- /*------------------------------------------------------*/
- /* Perform the code for randomly searching sequence */
- /*------------------------------------------------------*/
- id = (rand()&0x7FFFFFFF) % fPhaseInfo[kInsert].target;
- if (!id)
- id = fPhaseInfo[kInsert].target / 2;
- object = (CFiller *)CFiller::FindByID(database, kFillerID, id, FALSE, nil, nil);
- NeoAssert(object);
- object->unrefer();
- break;
-
- case kSerially:
- /*------------------------------------------------------*/
- /* Serially iterate over a class of objects */
- /*------------------------------------------------------*/
- if (fIterator) {
- object = fIterator->nextObject();
- if (!object) {
- fIterator->reset();
- object = fIterator->currentObject();
- }
- }
- else {
- fIterator = new CNeoIndexIterator(database, kFillerID, nil, FALSE, FALSE);
- object = fIterator->currentObject();
- }
- NeoAssert(object);
- break;
-
- case kChange:
- /*------------------------------------------------------*/
- /* Perform the code for Change sequence here */
- /*------------------------------------------------------*/
- if (fIterator) {
- object = fIterator->nextObject();
- if (!object) {
- fIterator->reset();
- object = fIterator->currentObject();
- }
- }
- else {
- fIterator = new CNeoIndexIterator(database, kFillerID);
- object = fIterator->currentObject();
- }
- NeoAssert(object);
- object->autoReferTo();
- object->setDirty();
- object->autoUnrefer();
- document->setDirty();
- break;
-
- case kDelete:
- /*------------------------------------------------------*/
- /* Perform the code for Delete sequencing here */
- /*------------------------------------------------------*/
- if (!fIterator)
- fIterator = new CNeoIndexIterator(database, kFillerID);
- object = fIterator->currentObject();
- NeoAssert(object);
- object->autoReferTo();
- fIterator->removeCurrent();
- object->autoUnrefer();
- break;
- }
- }
-
- if (database->isOpen() &&
- document->isDirty() &&
- CNeoPersist::FCacheUsed > (CNeoPersist::FCacheSize>>1)) {
- if (aPhase == kDelete &&
- fPhaseInfo[aPhase].delta + fPhaseInfo[aPhase].done >= fPhaseInfo[aPhase].target)
- database->commit(TRUE);
- else
- database->commit(FALSE);
- document->setDirty(FALSE);
- }
-
- RmvTime((QElem *)aTimer);
- RmvTime((QElem *)&updateTask);
-
- if (aTimer->tmCount > 0)
- fPhaseInfo[aPhase].soFar += -(k30MicroMinutes + aTimer->tmCount * 1000) - gLoopOverhead;
- else
- fPhaseInfo[aPhase].soFar += -(k30MicroMinutes - aTimer->tmCount) - gLoopOverhead;
- fPhaseInfo[aPhase].committed += IveDone;
- fPhaseInfo[aPhase].dirty = TRUE;
- fRefresh = TRUE;
-
- gNeoDatabase = oldDatabase;
- }
- else {
- setPhase(aPhase +1);
- if (fIterator) {
- fIterator->setForward(!fIterator->isForward());
- fIterator->reset();
- }
- }
- }
-
- void CNeoWindow::ClickInZoom(const EventRecord& inMacEvent, short inZoomDirection) // Zoom can be in or out
- {
- // Don't allow zooming
- }
-
- #ifdef qNeoThreads
- CBenchThread::CBenchThread(ThreadInfo *aInfo, const NeoThreadType aType, void **aArg, const Size aStackSize, const NeoThreadOptions aOptions)
- : CNeoThreadNative(aType, aArg, aStackSize, aOptions)
- {
- fSetTimer = FALSE;
- fTimer.qType = 0;
- fInfo = aInfo;
- }
-
- long CBenchThread::run(void)
- {
- while (fInfo->state == kAlive) {
- fInfo->window->doSomeWork(fInfo->phase, &fTimer);
-
- LThread::Yield();
- }
-
- fInfo->thread = nil;
-
- return fResult;
- }
-
- // ---------------------------------------------------------------------------
- // • handleSwapIn
- // ---------------------------------------------------------------------------
- // Callback to the Thread Manager.
- //
- void CBenchThread::handleSwapIn(void)
- {
- inherited::handleSwapIn();
-
- // turn timers back on
- if (fSetTimer) {
- InsXTime((QElem *)&fTimer);
- PrimeTime((QElem *)&fTimer, 0);
- }
- }
-
- // ---------------------------------------------------------------------------
- // • handleSwapOut
- // ---------------------------------------------------------------------------
- // Callback to the Thread Manager.
- //
- void CBenchThread::handleSwapOut(void)
- {
- // turn timers off
- fSetTimer = (((fTimer.qType)&0x8000) != 0);
- RmvTime((QElem *)&fTimer);
- if (fSetTimer) {
- // if (fTimer.tmCount > 0)
- // fTimer.tmCount += gLoopOverhead ;
- // else
- // fTimer.tmCount -= gLoopOverhead * 1000;
- }
-
- inherited::handleSwapOut();
- }
-
- #endif
-
-