home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Utilities / Fiend-1.4.1-src / Thinker.m < prev    next >
Encoding:
Text File  |  1995-08-29  |  18.9 KB  |  887 lines

  1. //    Thinker.m
  2. //
  3. //    This class is the brains behind the BackSpace app; it is the Application
  4. //    object's delegate, and it watches the system to determine when to
  5. //    initiate the screen saver mode.
  6. //
  7. //    You may freely copy, distribute, and reuse the code in this example.
  8. //    NeXT disclaims any warranty of any kind, expressed or  implied, as to its
  9. //    fitness for any particular use.
  10.  
  11.  
  12. #import "Thinker.h"
  13. #import "BackWindow.h"
  14. #import "BackView.h"
  15. #import "SpaceView.h"
  16. #import "MySlider.h"
  17. #import "Password.h"
  18. #import "Controller.h"
  19. #import "psfuncts.h"
  20.  
  21. #import <mach/mach.h>
  22. #import <appkit/appkit.h>
  23. #import <objc/NXBundle.h>
  24.  
  25. // convert vertical blank time to milliseconds
  26. #define SEC2MS(x) ((x * 1000) + 20)
  27.  
  28. //#define SHOWITERATIONSPERSEC
  29.  
  30. #ifdef SHOWITERATIONSPERSEC
  31. unsigned iterations;
  32. BStimeval then, now, targetTime;
  33. #endif
  34.  
  35. static id _BSThinker;
  36.  
  37. id BSThinker()
  38. {    return _BSThinker;
  39. }
  40.  
  41.  
  42. @implementation Thinker
  43.  
  44. - appDidInit:sender
  45. {
  46. //    const char *autoLaunch;
  47.     globalTier = BACKGROUNDTIER;
  48.     openAnother = YES;
  49.     _BSThinker = self;
  50.  
  51.     backZone = NXCreateZone(vm_page_size, vm_page_size, YES);
  52.     NXSetRect(&windowRect, 475, 300, 500, 450);
  53.     [NXApp getScreens:&screens count:&screenCount];
  54.  
  55.     [commonImageInspector getFrame: &inspectorFrame];
  56.     currentInspector = commonImageInspector;
  57.     
  58.     [[NXApp delegate] setProgressViewRatio:0.1];
  59.  
  60.     [self getViewType];
  61.     [self setVirtualViewIndexAndIncrement:NO];
  62.     [self getWindowType];
  63.  
  64.     [self getScreenSaverSetting];
  65.     [self getScreenLockerSetting];
  66.     [self getPrioritySetting];
  67.     [self getImageFile];
  68.     [self getHotCornerSetting];
  69.  
  70. #ifdef SHOWITERATIONSPERSEC
  71.     then = currentTimeInMs();
  72.     targetTime = then + 10000;
  73. #endif
  74.     
  75.     srandom(time(0));
  76.  
  77.     return self;
  78. }
  79.  
  80. - appDidHide:sender
  81. {
  82.     if (windowType != BACKWINDOW) [self removeTimer];
  83.     return self;
  84. }
  85.  
  86. - appDidUnhide:sender
  87. {
  88. //    if (!windowHasBeenDisplayed)
  89. //    {
  90. //        [[windMatrix window] makeKeyAndOrderFront:self];
  91. //        windowHasBeenDisplayed = YES;
  92. //    }
  93.  
  94.     if (windowType != NOWINDOW) [self createTimer];
  95.     return self;
  96. }
  97.  
  98.  
  99.  
  100. // Pretty much a dummy function to invoke the step method.
  101.  
  102. void timedEntryFunction (DPSTimedEntry timedEntry, double timeNow, void *theObject)
  103. {    [(id)theObject doDistributorLoop];
  104. }
  105.  
  106. - createTimer
  107. {
  108.     if (!timerValid)
  109.     {
  110.         timerValid = YES;
  111.         timer = DPSAddTimedEntry(0.02, &timedEntryFunction, self, NX_BASETHRESHOLD);
  112.     }
  113.     return self;
  114. }
  115.  
  116. - removeTimer
  117. {
  118.     if (timerValid) DPSRemoveTimedEntry (timer);
  119.     timerValid = NO;
  120.     return self;
  121. }
  122.  
  123. - doDistributorLoop
  124. {
  125.     NXEvent dummyEvent;
  126.     
  127.     keepLooping = YES;
  128.     [spaceView lockFocus];
  129.     if ([spaceView respondsTo:@selector(didLockFocus)]) [spaceView didLockFocus];
  130.  
  131.     do {
  132.         [spaceView oneStep];
  133.         [spaceWindow flushWindow];
  134.         NXPing ();    // Synchronize postscript for smoother animation
  135.  
  136.         [spaceView oneStep];
  137.         [spaceWindow flushWindow];
  138.         NXPing ();    // Synchronize postscript for smoother animation
  139.  
  140. #ifdef SHOWITERATIONSPERSEC
  141.             iterations++;
  142.             if ((now = currentTimeInMs()) > targetTime)
  143.             {
  144.                 printf("BackSpace: %5.1f its/sec\n",
  145.                     (double)iterations*1000.0/(double)(now - then));
  146.                 iterations = 0;
  147.                 targetTime = now + 10000;
  148.                 then = now;
  149.             }
  150. #endif
  151.             
  152.        } while (timerValid && keepLooping &&
  153.             ([NXApp peekNextEvent:NX_ALLEVENTS into:&dummyEvent 
  154.                 waitFor:0 threshold:NX_BASETHRESHOLD] == NULL));
  155.  
  156.     [spaceView unlockFocus];
  157.     
  158.     return self;
  159.  
  160. }
  161.  
  162. - installSpaceViewIntoWindow:w
  163. {
  164.     NXRect cvrect;
  165.     int i;
  166.     id subviews, contentView;
  167.     
  168.     if (!w) return nil;
  169.     contentView = [w contentView];
  170.  
  171.     // get size of content view
  172.     [contentView getBounds:&cvrect];
  173.     
  174.     // remove old subviews, this is overkill really...
  175.     subviews = [contentView subviews];
  176.     for (i=([subviews count]-1); i>=0; i--)
  177.     {    [[subviews objectAt:i] removeFromSuperview];
  178.     }
  179.     
  180.     // install it into the window's content view
  181.     [contentView addSubview:spaceView];
  182.     [contentView setAutoresizeSubviews:YES];
  183.     [spaceView setAutosizing:NX_WIDTHSIZABLE | NX_HEIGHTSIZABLE];
  184.  
  185.     // size the spaceview
  186.     [spaceView sizeTo:cvrect.size.width :cvrect.size.height];
  187.     
  188.     return self;
  189. }
  190.  
  191. - useNormalWindow
  192. {
  193.     int myBacking;
  194.     
  195.     spaceView = [self backView];
  196.     myBacking = [self backingTypeForView:spaceView];
  197.  
  198.     if (!normalWindow)
  199.     {
  200.         normalWindow = [[Window allocFromZone:backZone]
  201.             initContent:&windowRect style:NX_RESIZEBARSTYLE
  202.             backing:myBacking 
  203.             buttonMask:NX_CLOSEBUTTONMASK
  204.             defer:NO];
  205.         
  206.         [self setWindowTitle];
  207.         [normalWindow useOptimizedDrawing:YES];
  208.         [normalWindow setDynamicDepthLimit:YES]; //want window depth to match device!
  209.         [normalWindow setOneShot:YES];
  210.         [normalWindow setDelegate:self];
  211.         [normalWindow setBackgroundGray:NX_BLACK];
  212.     }
  213.  
  214.     spaceWindow = normalWindow;
  215.     [self installSpaceViewIntoWindow:spaceWindow];
  216.  
  217.     if ([spaceView respondsTo:@selector(setImage:)])
  218.         [spaceView setImage: image];
  219.     if ([spaceView respondsTo:@selector(newWindow)]) [spaceView newWindow];
  220.     [spaceWindow display];
  221.  
  222.     [spaceWindow makeKeyAndOrderFront:self];
  223.     
  224.     // need to do this so flushing always works!
  225.     // must do it late because kit does lazy window creation ie the PostScript
  226.     // window might not exist until you actually draw to it
  227.     
  228.     if (myBacking == NX_RETAINED)
  229.         [spaceWindow setBackingType:NX_RETAINED];
  230.     else [spaceWindow setBackingType:NX_BUFFERED];
  231.  
  232.     return self;
  233. }
  234.  
  235. - (int) backingTypeForView:aView
  236. {
  237.     if ([aView respondsTo:@selector(useBufferedWindow)] 
  238.         && [aView useBufferedWindow])
  239.         return NX_BUFFERED;
  240.     return NX_RETAINED;
  241. }
  242.  
  243. - useBackWindow:(int)tier
  244. {
  245.     int        i;
  246.     NXRect r={{0, 0}};
  247.     int myBacking;
  248.     
  249.     [NXApp getScreens:&screens count:&screenCount];
  250.     NXSetRect(&r, 0.0, 0.0, 0.0, 0.0);
  251.     for(i = 0; i < screenCount; i++)
  252.         NXUnionRect(&screens[i].screenBounds, &r);
  253.  
  254.     spaceView = [self backView];
  255.     myBacking = [self backingTypeForView:spaceView];
  256.     
  257.     [self createBigWindowIfNecessaryForView:spaceView];
  258.  
  259.     if (myBacking == NX_RETAINED)
  260.     {    spaceWindow = bigUnbufferedWindow;
  261.         tweakWindow([spaceWindow windowNum], tier);
  262.     }
  263.     else
  264.     {    spaceWindow = bigBufferedWindow;
  265.     }
  266.  
  267.     [self installSpaceViewIntoWindow:spaceWindow];
  268.  
  269.     if ([spaceView respondsTo:@selector(setImage:)])
  270.         [spaceView setImage: image];
  271.  
  272.     [spaceWindow placeWindow:&r];
  273.     if (myBacking == NX_BUFFERED) [spaceWindow display];
  274.  
  275.     [spaceWindow orderFront:self];
  276.     if (myBacking == NX_BUFFERED) tweakWindow([spaceWindow windowNum], tier);
  277.     else [spaceWindow display];
  278.  
  279.     if ([spaceView respondsTo:@selector(newWindow)]) [spaceView newWindow];
  280.  
  281.     return self;
  282. }
  283.  
  284. - createBigWindowIfNecessaryForView:aView
  285. {
  286.     int        i;
  287.     NXRect    r = {{0.0, 0.0}, {0.0, 0.0}};
  288.     int        myBacking = [self backingTypeForView:aView];
  289.     
  290.     [NXApp getScreens:&screens count:&screenCount];
  291.     NXSetRect(&r, 0.0, 0.0, 0.0, 0.0);
  292.     for(i = 0; i < screenCount; i++)
  293.         NXUnionRect(&screens[i].screenBounds, &r);
  294.  
  295.     if ((myBacking == NX_RETAINED) && !bigUnbufferedWindow)
  296.     {
  297.     
  298.         bigUnbufferedWindow = [[BackWindow allocFromZone:backZone]
  299.             initContent:&r style:NX_TOKENSTYLE
  300.             backing:NX_NONRETAINED buttonMask:0 defer:NO];
  301.  
  302.         [bigUnbufferedWindow useOptimizedDrawing:YES];
  303.  
  304.         [bigUnbufferedWindow removeFromEventMask:(NX_LMOUSEDOWNMASK | NX_LMOUSEUPMASK
  305.                  | NX_MOUSEMOVEDMASK | NX_LMOUSEDRAGGEDMASK
  306.                | NX_MOUSEENTEREDMASK | NX_MOUSEEXITEDMASK
  307.                | NX_KEYDOWNMASK | NX_KEYUPMASK
  308.                | NX_CURSORUPDATEMASK)];
  309.         [bigUnbufferedWindow setBackgroundGray:NX_BLACK];
  310.     }
  311.  
  312.     if ((myBacking == NX_BUFFERED) && !bigBufferedWindow)
  313.     {
  314.  
  315.         bigBufferedWindow = [[BackWindow allocFromZone:backZone]
  316.             initContent:&r style:NX_TOKENSTYLE
  317.             backing:NX_BUFFERED buttonMask:0 defer:NO];
  318.  
  319.         [bigBufferedWindow useOptimizedDrawing:YES];
  320.  
  321.         [bigBufferedWindow removeFromEventMask:(NX_LMOUSEDOWNMASK | NX_LMOUSEUPMASK
  322.                  | NX_MOUSEMOVEDMASK | NX_LMOUSEDRAGGEDMASK
  323.                | NX_MOUSEENTEREDMASK | NX_MOUSEEXITEDMASK
  324.                | NX_KEYDOWNMASK | NX_KEYUPMASK
  325.                | NX_CURSORUPDATEMASK)];
  326.  
  327.         [bigBufferedWindow setDynamicDepthLimit:YES]; //want window depth to match device!
  328.         [bigBufferedWindow setOneShot:YES];
  329.         [bigBufferedWindow setBackgroundGray:NX_BLACK];
  330.     }
  331.  
  332.     return self;
  333. }
  334.  
  335. - changeWindowType:sender
  336. {
  337.     [self changeWindowTypeAndRemember:YES];
  338.     return self;
  339. }
  340.  
  341. - changeWindowTypeAndRemember:(BOOL)rem
  342. {
  343.     char str[10];
  344.     int newWindowType;
  345.  
  346.     newWindowType = [windMatrix selectedRow];
  347.     if (newWindowType == windowType) return self;
  348.     
  349.     windowType = newWindowType;
  350.  
  351.     if (rem)
  352.     {
  353.         sprintf(str,"%1d", windowType);
  354.         NXWriteDefault("BackSpace", "windowType", str);
  355.     }
  356.  
  357.     [spaceWindow orderOut:self];
  358.     
  359.     switch (windowType)
  360.     {
  361.         case NOWINDOW:
  362.             [self removeTimer];
  363.             break;
  364.         case NORMALWINDOW:
  365.             [self useNormalWindow];
  366.             [self createTimer];
  367.             break;
  368.         case BACKWINDOW:
  369.             [self useBackWindow: globalTier];
  370.             [self createTimer];
  371.             break;
  372.     }
  373.     
  374.     return self;
  375. }
  376.  
  377. - getWindowType
  378. {
  379.     int tWindowType = NORMALWINDOW;
  380.     const char *ptr;
  381.     int val;
  382.  
  383.     ptr = NXGetDefaultValue("BackSpace", "windowType");
  384.     if (ptr)
  385.     {
  386.         sscanf(ptr,"%d",&val);
  387.         if (val >= 0 && val <= 2) tWindowType = val;
  388.     }
  389.     
  390.     [windMatrix selectCellAt:tWindowType :0];
  391.     [self changeWindowTypeAndRemember:NO];
  392.  
  393.     return self;
  394. }
  395.  
  396. - getScreenSaverSetting
  397. {
  398.     const char *ptr;
  399.     
  400.     if((evs = NXOpenEventStatus()) == 0)
  401.     {    perror("NXOpenEventStatus failed.");
  402.         exit(10);
  403.     }
  404.     
  405.     [self getDimBrightness:&dimBrightness];
  406.     
  407.     //in case the old dim brightness is somehow invalid, I reset it
  408.     if (dimBrightness > .25)
  409.     {
  410.         dimBrightness = .25;
  411.         [self _setDimBrightness:&dimBrightness];
  412.     }
  413.  
  414.     [screenSaver setState:0];
  415.     
  416.     ptr = NXGetDefaultValue("BackSpace", "screenSaver");
  417.  
  418.     if (!ptr || !strcmp(ptr,"Off")) [self setScreenSaver:NO andRemember:NO];
  419.     else [self setScreenSaver:YES andRemember:NO];
  420.     
  421.     return self;
  422. }
  423.  
  424. - changeScreenSaverSetting:sender
  425. {
  426.     [self setScreenSaver:([screenSaver state])andRemember:YES];
  427.     return self;
  428. }
  429.  
  430. - setScreenSaver:(BOOL)val andRemember:(BOOL)rem
  431. {
  432.     [screenSaver setState:val];
  433.     screenSaverVal = val;
  434.     
  435.     if (val)
  436.     {
  437.         // turn it on...
  438.         [self calcDimTime];
  439.         if (rem) NXWriteDefault("BackSpace", "screenSaver", "On");
  440.     }
  441.     else
  442.     {
  443.         // turn it off...
  444.         if (rem) NXRemoveDefault("BackSpace", "screenSaver");
  445.     }
  446.     
  447.     return self;
  448. }
  449.  
  450. - calcDimTime
  451. {
  452.     double dimTime;
  453.     [self getDimTime :&dimTime];
  454.     
  455.     if (dimTime < 0) dimTime = .1;
  456.     
  457.     if (screenSaverVal && !doingSaver)
  458.     {
  459.         // printf("BackSpace calcDimTime: dims in %f seconds\n",dimTime);
  460.     
  461.         [self perform:@selector(maybeDoScreenSaver:)
  462.             with:self
  463.             afterDelay:SEC2MS(dimTime)
  464.             cancelPrevious:YES];
  465.     }
  466.             
  467.     return self;
  468. }
  469.  
  470. - maybeDoScreenSaver:sender
  471. {
  472.     NXEvent anEvent;
  473.     BOOL autoDimmed;
  474.  
  475.     // in case timed entry fires but user has killed screen saver
  476.     if (!screenSaverVal || doingSaver) return self;
  477.     
  478.     autoDimmed = NXAutoDimState(evs);
  479.     if (!autoDimmed)
  480.     {
  481.         [self calcDimTime];
  482.         return self;
  483.     }
  484.  
  485.     // The perform:afterDelay: method starts a timed entry to
  486.     // invoke maybeDoScreenSaver, so we are in a timed entry
  487.     // right now.  If we just jumped into doScreenSaver:, we
  488.     // would interrupt the doDistributorLoop method while
  489.     // it's still focused on the spaceView.     By posting an
  490.     // event, we force that loop to bail out so we can jump
  491.     // into the screen saver cleanly.
  492.     
  493.     keepLooping = NO;    // There was a bug related to this at one point.
  494.                         // I don't think it's necessary anymore.
  495.     anEvent.type = NX_APPDEFINED;
  496.     anEvent.data.compound.subtype = BSDOSAVER;
  497.     anEvent.ctxt = [NXApp context];
  498.     DPSPostEvent(&anEvent,0);
  499.     
  500.     return self;
  501. }
  502.  
  503. - applicationDefined:(NXEvent *)theEvent
  504. {
  505.     switch (theEvent->data.compound.subtype)
  506.     {
  507.     case BSDOSAVER:
  508.         [self doScreenSaver:self];
  509.         [self calcDimTime];            // reset to fire again
  510.         break;
  511.     case BSOPENFILE:
  512.         [self doDelayedOpenFile];
  513.         break;
  514.     default:
  515.         break;
  516.     }
  517.     return self;
  518. }
  519.  
  520. - showFakeScreenSaverAfterPause:sender
  521. {
  522. //    usleep(250000);
  523.     thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT, 250);
  524.     return [self showFakeScreenSaver:sender];
  525. }
  526.  
  527. - showFakeScreenSaver:sender
  528. {
  529.     [self screenSaverMode];
  530.     NXSetAutoDimState(evs, YES);
  531.     [self doScreenSaver:self];
  532.     NXSetAutoDimState(evs, NO);
  533.     [self normalMode];            //usually not necessary
  534.     
  535.     // reset to fire again
  536.     [self calcDimTime];
  537.         
  538.     return self;
  539. }
  540.  
  541.  
  542. - doScreenSaver:sender
  543. {
  544.     BOOL autoDimmed;
  545.     int oldWindowType;
  546.     BOOL mouseOK, oldTimerValid;
  547.     BOOL ignoreMouseMovement = NO;
  548.     BOOL isHidden;
  549.     NXRect trackingRect;
  550.     NXPoint mouseLoc;
  551.     BOOL passwordOK;
  552.     BOOL stoleActivation = NO;
  553.     int oldActiveApp = 0;
  554.         
  555.     // must be sure we don't enter on timed entry after faking saver
  556.     doingSaver = YES;
  557.     
  558.     isHidden = [NXApp isHidden];
  559.     if (isHidden)
  560.     {
  561.         [NXApp unhideWithoutActivation:self];
  562.     }
  563.  
  564.     if ([password isLocked])
  565.     {
  566.         oldActiveApp = [NXApp activateSelf:YES];
  567.         stoleActivation = YES;
  568.     }
  569.     
  570.     [self setVirtualViewIndexAndIncrement:YES];
  571.  
  572.     //save old window state
  573.     oldWindowType = [windMatrix selectedRow];
  574.  
  575.     globalTier = SAVERTIER;
  576.  
  577.     [self blackOutAllScreens];
  578.     
  579.     //background window on screen
  580.     [windMatrix selectCellAt:BACKWINDOW :0];
  581.     [self changeWindowTypeAndRemember:NO];
  582.     
  583.     //nuke timer so timed entry doesn't fire
  584.     oldTimerValid = timerValid;
  585.     [self removeTimer];
  586.  
  587.  
  588.     //set background window tier to SAVERTIER
  589.     if ([self backingTypeForView:spaceView] == NX_BUFFERED)
  590.     {
  591.         // make sure the one shot buffer really exists
  592.         //[spaceWindow display];    //xxx
  593.         if ([spaceWindow windowNum] <= 0) [spaceWindow display];
  594.         PSsetwindowlevel(SAVERTIER, [spaceWindow windowNum]);
  595. //        PSsetwindowlevel(-1, [spaceWindow windowNum]);
  596.     }
  597.     else 
  598.     {
  599.         PSsetwindowlevel(SAVERTIER, [spaceWindow windowNum]);
  600. //        PSsetwindowlevel(-1, [spaceWindow windowNum]);
  601.         [spaceView fillBoundsWithBlack];
  602.         [spaceView display];
  603.     }
  604.  
  605.     NXPing();
  606.     [self screenSaverMode];
  607.  
  608.     if ([spaceView respondsTo:@selector(enteredScreenSaverMode)])
  609.         [spaceView enteredScreenSaverMode];
  610.  
  611.     do {
  612.         //obscure cursor
  613.         PShidecursor();
  614.     
  615.         [spaceView lockFocus];
  616.         if ([spaceView respondsTo:@selector(didLockFocus)])
  617.             [spaceView didLockFocus];
  618.  
  619.  
  620.         if ([spaceView respondsTo:@selector(ignoreMouseMovement)])
  621.             ignoreMouseMovement = [spaceView ignoreMouseMovement];
  622.  
  623.         [spaceWindow getMouseLocation:&mouseLoc];
  624.         trackingRect.origin.x = mouseLoc.x - 100;
  625.         trackingRect.origin.y = mouseLoc.y - 100;
  626.         trackingRect.size.width = trackingRect.size.height = 200;
  627.     
  628.         do {
  629.             [spaceView oneStep];
  630.             [spaceWindow flushWindow];
  631.             NXPing();    // Synchronize postscript for smoother animation
  632.  
  633.             // note: window and view coordinates the same!
  634.             // so I don't have to convert to view coord system
  635.             if (ignoreMouseMovement) mouseOK = YES;
  636.             else
  637.             {
  638.                 [spaceWindow getMouseLocation:&mouseLoc];
  639.                 mouseOK = [spaceView mouse:&mouseLoc inRect:&trackingRect];
  640.             }
  641.         
  642.             [spaceView oneStep];
  643.             [spaceWindow flushWindow];
  644.             NXPing();    // Synchronize postscript for smoother animation
  645.  
  646.             autoDimmed = NXAutoDimState(evs);
  647.         } while (autoDimmed && mouseOK);
  648.     
  649.         [spaceView unlockFocus];
  650.     
  651.         //restore cursor
  652.         PSshowcursor();
  653.         
  654.         passwordOK = [password checkPassword: 
  655.             NXLocalString("Screen is locked.  Enter password to unlock:",0,0) 
  656.             randomPos:YES checkLock:YES withView:spaceView];
  657.  
  658.         if (!passwordOK) NXSetAutoDimState(evs, YES);
  659.  
  660.     } while (!passwordOK);
  661.  
  662.     if ([spaceView respondsTo:@selector(willExitScreenSaverMode)])
  663.         [spaceView willExitScreenSaverMode];
  664.  
  665.     NXSetAutoDimState(evs, NO);
  666.     [self normalMode];
  667.  
  668.     //background window tier to BACKGROUNDTIER
  669.     PSsetwindowlevel(BACKGROUNDTIER, [spaceWindow windowNum]);
  670.     globalTier = BACKGROUNDTIER;
  671.     
  672.     if (([self backingTypeForView:spaceView] != NX_BUFFERED) &&
  673.             oldWindowType == BACKWINDOW)
  674.         // this justs fixes a display bug for really lazy nonretained windows
  675.     {
  676.         [spaceView fillBoundsWithBlack];
  677.         [spaceView display];
  678.     }
  679.  
  680.     if (oldTimerValid)    [self createTimer];
  681.  
  682.     [self unBlackOutAllScreens];
  683.     
  684.     //restore old window state
  685.     [windMatrix selectCellAt:oldWindowType :0];
  686.     [self changeWindowTypeAndRemember:NO];
  687.     
  688.     if (stoleActivation) 
  689.     {
  690.         if (oldActiveApp) [NXApp activate:oldActiveApp];
  691.         else [NXApp deactivateSelf];
  692.     }
  693.  
  694.     if (isHidden)
  695.     {
  696.         [NXApp hide:self];
  697.     }
  698.  
  699.     doingSaver = NO;
  700.  
  701.     return self;
  702. }
  703.  
  704. - appWillTerminate:sender
  705. {
  706.     [self normalMode];
  707.     return self;
  708. }
  709.  
  710. - appDidBecomeActive:sender
  711. {
  712.     id theMatrix;
  713.  
  714.     theMatrix = [viewSelectionBrowser matrixInColumn:0];
  715.     [theMatrix scrollCellToVisible:realViewIndex :0];
  716.     return self;
  717. }
  718.  
  719. - app:sender powerOffIn:(int)ms andSave:(int)aFlag
  720. {
  721.     return [NXApp terminate:self];
  722. }
  723.  
  724. - getPrioritySetting
  725. {
  726.     const char *ptr;
  727.     int val;
  728.  
  729.     [mySlider setMinValue: 0];
  730.     [mySlider setMaxValue: 10];
  731.     
  732.     ptr = NXGetDefaultValue("BackSpace", "priority");
  733.     if (ptr)
  734.     {
  735.         sscanf(ptr,"%d",&val);
  736.         if (val >= 0 && val <= 10) priority = val;
  737.         else priority = 4;
  738.     }
  739.     else priority = 4;
  740.     
  741.     [[mySlider cell] setIntValue:priority];
  742.     [[priorityLevel cell] setIntValue:priority];
  743.  
  744. //    use mach call rather than unix - mach lets me increase priority!
  745. //    setpriority(PRIO_PROCESS, 0, priority);
  746.     cthread_priority(cthread_self(), priority, FALSE);
  747.  
  748.     return self;
  749. }
  750.  
  751. - changeSliderValue:sender
  752. {
  753.     priority = [[mySlider cell] intValue];
  754.     [[priorityLevel cell] setIntValue:priority];
  755.     return self;
  756. }
  757.  
  758. - saveSliderValue
  759. {
  760.     char str[50];
  761. //    setpriority(PRIO_PROCESS, 0, priority);
  762.     cthread_priority(cthread_self(), priority, FALSE);
  763.  
  764.     sprintf(str,"%d", priority);
  765.     NXWriteDefault("BackSpace", "priority", str);
  766.     return self;
  767. }
  768.  
  769. - windowWillResize:sender toSize:(NXSize *)frameSize
  770. {
  771.     if (frameSize->width < 100) frameSize->width = 100;
  772.     if (frameSize->height < 100) frameSize->height = 100;
  773.     return self;
  774. }
  775.  
  776. - windowWillClose:sender
  777. {
  778.     [windMatrix selectCellAt:NOWINDOW :0];
  779.     [self perform:@selector(changeWindowType:) with:self
  780.         afterDelay:1 cancelPrevious:YES];
  781.     return nil;
  782. }
  783.  
  784. BStimeval currentTimeInMs()
  785. {
  786.     struct timeval curTime;
  787.     gettimeofday (&curTime, NULL);
  788.     return (curTime.tv_sec) * 1000 + curTime.tv_usec / 1000;
  789. }
  790.  
  791. //
  792. //    Additional methods to handle a common image object for views.
  793. //    Lennart Lovstrad, Rank Xerox EuroPARC, August 1991.
  794. //
  795.  
  796. - setImageFromFile: (const char *) filename
  797. {
  798.     [image free];
  799.  
  800.     image = [[NXImage alloc] initFromFile: filename];
  801.     if (image == nil)
  802.     {
  803.         NXRunAlertPanel([NXApp appName], NXLocalString("Could not open %s",0,0),
  804.                 NULL, NULL, NULL, filename);
  805.         image = nil;
  806.         //return nil;    //can't return, image is invalid
  807.     }
  808.     
  809.     return [self commonImageInit];
  810. }
  811.  
  812. - setImageFromName: (const char *) name
  813. {
  814.     [image free];
  815.     image = [[NXImage alloc] initFromSection: name];
  816.     
  817.     return [self commonImageInit];
  818. }
  819.  
  820. - commonImageInit
  821. {
  822.     [imageView setImage: image];
  823.     [imageView display];
  824.  
  825.     if ([spaceView respondsTo:@selector(setImage:)])
  826.         [spaceView setImage: image];
  827.  
  828.     if ([self backingTypeForView:spaceView] != NX_BUFFERED)
  829.     {
  830.         [spaceView fillBoundsWithBlack];
  831.         [spaceView display];
  832.     }
  833.  
  834.     return self;
  835. }
  836.  
  837. - getImageFile
  838. {
  839.     const char *filename;
  840.  
  841.     filename = NXGetDefaultValue("BackSpace", "imageFile");
  842.     if (filename)
  843.         [self setImageFromFile: filename];
  844.     else [self setImageFromName: "defaultImage"];
  845.  
  846.     return self;
  847. }
  848.  
  849. - setImageFileFrom: sender
  850. {
  851.     id openPanel = [OpenPanel new];
  852.     const char *fileTypes[] = {"tiff", "eps", NULL};
  853.     
  854.     if ([openPanel runModalForTypes: fileTypes])
  855.     {
  856.         [self setImageFromFile: [openPanel filename]];
  857.         NXWriteDefault("BackSpace", "imageFile", [openPanel filename]);
  858.     }
  859.  
  860.     [spaceView display];    //don't know why this is necessary...
  861.  
  862.     return self;
  863. }
  864.  
  865. // This should return a float between 0 and 1
  866. float frandom()
  867. {
  868.     float val = (random() & 0x7fffffff);
  869.     val /= 0x7fffffff;
  870.     return val;
  871. }
  872.  
  873. float randBetween(float a, float b)
  874. {
  875.     float val, scale, t;
  876.  
  877.     if (a > b)
  878.     {    t = a; a = b; b = t;
  879.     }
  880.     
  881.     scale = (b-a);
  882.     val = scale * frandom();
  883.     return (a + val);
  884. }
  885.  
  886. @end
  887.