home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / RiscOS / APP / DEVS / SMALLT / SQ123B.ZIP / Sq123b / SqueakV1 < prev   
Text File  |  1997-02-05  |  2MB  |  56,101 lines

  1. 'From Smalltalk-80 version 1.03 of July 31, 1996 on 20 September 1996 at 10:50:05 am'!
  2.  
  3. Object subclass: #AbstractSound
  4.     instanceVariableNames: 'samplesUntilNextControl '
  5.     classVariableNames: ''
  6.     poolDictionaries: ''
  7.     category: 'Sound'!
  8.  
  9. !AbstractSound methodsFor: 'initialization'!
  10. initialize
  11.  
  12.     ^ self
  13. !
  14. setPitch: p dur: d loudness: l
  15.  
  16.     self subclassResponsibility.! !
  17.  
  18. !AbstractSound methodsFor: 'playing'!
  19. play
  20.     "Play this sound to the sound ouput port in real time."
  21.  
  22.     SoundPlayer playSound: self.!
  23. playSampleCount: n into: aSoundBuffer startingAt: startIndex stereo: stereoFlag
  24.     "Mixes the next count samples of this sound into the given buffer starting at the given index, updating the receiver's control parameters at periodic intervals."
  25.  
  26.     | pastEnd i leftRightPan remainingSamples count |
  27.     stereoFlag ifTrue: [leftRightPan _ 500] ifFalse: [leftRightPan _ 1000].
  28.     pastEnd _ startIndex + n.  "index just index of after last sample"
  29.     i _ startIndex.
  30.     [i < pastEnd] whileTrue: [
  31.         remainingSamples _ self samplesRemaining.
  32.         remainingSamples <= 0 ifTrue: [ ^ self ].
  33.         count _ ((pastEnd - i) min: samplesUntilNextControl) min: remainingSamples.
  34.         self mixSampleCount: count into: aSoundBuffer startingAt: i pan: leftRightPan.
  35.         samplesUntilNextControl _ samplesUntilNextControl - count.
  36.         samplesUntilNextControl <= 0 ifTrue: [
  37.             self doControl.
  38.             samplesUntilNextControl _ (self samplingRate // self controlRate).
  39.         ].
  40.         i _ i + count.
  41.     ].
  42. !
  43. playSilently
  44.     "Compute the samples of this sound without outputting them. Used for performance analysis."
  45.  
  46.     | buf |
  47.     self reset.
  48.     buf _ SoundBuffer sampleCount: (self samplingRate // 10).
  49.     [self samplesRemaining > 0] whileTrue: [
  50.         buf primFill: 0.
  51.         self playSampleCount: buf sampleCount into: buf startingAt: 1 stereo: true.
  52.     ].
  53. ! !
  54.  
  55. !AbstractSound methodsFor: 'sound generation'!
  56. doControl
  57.     "Update the control parameters of this sound (e.g., it's envelope)."
  58.     "Note: This is only called at a small fraction of the sampling rate."
  59.  
  60.     ^ self!
  61. mixSampleCount: count into: aSoundBuffer startingAt: index pan: pan
  62.     "Mix the given number of samples with the samples already in the given buffer starting at the given index. Assume that the buffer size is at least (index + count) - 1. The pan parameter determines the left-right balance of the sound, where 0 is left only, 1000 is right only, and 500 is centered."
  63.  
  64.     self subclassResponsibility.!
  65. reset
  66.     "Reset my internal state for a replay."
  67.  
  68.     samplesUntilNextControl _ (self samplingRate // self controlRate).
  69. !
  70. samplesRemaining
  71.     "Answer the number of samples remaining until the end of this sound. A sound with an indefinite ending time should answer some large integer such as 1000000."
  72.  
  73.     ^ 1000000! !
  74.  
  75. !AbstractSound methodsFor: 'composition'!
  76. + aSound
  77.     "Return the mix of the receiver and the argument sound."
  78.  
  79.     ^ MixedSound new
  80.         add: self;
  81.         add: aSound
  82. !
  83. , aSound
  84.     "Return the concatenation of the receiver and the argument sound."
  85.  
  86.     ^ SequentialSound new
  87.         add: self;
  88.         add: aSound
  89. !
  90. delayedBy: seconds
  91.     "Return a composite sound consisting of a rest for the given amount of time followed by the receiver."
  92.  
  93.     ^ (RestSound dur: seconds), self! !
  94.  
  95. !AbstractSound methodsFor: 'sampling rates'!
  96. controlRate
  97.     "Answer the number of control changes per second."
  98.  
  99.     ^ 50!
  100. samplingRate
  101.     "Answer the sampling rate in samples per second."
  102.  
  103.     ^ SoundPlayer samplingRate! !
  104. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  105.  
  106. AbstractSound class
  107.     instanceVariableNames: ''!
  108.  
  109. !AbstractSound class methodsFor: 'instance creation'!
  110. dur: d
  111.     "Return a rest of the given duration."
  112.  
  113.     ^ self basicNew setDur: d!
  114. namedNoteSequenceFrom: anArray
  115.     "Build a note sequence (i.e., a SequentialSound) from the given array. Elements are either (pitchName, duration, loudness) triples or (#rest duration) pairs."
  116.  
  117.     | score |
  118.     score _ SequentialSound new.
  119.     anArray do: [ :el |
  120.         el size = 3 ifTrue: [
  121.             score add: (self pitch: (self pitchForName: (el at: 1)) dur: (el at: 2) loudness: (el at: 3)).
  122.         ] ifFalse: [
  123.             score add: (RestSound dur: (el at: 2)).
  124.         ].
  125.     ].
  126.     ^ score!
  127. new
  128.  
  129.     ^ self basicNew initialize!
  130. noteSequenceFrom: anArray
  131.     "Build a note sequence (i.e., a SequentialSound) from the given array. Elements are either (pitch, duration, loudness) triples or (#rest duration) pairs."
  132.  
  133.     | score |
  134.     score _ SequentialSound new.
  135.     anArray do: [ :el |
  136.         el size = 3 ifTrue: [
  137.             score add: (self pitch: (el at: 1) dur: (el at: 2) loudness: (el at: 3)).
  138.         ] ifFalse: [
  139.             score add: (RestSound dur: (el at: 2)).
  140.         ].
  141.     ].
  142.     ^ score!
  143. pitch: p dur: d loudness: l
  144.     "Return a new sound object to a note with the given parameters."
  145.  
  146.     ^ self basicNew setPitch: p dur: d loudness: l!
  147. pitchForName: aString
  148.     "AbstractSound pitchForName: 'c2'"
  149.     "#(c 'c#' d eb e f fs g 'g#' a bf b) collect: [ :s | AbstractSound pitchForName: s, '4']"
  150.  
  151.     | s modifier octave i j noteName p |
  152.     s _ ReadStream on: aString.
  153.     modifier _ $n.
  154.     noteName _ s next.
  155.     (s atEnd not and: [s peek isDigit]) ifFalse: [ modifier _ s next ].
  156.     s atEnd
  157.         ifTrue: [ octave _ 4 ]
  158.         ifFalse: [ octave _ Integer readFrom: s ].
  159.     octave < 0 ifTrue: [ self error: 'cannot use negative octave number' ].
  160.     i _ 'cdefgab' indexOf: noteName.
  161.     i = 0 ifTrue: [ self error: 'bad note name: ', noteName asString ].
  162.     i _ #(2 4 6 7 9 11 13) at: i.
  163.     j _ 's#fb' indexOf: modifier.
  164.     j = 0 ifFalse: [ i _ i + (#(1 1 -1 -1) at: j) ].  "i is now in range: [1..14]"
  165.     "Table generator: (1 to: 14) collect: [ :i | 16.3516 * (2.0 raisedTo: (i - 2) asFloat / 12.0)]"
  166.     p _ #(15.4339 16.3516 17.3239 18.354 19.4454 20.6017 21.8268 23.1247 24.4997 25.9565 27.5 29.1352 30.8677 32.7032) at: i.
  167.     octave timesRepeat: [ p _ 2.0 * p ].
  168.     ^ p
  169. ! !
  170.  
  171. !AbstractSound class methodsFor: 'examples'!
  172. bachFugue
  173.     "A fugue by J. S. Bach."
  174.     "AbstractSound bachFugue play"
  175.  
  176.     "BoinkSound        bachFugueVoice1 play"
  177.     "WaveTableSound    bachFugueVoice1 play"
  178.     "PluckedSound        bachFugueVoice1 play"
  179.     "FMSound            bachFugueVoice1 play"
  180.  
  181.     ^ MixedSound new
  182.         add: BoinkSound bachFugueVoice1 pan: 200;
  183.         add: WaveTableSound bachFugueVoice2 pan: 800;
  184.         add: FMSound bachFugueVoice3 pan: 400;
  185.         add: FMSound bachFugueVoice4 pan: 600.
  186. !
  187. bachFugueVoice1
  188.     "Voice one of a fugue by J. S. Bach."
  189.  
  190.     ^ self noteSequenceFrom: #(
  191.         (1047 0.15 268)
  192.         (988  0.15 268)
  193.         (1047 0.30 268)
  194.         (784  0.30 268)
  195.         (831  0.30 268)
  196.         (1047 0.15 268)
  197.         (988  0.15 268)
  198.         (1047 0.30 268)
  199.         (1175 0.30 268)
  200.         (784  0.30 268)
  201.         (1047 0.15 268)
  202.         (988  0.15 268)
  203.         (1047 0.30 268)
  204.         (1175 0.30 268)
  205.         (698  0.15 268)
  206.         (784  0.15 268)
  207.         (831  0.60 268)
  208.         (784  0.15 268)
  209.         (698  0.15 268)
  210.         (622  0.15 268)
  211.         (1047 0.15 268)
  212.         (988  0.15 268)
  213.         (880  0.15 268)
  214.         (784  0.15 268)
  215.         (698  0.15 268)
  216.         (622  0.15 268)
  217.         (587  0.15 268)
  218.         (523  0.30 268)
  219.         (1245 0.30 268)
  220.         (1175 0.30 268)
  221.         (1047 0.30 268)
  222.         (932  0.30 268)
  223.         (880  0.30 268)
  224.         (932  0.30 268)
  225.         (1047 0.30 268)
  226.         (740  0.30 268)
  227.         (784  0.30 268)
  228.         (880  0.30 268)
  229.         (740  0.30 268)
  230.         (784  0.60 268)
  231.         (rest 0.15)
  232.         (523  0.15 268)
  233.         (587  0.15 268)
  234.         (622  0.15 268)
  235.         (698  0.15 268)
  236.         (784  0.15 268)
  237.         (831  0.45 268)
  238.         (587  0.15 268)
  239.         (622  0.15 268)
  240.         (698  0.15 268)
  241.         (784  0.15 268)
  242.         (880  0.15 268)
  243.         (932  0.45 268)
  244.         (622  0.15 268)
  245.         (698  0.15 268)
  246.         (784  0.15 268)
  247.         (831  0.15 268)
  248.         (784  0.15 268)
  249.         (698  0.15 268)
  250.         (622  0.15 268)
  251.         (587  0.30 268)
  252.         (1047 0.15 268)
  253.         (988  0.15 268)
  254.         (1047 0.60 268)
  255.         (rest 0.9)
  256.         (1397 0.30 268)
  257.         (1245 0.30 268)
  258.         (1175 0.30 268)
  259.         (rest 0.3)
  260.         (831  0.30 268)
  261.         (784  0.30 268)
  262.         (698  0.30 268)
  263.         (784  0.30 268)
  264.         (698  0.15 268)
  265.         (622  0.15 268)
  266.         (698  0.30 268)
  267.         (587  0.30 268)
  268.         (784  0.60 268)
  269.         (rest 0.3)
  270.         (988  0.30 268)
  271.         (1047 0.30 268)
  272.         (1047 0.15 268)
  273.         (988  0.15 268)
  274.         (1047 0.30 268)
  275.         (784  0.30 268)
  276.         (831  0.60 268)
  277.         (rest 0.3)
  278.         (880  0.30 268)
  279.         (932  0.30 268)
  280.         (932  0.15 268)
  281.         (880  0.15 268)
  282.         (932  0.30 268)
  283.         (698  0.30 268)
  284.         (784  0.60 268)
  285.         (rest 0.3)
  286.         (784  0.30 268)
  287.         (831  0.30 268)
  288.         (831  0.30 268)
  289.         (784  0.30 268)
  290.         (698  0.30 268)
  291.         (rest 0.3)
  292.         (415  0.30 268)
  293.         (466  0.30 268)
  294.         (523  0.30 268)
  295.         (rest 0.3)
  296.         (415  0.15 268)
  297.         (392  0.15 268)
  298.         (415  0.30 268)
  299.         (349  0.30 268)
  300.         (466  0.30 268)
  301.         (523  0.30 268)
  302.         (466  0.30 268)
  303.         (415  0.30 268)
  304.         (466  0.30 268)
  305.         (392  0.30 268)
  306.         (349  0.30 268)
  307.         (311  0.30 268)
  308.         (349  0.30 268)
  309.         (554  0.30 268)
  310.         (523  0.30 268)
  311.         (466  0.30 268)
  312.         (523  0.30 268)
  313.         (415  0.30 268)
  314.         (392  0.30 268)
  315.         (349  0.30 268)
  316.         (392  0.30 268)
  317.         (784  0.15 268)
  318.         (740  0.15 268)
  319.         (784  0.30 268)
  320.         (523  0.30 268)
  321.         (622  0.30 268)
  322.         (784  0.15 268)
  323.         (740  0.15 268)
  324.         (784  0.30 268)
  325.         (880  0.30 268)
  326.         (587  0.30 268)
  327.         (784  0.15 268)
  328.         (740  0.15 268)
  329.         (784  0.30 268)
  330.         (880  0.30 268)
  331.         (523  0.15 268)
  332.         (587  0.15 268)
  333.         (622  0.60 268)
  334.         (587  0.15 268)
  335.         (523  0.15 268)
  336.         (466  0.30 346)
  337.         (rest 0.45)
  338.         (587  0.15 346)
  339.         (659  0.15 346)
  340.         (740  0.15 346)
  341.         (784  0.15 346)
  342.         (880  0.15 346)
  343.         (932  0.45 346)
  344.         (659  0.15 346)
  345.         (698  0.15 346)
  346.         (784  0.15 346)
  347.         (880  0.15 346)
  348.         (932  0.15 346)
  349.         (1047 0.45 346)
  350.         (740  0.15 346)
  351.         (784  0.15 346)
  352.         (880  0.15 346)
  353.         (932  0.30 346)
  354.         (622  0.15 346)
  355.         (587  0.15 346)
  356.         (622  0.30 346)
  357.         (392  0.30 346)
  358.         (415  0.30 346)
  359.         (698  0.15 346)
  360.         (622  0.15 346)
  361.         (698  0.30 346)
  362.         (440  0.30 346)
  363.         (466  0.30 346)
  364.         (784  0.15 346)
  365.         (698  0.15 346)
  366.         (784  0.30 346)
  367.         (494  0.30 346)
  368.         (523  0.15 346)
  369.         (698  0.15 346)
  370.         (622  0.15 346)
  371.         (587  0.15 346)
  372.         (523  0.15 346)
  373.         (466  0.15 346)
  374.         (440  0.15 346)
  375.         (392  0.15 346)
  376.         (349  0.30 346)
  377.         (831  0.30 346)
  378.         (784  0.30 346)
  379.         (698  0.30 346)
  380.         (622  0.30 346)
  381.         (587  0.30 346)
  382.         (622  0.30 346)
  383.         (698  0.30 346)
  384.         (494  0.30 346)
  385.         (523  0.30 346)
  386.         (587  0.30 346)
  387.         (494  0.30 346)
  388.         (523  0.60 346)
  389.         (rest 0.3)
  390.         (659  0.30 346)
  391.         (698  0.30 346)
  392.         (698  0.15 346)
  393.         (659  0.15 346)
  394.         (698  0.30 346)
  395.         (523  0.30 346)
  396.         (587  0.60 346)
  397.         (rest 0.3)
  398.         (587  0.30 346)
  399.         (622  0.30 346)
  400.         (622  0.15 346)
  401.         (587  0.15 346)
  402.         (622  0.30 346)
  403.         (466  0.30 346)
  404.         (523  1.20 346)
  405.         (523  0.30 346)
  406.         (587  0.15 346)
  407.         (622  0.15 346)
  408.         (698  0.15 346)
  409.         (622  0.15 346)
  410.         (698  0.15 346)
  411.         (587  0.15 346)
  412.         (494  0.30 457)
  413.         (rest 0.6)
  414.         (494  0.30 457)
  415.         (523  0.30 457)
  416.         (rest 0.6)
  417.         (622  0.30 457)
  418.         (587  0.30 457)
  419.         (rest 0.6)
  420.         (698  0.60 457)
  421.         (rest 0.6)
  422.         (698  0.30 457)
  423.         (622  0.30 457)
  424.         (831  0.30 457)
  425.         (784  0.30 457)
  426.         (698  0.30 457)
  427.         (622  0.30 457)
  428.         (587  0.30 457)
  429.         (622  0.30 457)
  430.         (698  0.30 457)
  431.         (494  0.30 457)
  432.         (523  0.30 457)
  433.         (587  0.30 457)
  434.         (494  0.30 457)
  435.         (494  0.30 457)
  436.         (523  0.30 457)
  437.         (rest 0.3)
  438.         (523  0.30 457)
  439.         (698  0.15 457)
  440.         (587  0.15 457)
  441.         (622  0.15 457)
  442.         (523  0.45 457)
  443.         (494  0.30 457)
  444.         (523  0.60 457)
  445.         (rest 0.3)
  446.         (659  0.30 268)
  447.         (698  0.60 268)
  448.         (rest 0.3)
  449.         (698  0.30 268)
  450.         (698  0.30 268)
  451.         (622  0.15 268)
  452.         (587  0.15 268)
  453.         (622  0.30 268)
  454.         (698  0.30 268)
  455.         (587  0.40 268)
  456.         (rest 0.4)
  457.         (587  0.40 268)
  458.         (rest 0.4)
  459.         (523  1.60 268)).!
  460. bachFugueVoice2
  461.     "Voice two of a fugue by J. S. Bach."
  462.  
  463.     ^ self noteSequenceFrom: #(
  464.         (rest 4.8)
  465.         (1568 0.15 346)
  466.         (1480 0.15 346)
  467.         (1568 0.30 346)
  468.         (1047 0.30 346)
  469.         (1245 0.30 346)
  470.         (1568 0.15 346)
  471.         (1480 0.15 346)
  472.         (1568 0.30 346)
  473.         (1760 0.30 346)
  474.         (1175 0.30 346)
  475.         (1568 0.15 346)
  476.         (1480 0.15 346)
  477.         (1568 0.30 346)
  478.         (1760 0.30 346)
  479.         (1047 0.15 346)
  480.         (1175 0.15 346)
  481.         (1245 0.60 346)
  482.         (1175 0.15 346)
  483.         (1047 0.15 346)
  484.         (932  0.30 346)
  485.         (1245 0.15 346)
  486.         (1175 0.15 346)
  487.         (1245 0.30 346)
  488.         (784  0.30 346)
  489.         (831  0.30 346)
  490.         (1397 0.15 346)
  491.         (1245 0.15 346)
  492.         (1397 0.30 346)
  493.         (880  0.30 346)
  494.         (932  0.30 346)
  495.         (1568 0.15 346)
  496.         (1397 0.15 346)
  497.         (1568 0.30 346)
  498.         (988  0.30 346)
  499.         (1047 0.30 346)
  500.         (1175 0.15 346)
  501.         (1245 0.15 346)
  502.         (1397 0.90 346)
  503.         (1245 0.15 346)
  504.         (1175 0.15 346)
  505.         (1047 0.15 346)
  506.         (932  0.15 346)
  507.         (831  0.15 346)
  508.         (784  0.15 346)
  509.         (698  0.30 346)
  510.         (1661 0.30 346)
  511.         (1568 0.30 346)
  512.         (1397 0.30 346)
  513.         (1245 0.30 346)
  514.         (1175 0.30 346)
  515.         (1245 0.30 346)
  516.         (1397 0.30 346)
  517.         (988  0.30 346)
  518.         (1047 0.30 346)
  519.         (1175 0.30 346)
  520.         (988  0.30 346)
  521.         (1047 0.30 457)
  522.         (1568 0.15 457)
  523.         (1480 0.15 457)
  524.         (1568 0.30 457)
  525.         (1175 0.30 457)
  526.         (1245 0.60 457)
  527.         (rest 0.3)
  528.         (1319 0.30 457)
  529.         (1397 0.30 457)
  530.         (1397 0.15 457)
  531.         (1319 0.15 457)
  532.         (1397 0.30 457)
  533.         (1047 0.30 457)
  534.         (1175 0.60 457)
  535.         (rest 0.3)
  536.         (1175 0.30 457)
  537.         (1245 0.30 457)
  538.         (1245 0.15 457)
  539.         (1175 0.15 457)
  540.         (1245 0.30 457)
  541.         (932  0.30 457)
  542.         (1047 0.30 457)
  543.         (1245 0.15 457)
  544.         (1175 0.15 457)
  545.         (1245 0.30 457)
  546.         (1397 0.30 457)
  547.         (932  0.30 457)
  548.         (1245 0.15 457)
  549.         (1175 0.15 457)
  550.         (1245 0.30 457)
  551.         (1397 0.30 457)
  552.         (831  0.15 457)
  553.         (932  0.15 457)
  554.         (1047 0.60 457)
  555.         (932  0.15 457)
  556.         (831  0.15 457)
  557.         (784  0.15 457)
  558.         (622  0.15 457)
  559.         (698  0.15 457)
  560.         (784  0.15 457)
  561.         (831  0.15 457)
  562.         (932  0.15 457)
  563.         (1047 0.15 457)
  564.         (1175 0.15 457)
  565.         (1245 0.15 457)
  566.         (1175 0.15 457)
  567.         (1047 0.15 457)
  568.         (1175 0.15 457)
  569.         (1245 0.15 457)
  570.         (1397 0.15 457)
  571.         (1568 0.15 457)
  572.         (1760 0.15 457)
  573.         (1865 0.15 457)
  574.         (698  0.15 457)
  575.         (784  0.15 457)
  576.         (831  0.15 457)
  577.         (932  0.15 457)
  578.         (1047 0.15 457)
  579.         (1175 0.15 457)
  580.         (1319 0.15 457)
  581.         (1397 0.15 457)
  582.         (1245 0.15 457)
  583.         (1175 0.15 457)
  584.         (1245 0.15 457)
  585.         (1397 0.15 457)
  586.         (1568 0.15 457)
  587.         (1760 0.15 457)
  588.         (1976 0.15 457)
  589.         (2093 0.30 457)
  590.         (1976 0.15 457)
  591.         (1760 0.15 457)
  592.         (1568 0.15 457)
  593.         (1397 0.15 457)
  594.         (1245 0.15 457)
  595.         (1175 0.15 457)
  596.         (1047 0.30 457)
  597.         (1245 0.30 457)
  598.         (1175 0.30 457)
  599.         (1047 0.30 457)
  600.         (932  0.30 457)
  601.         (880  0.30 457)
  602.         (932  0.30 457)
  603.         (1047 0.30 457)
  604.         (740  0.30 457)
  605.         (784  0.30 457)
  606.         (880  0.30 457)
  607.         (740  0.30 457)
  608.         (784  0.30 457)
  609.         (1175 0.15 457)
  610.         (1047 0.15 457)
  611.         (1175 0.30 457)
  612.         (rest 0.6)
  613.         (1319 0.15 457)
  614.         (1175 0.15 457)
  615.         (1319 0.30 457)
  616.         (rest 0.6)
  617.         (1480 0.15 457)
  618.         (1319 0.15 457)
  619.         (1480 0.30 457)
  620.         (rest 0.6)
  621.         (784  0.15 457)
  622.         (698  0.15 457)
  623.         (784  0.30 457)
  624.         (rest 0.6)
  625.         (880  0.15 457)
  626.         (784  0.15 457)
  627.         (880  0.30 457)
  628.         (rest 0.6)
  629.         (988  0.15 457)
  630.         (880  0.15 457)
  631.         (988  0.30 457)
  632.         (rest 0.6)
  633.         (1047 0.15 457)
  634.         (988  0.15 457)
  635.         (1047 0.30 457)
  636.         (784  0.30 457)
  637.         (831  0.30 457)
  638.         (1047 0.15 457)
  639.         (988  0.15 457)
  640.         (1047 0.30 457)
  641.         (1175 0.30 457)
  642.         (784  0.30 457)
  643.         (1047 0.15 457)
  644.         (988  0.15 457)
  645.         (1047 0.30 457)
  646.         (1175 0.30 457)
  647.         (698  0.15 457)
  648.         (784  0.15 457)
  649.         (831  0.60 457)
  650.         (784  0.15 457)
  651.         (698  0.15 457)
  652.         (622  0.30 457)
  653.         (1047 0.15 457)
  654.         (988  0.15 457)
  655.         (1047 0.30 457)
  656.         (784  0.30 457)
  657.         (831  0.60 457)
  658.         (rest 0.3)
  659.         (880  0.30 457)
  660.         (932  0.30 457)
  661.         (932  0.15 457)
  662.         (880  0.15 457)
  663.         (932  0.30 457)
  664.         (698  0.30 457)
  665.         (784  0.60 457)
  666.         (rest 0.3)
  667.         (784  0.60 457)
  668.         (831  0.15 457)
  669.         (932  0.15 457)
  670.         (1047 0.15 457)
  671.         (988  0.15 457)
  672.         (1047 0.15 457)
  673.         (831  0.15 457)
  674.         (698  1.20 457)
  675.         (698  0.30 591)
  676.         (1175 0.15 591)
  677.         (1047 0.15 591)
  678.         (1175 0.30 591)
  679.         (698  0.30 591)
  680.         (622  0.30 591)
  681.         (1245 0.15 591)
  682.         (1175 0.15 591)
  683.         (1245 0.30 591)
  684.         (784  0.30 591)
  685.         (698  0.30 591)
  686.         (1397 0.15 591)
  687.         (1245 0.15 591)
  688.         (1397 0.30 591)
  689.         (831  0.30 591)
  690.         (784  0.15 591)
  691.         (1397 0.15 591)
  692.         (1245 0.15 591)
  693.         (1175 0.15 591)
  694.         (1047 0.15 591)
  695.         (988  0.15 591)
  696.         (880  0.15 591)
  697.         (784  0.15 591)
  698.         (1047 0.30 591)
  699.         (1397 0.30 591)
  700.         (1245 0.30 591)
  701.         (1175 0.30 591)
  702.         (rest 0.3)
  703.         (831  0.30 591)
  704.         (784  0.30 591)
  705.         (698  0.30 591)
  706.         (784  0.30 591)
  707.         (698  0.15 591)
  708.         (622  0.15 591)
  709.         (698  0.30 591)
  710.         (587  0.30 591)
  711.         (831  0.30 591)
  712.         (784  0.30 591)
  713.         (rest 0.3)
  714.         (880  0.30 591)
  715.         (988  0.30 591)
  716.         (1047 0.30 591)
  717.         (698  0.15 591)
  718.         (622  0.15 591)
  719.         (587  0.15 591)
  720.         (523  0.15 591)
  721.         (523  0.30 591)
  722.         (1047 0.15 346)
  723.         (988  0.15 346)
  724.         (1047 0.30 346)
  725.         (784  0.30 346)
  726.         (831  0.30 346)
  727.         (1047 0.15 346)
  728.         (988  0.15 346)
  729.         (1047 0.30 346)
  730.         (1175 0.30 346)
  731.         (784  0.30 346)
  732.         (1047 0.15 346)
  733.         (988  0.15 346)
  734.         (1047 0.30 346)
  735.         (1175 0.30 346)
  736.         (698  0.20 346)
  737.         (784  0.20 346)
  738.         (831  0.80 346)
  739.         (784  0.20 346)
  740.         (698  0.20 346)
  741.         (659  1.60 346)).
  742. !
  743. bachFugueVoice3
  744.     "Voice three of a fugue by J. S. Bach."
  745.  
  746.     ^ self noteSequenceFrom: #(
  747.         (rest 14.4)
  748.         (523  0.15 457)
  749.         (494  0.15 457)
  750.         (523  0.30 457)
  751.         (392  0.30 457)
  752.         (415  0.30 457)
  753.         (523  0.15 457)
  754.         (494  0.15 457)
  755.         (523  0.30 457)
  756.         (587  0.30 457)
  757.         (392  0.30 457)
  758.         (523  0.15 457)
  759.         (494  0.15 457)
  760.         (523  0.30 457)
  761.         (587  0.30 457)
  762.         (349  0.15 457)
  763.         (392  0.15 457)
  764.         (415  0.60 457)
  765.         (392  0.15 457)
  766.         (349  0.15 457)
  767.         (311  0.15 457)
  768.         (523  0.15 457)
  769.         (494  0.15 457)
  770.         (440  0.15 457)
  771.         (392  0.15 457)
  772.         (349  0.15 457)
  773.         (311  0.15 457)
  774.         (294  0.15 457)
  775.         (262  0.15 457)
  776.         (294  0.15 457)
  777.         (311  0.15 457)
  778.         (294  0.15 457)
  779.         (262  0.15 457)
  780.         (233  0.15 457)
  781.         (208  0.15 457)
  782.         (196  0.15 457)
  783.         (175  0.15 457)
  784.         (466  0.15 457)
  785.         (415  0.15 457)
  786.         (392  0.15 457)
  787.         (349  0.15 457)
  788.         (311  0.15 457)
  789.         (294  0.15 457)
  790.         (262  0.15 457)
  791.         (233  0.15 457)
  792.         (262  0.15 457)
  793.         (294  0.15 457)
  794.         (262  0.15 457)
  795.         (233  0.15 457)
  796.         (208  0.15 457)
  797.         (196  0.15 457)
  798.         (175  0.15 457)
  799.         (156  0.15 457)
  800.         (415  0.15 457)
  801.         (392  0.15 457)
  802.         (349  0.15 457)
  803.         (311  0.15 457)
  804.         (277  0.15 457)
  805.         (262  0.15 457)
  806.         (233  0.15 457)
  807.         (208  0.30 457)
  808.         (523  0.30 457)
  809.         (466  0.30 457)
  810.         (415  0.30 457)
  811.         (392  0.30 457)
  812.         (349  0.30 457)
  813.         (392  0.30 457)
  814.         (415  0.30 457)
  815.         (294  0.30 457)
  816.         (311  0.30 457)
  817.         (349  0.30 457)
  818.         (294  0.30 457)
  819.         (311  0.30 457)
  820.         (415  0.30 457)
  821.         (392  0.30 457)
  822.         (349  0.30 457)
  823.         (392  0.30 457)
  824.         (311  0.30 457)
  825.         (294  0.30 457)
  826.         (262  0.30 457)
  827.         (294  0.30 457)
  828.         (466  0.30 457)
  829.         (415  0.30 457)
  830.         (392  0.30 457)
  831.         (415  0.30 457)
  832.         (349  0.30 457)
  833.         (311  0.30 457)
  834.         (294  0.30 457)
  835.         (311  0.30 457)
  836.         (rest 1.2)
  837.         (262  0.30 457)
  838.         (233  0.30 457)
  839.         (220  0.30 457)
  840.         (rest 0.3)
  841.         (311  0.30 457)
  842.         (294  0.30 457)
  843.         (262  0.30 457)
  844.         (294  0.30 457)
  845.         (262  0.15 457)
  846.         (233  0.15 457)
  847.         (262  0.30 457)
  848.         (294  0.30 457)
  849.         (196  0.30 591)
  850.         (466  0.15 591)
  851.         (440  0.15 591)
  852.         (466  0.30 591)
  853.         (294  0.30 591)
  854.         (311  0.30 591)
  855.         (523  0.15 591)
  856.         (466  0.15 591)
  857.         (523  0.30 591)
  858.         (330  0.30 591)
  859.         (349  0.30 591)
  860.         (587  0.15 591)
  861.         (523  0.15 591)
  862.         (587  0.30 591)
  863.         (370  0.30 591)
  864.         (392  0.60 591)
  865.         (rest 0.15)
  866.         (196  0.15 591)
  867.         (220  0.15 591)
  868.         (247  0.15 591)
  869.         (262  0.15 591)
  870.         (294  0.15 591)
  871.         (311  0.45 591)
  872.         (220  0.15 591)
  873.         (233  0.15 591)
  874.         (262  0.15 591)
  875.         (294  0.15 591)
  876.         (311  0.15 591)
  877.         (349  0.45 591)
  878.         (247  0.15 591)
  879.         (262  0.15 591)
  880.         (294  0.15 591)
  881.         (311  0.30 591)
  882.         (rest 0.6)
  883.         (330  0.30 591)
  884.         (349  0.30 591)
  885.         (175  0.30 591)
  886.         (156  0.30 591)
  887.         (147  0.30 591)
  888.         (rest 0.3)
  889.         (208  0.30 591)
  890.         (196  0.30 591)
  891.         (175  0.30 591)
  892.         (196  0.30 591)
  893.         (175  0.15 591)
  894.         (156  0.15 591)
  895.         (175  0.30 591)
  896.         (196  0.30 591)
  897.         (262  0.15 591)
  898.         (294  0.15 591)
  899.         (311  0.15 591)
  900.         (294  0.15 591)
  901.         (262  0.15 591)
  902.         (233  0.15 591)
  903.         (208  0.15 591)
  904.         (196  0.15 591)
  905.         (175  0.15 591)
  906.         (466  0.15 591)
  907.         (415  0.15 591)
  908.         (392  0.15 591)
  909.         (349  0.15 591)
  910.         (311  0.15 591)
  911.         (294  0.15 591)
  912.         (262  0.15 591)
  913.         (233  0.15 591)
  914.         (262  0.15 591)
  915.         (294  0.15 591)
  916.         (262  0.15 591)
  917.         (233  0.15 591)
  918.         (208  0.15 591)
  919.         (196  0.15 591)
  920.         (175  0.15 591)
  921.         (156  0.15 591)
  922.         (415  0.15 591)
  923.         (392  0.15 591)
  924.         (349  0.15 591)
  925.         (311  0.15 591)
  926.         (294  0.15 591)
  927.         (262  0.15 591)
  928.         (233  0.15 591)
  929.         (208  0.15 591)
  930.         (233  0.15 591)
  931.         (262  0.15 591)
  932.         (233  0.15 591)
  933.         (208  0.15 591)
  934.         (196  0.15 591)
  935.         (175  0.15 591)
  936.         (156  0.15 591)
  937.         (147  0.15 591)
  938.         (392  0.15 591)
  939.         (349  0.15 591)
  940.         (311  0.15 591)
  941.         (294  0.15 591)
  942.         (262  0.15 591)
  943.         (247  0.15 591)
  944.         (220  0.15 591)
  945.         (196  0.60 772)
  946.         (196  0.60 772)
  947.         (rest 0.15)
  948.         (196  0.15 772)
  949.         (220  0.15 772)
  950.         (247  0.15 772)
  951.         (262  0.15 772)
  952.         (294  0.15 772)
  953.         (311  0.15 772)
  954.         (349  0.15 772)
  955.         (392  0.15 772)
  956.         (349  0.15 772)
  957.         (415  0.15 772)
  958.         (392  0.15 772)
  959.         (349  0.15 772)
  960.         (311  0.15 772)
  961.         (294  0.15 772)
  962.         (262  0.15 772)
  963.         (247  0.30 772)
  964.         (262  0.15 772)
  965.         (494  0.15 772)
  966.         (262  0.30 772)
  967.         (196  0.30 772)
  968.         (208  0.30 772)
  969.         (262  0.15 772)
  970.         (247  0.15 772)
  971.         (262  0.30 772)
  972.         (294  0.30 772)
  973.         (196  0.30 772)
  974.         (262  0.15 772)
  975.         (247  0.15 772)
  976.         (262  0.30 772)
  977.         (294  0.30 772)
  978.         (175  0.15 772)
  979.         (196  0.15 772)
  980.         (208  0.60 772)
  981.         (196  0.15 772)
  982.         (175  0.15 772)
  983.         (156  0.60 772)
  984.         (rest 0.3)
  985.         (311  0.30 772)
  986.         (294  0.30 772)
  987.         (262  0.30 772)
  988.         (392  0.30 772)
  989.         (196  0.30 772)
  990.         (262  3.60 268)
  991.         (494  0.40 268)
  992.         (rest 0.4)
  993.         (494  0.40 268)
  994.         (rest 0.4)
  995.         (392  1.60 268)).
  996. !
  997. bachFugueVoice4
  998.     "Voice four of a fugue by J. S. Bach."
  999.     "FMSound bachFugueVoice4 play"
  1000.  
  1001.     ^ self noteSequenceFrom: #(
  1002.         (rest 61.2)
  1003.         (131  0.15 500)
  1004.         (123  0.15 500)
  1005.         (131  0.30 500)
  1006.         (98   0.30 500)
  1007.         (104  0.30 500)
  1008.         (131  0.15 500)
  1009.         (123  0.15 500)
  1010.         (131  0.30 500)
  1011.         (147  0.30 500)
  1012.         (98   0.30 500)
  1013.         (131  0.15 500)
  1014.         (123  0.15 500)
  1015.         (131  0.30 500)
  1016.         (147  0.30 500)
  1017.         (87   0.15 500)
  1018.         (98   0.15 500)
  1019.         (104  0.60 500)
  1020.         (98   0.15 500)
  1021.         (87   0.15 500)
  1022.         (78   0.60 500)
  1023.         (rest 0.3)
  1024.         (156  0.30 500)
  1025.         (147  0.30 500)
  1026.         (131  0.30 500)
  1027.         (196  0.30 500)
  1028.         (98   0.30 500)
  1029.         (131  3.60 268)
  1030.         (131  3.20 205)).
  1031. !
  1032. chromaticScale
  1033.     "PluckedSound chromaticScale play"
  1034.  
  1035.     ^ self namedNoteSequenceFrom: #(
  1036.         (c4 0.5 400)
  1037.         (cs4 0.5 400)        "s means sharp"
  1038.         (d4 0.5 400)
  1039.         (eb4 0.5 400)    "b means flat (it looks like a flat sign in music notation)"
  1040.         (e4 0.5 400)
  1041.         (f4 0.5 400)
  1042.         ('f#4' 0.5 400)    "# also means sharp, but it must be quoted within an array literal"
  1043.         (g4 0.5 400)
  1044.         (af4 0.5 400)        "f also means flat"
  1045.         (a4 0.5 400)
  1046.         (bb4 0.5 400)
  1047.         (b4 0.5 400)
  1048.         (c5 2.0 400))!
  1049. lowMajorScale
  1050.     "PluckedSound lowMajorScale play"
  1051.  
  1052.     ^ self namedNoteSequenceFrom: #(
  1053.         (c3 0.25 400)
  1054.         (d3 0.25 400)
  1055.         (e3 0.25 400)
  1056.         (f3 0.25 400)
  1057.         (g3 0.25 400)
  1058.         (a3 0.25 400)
  1059.         (b3 0.25 400)
  1060.         (c4 0.25 400)
  1061.         (d4 0.25 400)
  1062.         (c4 0.25 400)
  1063.         (b3 0.25 400)
  1064.         (a3 0.25 400)
  1065.         (g3 0.25 400)
  1066.         (f3 0.25 400)
  1067.         (e3 0.25 400)
  1068.         (d3 0.25 400)
  1069.         (c3 1.00 400))!
  1070. majorScale
  1071.     "BoinkSound majorScale play"
  1072.  
  1073.     ^ self namedNoteSequenceFrom: #(
  1074.         (c5 0.25 400)
  1075.         (d5 0.25 400)
  1076.         (e5 0.25 400)
  1077.         (f5 0.25 400)
  1078.         (g5 0.25 400)
  1079.         (a5 0.25 400)
  1080.         (b5 0.25 400)
  1081.         (c6 0.25 400)
  1082.         (d6 0.25 400)
  1083.         (c6 0.25 400)
  1084.         (b5 0.25 400)
  1085.         (a5 0.25 400)
  1086.         (g5 0.25 400)
  1087.         (f5 0.25 400)
  1088.         (e5 0.25 400)
  1089.         (d5 0.25 400)
  1090.         (c5 1.00 400))!
  1091. scaleTest
  1092.     "AbstractSound scaleTest play"
  1093.  
  1094.     ^ MixedSound new
  1095.         add: FMSound majorScale pan: 0;
  1096.         add: (PluckedSound lowMajorScale delayedBy: 0.5) pan: 1000.
  1097. !
  1098. testFMInteractively
  1099.     "Experiment with different settings of the FM modulation and multiplier settings interactively by moving the mouse. The top-left corner of the screen is 0 for both parameters. Stop when the mouse is pressed."
  1100.     "AbstractSound testFMInteractively"
  1101.  
  1102.     | s mousePt lastVal status |
  1103.     SoundPlayer startPlayerProcessBufferSize: 1100 rate: 22050 stereo: false.
  1104.     s _ FMSound pitch: 440.0 dur: 200.0 loudness: 200.
  1105.     s  decayRate: 1.0; modulationDecay: 1.0.
  1106.  
  1107.     SoundPlayer playSound: s.
  1108.     [Sensor anyButtonPressed] whileFalse: [
  1109.         mousePt _ Sensor cursorPoint.
  1110.         mousePt ~= lastVal ifTrue: [
  1111.             s modulation: mousePt x * 3 multiplier: mousePt y asFloat / 100.0.
  1112.             lastVal _ mousePt.
  1113.             status _
  1114. 'mod: ', (mousePt x * 3) printString, '
  1115. mult: ', (mousePt y asFloat / 100.0) printString.
  1116.             status asParagraph displayOn: Display at: 10@10.
  1117.         ].
  1118.     ].
  1119.     SoundPlayer pauseSound: s.
  1120. ! !Path subclass: #Arc
  1121.     instanceVariableNames: 'quadrant radius center '
  1122.     classVariableNames: ''
  1123.     poolDictionaries: ''
  1124.     category: 'Graphics-Paths'!
  1125. Arc comment:
  1126. 'Arcs are an unusual implementation of splines
  1127. due to Ted Kaehler.  Imagine two lines that meet at a corner.
  1128. Now imagine two moving points; one moves from the corner to
  1129. the end on one line, the other moves from the end of the other
  1130. line in to the corner.  Now imagine a series of lines drawn 
  1131. between those moving points at each step along the way (they
  1132. form a sort of spider web pattern).  By connecting segments
  1133. of the intersecting lines, a smooth curve is achieved that is
  1134. tangent to both of the original lines.  Voila.'!
  1135.  
  1136. !Arc methodsFor: 'accessing'!
  1137. center
  1138.     "Answer the point at the center of the receiver."
  1139.  
  1140.     ^center!
  1141. center: aPoint 
  1142.     "Set aPoint to be the receiver's center."
  1143.  
  1144.     center _ aPoint!
  1145. center: aPoint radius: anInteger 
  1146.     "The receiver is defined by a point at the center and a radius. The 
  1147.     quadrant is not reset."
  1148.  
  1149.     center _ aPoint.
  1150.     radius _ anInteger!
  1151. center: aPoint radius: anInteger quadrant: section 
  1152.     "Set the receiver's quadrant to be the argument, section. The size of the 
  1153.     receiver is defined by the center and its radius."
  1154.  
  1155.     center _ aPoint.
  1156.     radius _ anInteger.
  1157.     quadrant _ section!
  1158. quadrant
  1159.     "Answer the part of the circle represented by the receiver."
  1160.     ^quadrant!
  1161. quadrant: section 
  1162.     "Set the part of the circle represented by the receiver to be the argument, 
  1163.     section."
  1164.  
  1165.     quadrant _ section!
  1166. radius
  1167.     "Answer the receiver's radius."
  1168.  
  1169.     ^radius!
  1170. radius: anInteger 
  1171.     "Set the receiver's radius to be the argument, anInteger."
  1172.  
  1173.     radius _ anInteger! !
  1174.  
  1175. !Arc methodsFor: 'display box access'!
  1176. computeBoundingBox
  1177.     | aRectangle aPoint |
  1178.     aRectangle _ center - radius + form offset extent: form extent + (radius * 2) asPoint.
  1179.     aPoint _ center + form extent.
  1180.     quadrant = 1 ifTrue: [aRectangle left: center x; bottom: aPoint y].
  1181.     quadrant = 2 ifTrue: [aRectangle right: aPoint x; bottom: aPoint y].
  1182.     quadrant = 3 ifTrue: [aRectangle right: aPoint x; top: center y].
  1183.     quadrant = 4 ifTrue: [aRectangle left: center x; top: center y].
  1184.     ^aRectangle! !
  1185.  
  1186. !Arc methodsFor: 'displaying'!
  1187. displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
  1188.  
  1189.     | nSegments line angle sin cos xn yn xn1 yn1 |
  1190.     nSegments _ 12.0.
  1191.     line _ Line new.
  1192.     line form: self form.
  1193.     angle _ 90.0 / nSegments.
  1194.     sin _ (angle * (2 * Float pi / 360.0)) sin.
  1195.     cos _ (angle * (2 * Float pi / 360.0)) cos.
  1196.     quadrant = 1
  1197.         ifTrue: 
  1198.             [xn _ radius asFloat.
  1199.             yn _ 0.0].
  1200.     quadrant = 2
  1201.         ifTrue: 
  1202.             [xn _ 0.0.
  1203.             yn _ 0.0 - radius asFloat].
  1204.     quadrant = 3
  1205.         ifTrue: 
  1206.             [xn _ 0.0 - radius asFloat.
  1207.             yn _ 0.0].
  1208.     quadrant = 4
  1209.         ifTrue: 
  1210.             [xn _ 0.0.
  1211.             yn _ radius asFloat].
  1212.     nSegments asInteger
  1213.         timesRepeat: 
  1214.             [xn1 _ xn * cos + (yn * sin).
  1215.             yn1 _ yn * cos - (xn * sin).
  1216.             line beginPoint: center + (xn asInteger @ yn asInteger).
  1217.             line endPoint: center + (xn1 asInteger @ yn1 asInteger).
  1218.             line
  1219.                 displayOn: aDisplayMedium
  1220.                 at: aPoint
  1221.                 clippingBox: clipRect
  1222.                 rule: anInteger
  1223.                 fillColor: aForm.
  1224.             xn _ xn1.
  1225.             yn _ yn1]!
  1226. displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
  1227.  
  1228.     | newArc tempCenter |
  1229.     newArc _ Arc new.
  1230.     tempCenter _ aTransformation applyTo: self center.
  1231.     newArc center: tempCenter x asInteger @ tempCenter y asInteger.
  1232.     newArc quadrant: self quadrant.
  1233.     newArc radius: (self radius * aTransformation scale x) asInteger.
  1234.     newArc form: self form.
  1235.     newArc
  1236.         displayOn: aDisplayMedium
  1237.         at: 0 @ 0
  1238.         clippingBox: clipRect
  1239.         rule: anInteger
  1240.         fillColor: aForm! !
  1241. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1242.  
  1243. Arc class
  1244.     instanceVariableNames: ''!
  1245.  
  1246. !Arc class methodsFor: 'examples'!
  1247. example
  1248.     "Click the button somewhere on the screen. The designated point will
  1249.     be the center of an Arc with radius 50 in the 4th quadrant."
  1250.  
  1251.     | anArc aForm |
  1252.     aForm _ Form extent: 1 @ 30.    "make a long thin Form for display"
  1253.     aForm fillBlack.                        "turn it black"
  1254.     anArc _ Arc new.
  1255.     anArc form: aForm.                    "set the form for display"
  1256.     anArc radius: 50.0.
  1257.     anArc center: Sensor waitButton.
  1258.     anArc quadrant: 4.
  1259.     anArc displayOn: Display.
  1260.     Sensor waitButton
  1261.  
  1262.     "Arc example"! !ArrayedCollection variableSubclass: #Array
  1263.     instanceVariableNames: ''
  1264.     classVariableNames: ''
  1265.     poolDictionaries: ''
  1266.     category: 'Collections-Arrayed'!
  1267. Array comment:
  1268. 'I present an ArrayedCollection whose elements are objects.'!
  1269.  
  1270. !Array methodsFor: 'comparing'!
  1271. hash
  1272.     "Make sure that equal (=) arrays hash equally."
  1273.  
  1274.     self size = 0 ifTrue: [^17171].
  1275.     ^(self at: 1) hash + (self at: self size) hash!
  1276. hashMappedBy: map
  1277.     "Answer what my hash would be if oops changed according to map."
  1278.  
  1279.     self size = 0 ifTrue: [^self hash].
  1280.     ^(self first hashMappedBy: map) + (self last hashMappedBy: map)! !
  1281.  
  1282. !Array methodsFor: 'converting'!
  1283. asArray
  1284.     "Answer with the receiver itself."
  1285.  
  1286.     ^self!
  1287. elementsExchangeIdentityWith: otherArray
  1288.     <primitive: 128>
  1289.     self primitiveFailed!
  1290. evalStrings
  1291.        "Allows you to construct literal arrays.
  1292.     #(true false nil '5@6' 'Set new' '''text string''') evalStrings
  1293.     gives an array with true, false, nil, a Point, a Set, and a String
  1294.     instead of just a bunch of Symbols"
  1295.     | it |
  1296.  
  1297.     ^ self collect: [:each |
  1298.         it _ each.
  1299.         each == #true ifTrue: [it _ true].
  1300.               each == #false ifTrue: [it _ false].
  1301.         each == #nil ifTrue: [it _ nil].
  1302.         each class == String ifTrue: [
  1303.             it _ Compiler evaluate: each].
  1304.         each class == Array ifTrue: [it _ it evalStrings].
  1305.         it]! !
  1306.  
  1307. !Array methodsFor: 'printing'!
  1308. isLiteral
  1309.  
  1310.     self detect: [:element | element isLiteral not] ifNone: [^true].
  1311.     ^false!
  1312. printOn: aStream
  1313.  
  1314.     | tooMany |
  1315.     tooMany _ self maxPrint.    
  1316.         "Need absolute limit, or infinite recursion will never 
  1317.         notice anything going wrong.  7/26/96 tk"
  1318.     aStream nextPut: $(.
  1319.     self do: 
  1320.         [:element | 
  1321.         aStream position > tooMany ifTrue: [aStream nextPutAll: '...etc...)'. ^self].
  1322.         element printOn: aStream.
  1323.         aStream space].
  1324.     aStream nextPut: $)!
  1325. storeOn: aStream 
  1326.     "Use the literal form if possible."
  1327.  
  1328.     self isLiteral
  1329.         ifTrue: 
  1330.             [aStream nextPut: $#; nextPut: $(.
  1331.             self do: 
  1332.                 [:element | 
  1333.                 element printOn: aStream.
  1334.                 aStream space].
  1335.             aStream nextPut: $)]
  1336.         ifFalse: [super storeOn: aStream]! !
  1337.  
  1338. !Array methodsFor: 'private'!
  1339. replaceFrom: start to: stop with: replacement startingAt: repStart 
  1340.     "Primitive. This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the collection, replacement. Answer the receiver. Range checks are performed in the primitive only. Optional. See Object documentation whatIsAPrimitive."
  1341.     <primitive: 105>
  1342.     super replaceFrom: start to: stop with: replacement startingAt: repStart! !ArrayedCollection subclass: #Array2D
  1343.     instanceVariableNames: 'width contents '
  1344.     classVariableNames: ''
  1345.     poolDictionaries: ''
  1346.     category: 'Collections-Arrayed'!
  1347.  
  1348. !Array2D methodsFor: 'access'!
  1349. at: i at: j
  1350.     "return the element"
  1351.     (i < 1) | (i > width) ifTrue: [
  1352.         ^ self error: 'first index out of bounds'].
  1353.     "second index bounds check is automatic, since contents
  1354.         array will get a bounds error."
  1355.  
  1356.     ^ contents at: (j - 1) * width + i!
  1357. at: i at: j add: value
  1358.     "add value to the element"
  1359.     | index |
  1360.     (i < 1) | (i > width) ifTrue: [
  1361.         ^ self error: 'first index out of bounds'].
  1362.     "second index bounds check is automatic, since contents
  1363.         array will get a bounds error."
  1364.  
  1365.     index _ (j - 1) * width + i.
  1366.     ^ contents at: index put: (contents at: index) + value!
  1367. at: i at: j put: value
  1368.     "return the element"
  1369.     (i < 1) | (i > width) ifTrue: [
  1370.         ^ self error: 'first index out of bounds'].
  1371.     "second index bounds check is automatic, since contents
  1372.         array will get a bounds error."
  1373.  
  1374.     ^ contents at: (j - 1) * width + i put: value!
  1375. atAllPut: value
  1376.     "Initialize"
  1377.     contents atAllPut: value!
  1378. atCol: i
  1379.     "Fetch a whole column.  6/20/96 tk"
  1380.  
  1381.     | ans |
  1382.     ans _ contents class new: self height.
  1383.     1 to: self height do: [:ind |
  1384.         ans at: ind put: (self at: i at: ind)].
  1385.     ^ ans!
  1386. atCol: i put: list
  1387.     "Put in a whole column.
  1388.      hold first index constant"
  1389.  
  1390.     list size = self height ifFalse: [self error: 'wrong size']
  1391.     list doWithIndex: [:value :j |
  1392.         self at: i at: j put: value].!
  1393. atRow: j
  1394.     "Fetch a whole row.  6/20/96 tk"
  1395.  
  1396.     ^ contents copyFrom: (j - 1) * width + 1 to: (j) * width!
  1397. atRow: j put: list
  1398.     "Put in a whole row.
  1399.      hold second index constant"
  1400.  
  1401.     list size = self width ifFalse: [self error: 'wrong size']
  1402.     list doWithIndex: [:value :i |
  1403.         self at: i at: j put: value].!
  1404. do: aBlock
  1405.     "Iterate with X varying most quickly.  6/20/96 tk"
  1406.     ^ contents do: aBlock!
  1407. extent
  1408.     ^ width @ self height!
  1409. extent: extent fromArray: anArray
  1410.     "Load this 2-D array up from a 1-D array.  X varies most quickly.  6/20/96 tk"
  1411.  
  1412.     extent x * extent y = anArray size ifFalse: [
  1413.         ^ self error: 'dimensions don''t match'].
  1414.     width _ extent x.
  1415.     contents _ anArray.!
  1416. height
  1417.     "second dimension"
  1418.     "no need to save it"
  1419.     ^ contents size // width!
  1420. width
  1421.     "first dimension"
  1422.     ^ width!
  1423. width: x height: y type: class
  1424.     "Set the number of elements in the first and
  1425.     second dimensions.  class can be Array or String or ByteArray."
  1426.  
  1427.     contents == nil ifFalse: [self error: 'No runtime size change yet'].
  1428.         "later move all the elements to the new sized array"
  1429.     width _ x.
  1430.     contents _ class new: width*y.! !
  1431. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1432.  
  1433. Array2D class
  1434.     instanceVariableNames: ''!
  1435.  
  1436. !Array2D class methodsFor: 'as yet unclassified'!
  1437. new
  1438.     "Override ArrayedCollection.  6/20/96 tk"
  1439.     ^ self basicNew!
  1440. new: size
  1441.     "Use (self new width: x height: y type: Array)   6/20/96 tk"
  1442.     ^ self shouldNotImplement! !SequenceableCollection subclass: #ArrayedCollection
  1443.     instanceVariableNames: ''
  1444.     classVariableNames: ''
  1445.     poolDictionaries: ''
  1446.     category: 'Collections-Abstract'!
  1447. ArrayedCollection comment:
  1448. 'I am an abstract collection of elements with a fixed range of integers (from 1 to n>=1) as external keys.'!
  1449.  
  1450. !ArrayedCollection methodsFor: 'accessing'!
  1451. size
  1452.     "Primitive. Answer the number of indexable fields in the receiver. This
  1453.     value is the same as the largest legal subscript. Primitive is specified
  1454.     here to override SequenceableCollection size. Essential. See Object
  1455.     documentation whatIsAPrimitive. "
  1456.  
  1457.     <primitive: 62>
  1458.     ^self basicSize! !
  1459.  
  1460. !ArrayedCollection methodsFor: 'adding'!
  1461. add: newObject
  1462.  
  1463.     self shouldNotImplement! !
  1464.  
  1465. !ArrayedCollection methodsFor: 'printing'!
  1466. storeOn: aStream
  1467.  
  1468.     aStream nextPutAll: '(('.
  1469.     aStream nextPutAll: self class name.
  1470.     aStream nextPutAll: ' new: '.
  1471.     aStream store: self size.
  1472.     aStream nextPut: $).
  1473.     (self storeElementsFrom: 1 to: self size on: aStream)
  1474.         ifFalse: [aStream nextPutAll: '; yourself'].
  1475.     aStream nextPut: $)! !
  1476.  
  1477. !ArrayedCollection methodsFor: 'private'!
  1478. defaultElement
  1479.  
  1480.     ^nil!
  1481. fill: numElements fromStack: aContext 
  1482.     "Fill me with numElements elements, popped in reverse order from
  1483.      the stack of aContext.  Do not call directly: this is called indirectly by {1. 2. 3}
  1484.      constructs."
  1485.  
  1486.     aContext pop: numElements toIndexable: self!
  1487. storeElementsFrom: firstIndex to: lastIndex on: aStream
  1488.  
  1489.     | noneYet defaultElement arrayElement |
  1490.     noneYet _ true.
  1491.     defaultElement _ self defaultElement.
  1492.     firstIndex to: lastIndex do: 
  1493.         [:index | 
  1494.         arrayElement _ self at: index.
  1495.         arrayElement = defaultElement
  1496.             ifFalse: 
  1497.                 [noneYet
  1498.                     ifTrue: [noneYet _ false]
  1499.                     ifFalse: [aStream nextPut: $;].
  1500.                 aStream nextPutAll: ' at: '.
  1501.                 aStream store: index.
  1502.                 aStream nextPutAll: ' put: '.
  1503.                 aStream store: arrayElement]].
  1504.     ^noneYet! !
  1505. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1506.  
  1507. ArrayedCollection class
  1508.     instanceVariableNames: ''!
  1509.  
  1510. !ArrayedCollection class methodsFor: 'instance creation'!
  1511. fromBraceStack: itsSize 
  1512.     "Answer an instance of me with itsSize elements, popped in reverse order from
  1513.      the stack of thisContext sender.  Do not call directly: this is called by {1. 2. 3}
  1514.      constructs."
  1515.  
  1516.     ^ (self new: itsSize) fill: itsSize fromStack: thisContext sender!
  1517. new
  1518.     "Answer a new instance of me, with size = 0."
  1519.  
  1520.     ^self new: 0!
  1521. new: size withAll: value 
  1522.     "Answer an instance of me, with number of elements equal to size, each 
  1523.     of which refers to the argument, value."
  1524.  
  1525.     ^(self new: size) atAllPut: value!
  1526. newFrom: aCollection 
  1527.     "Answer an instance of me containing the same elements as aCollection."
  1528.     | newArray |
  1529.     newArray _ self new: aCollection size.
  1530.     1 to: aCollection size do: [:i | newArray at: i put: (aCollection at: i)].
  1531.     ^ newArray
  1532.  
  1533. "    Array newFrom: {1. 2. 3}
  1534.     {1. 2. 3} as: Array
  1535.     {1. 2. 3} as: ByteArray
  1536.     {$c. $h. $r} as: String
  1537.     {$c. $h. $r} as: Text
  1538. "!
  1539. with: anObject 
  1540.     "Answer a new instance of me, containing only anObject."
  1541.  
  1542.     | newCollection |
  1543.     newCollection _ self new: 1.
  1544.     newCollection at: 1 put: anObject.
  1545.     ^newCollection!
  1546. with: firstObject with: secondObject 
  1547.     "Answer a new instance of me, containing firstObject and secondObject."
  1548.  
  1549.     | newCollection |
  1550.     newCollection _ self new: 2.
  1551.     newCollection at: 1 put: firstObject.
  1552.     newCollection at: 2 put: secondObject.
  1553.     ^newCollection!
  1554. with: firstObject with: secondObject with: thirdObject 
  1555.     "Answer a new instance of me, containing only the three arguments as
  1556.     elements."
  1557.  
  1558.     | newCollection |
  1559.     newCollection _ self new: 3.
  1560.     newCollection at: 1 put: firstObject.
  1561.     newCollection at: 2 put: secondObject.
  1562.     newCollection at: 3 put: thirdObject.
  1563.     ^newCollection!
  1564. with: firstObject with: secondObject with: thirdObject with: fourthObject 
  1565.     "Answer a new instance of me, containing only the three arguments as
  1566.     elements."
  1567.  
  1568.     | newCollection |
  1569.     newCollection _ self new: 4.
  1570.     newCollection at: 1 put: firstObject.
  1571.     newCollection at: 2 put: secondObject.
  1572.     newCollection at: 3 put: thirdObject.
  1573.     newCollection at: 4 put: fourthObject.
  1574.     ^newCollection!
  1575. with: firstObject with: secondObject with: thirdObject with: fourthObject with: fifthObject
  1576.     "Answer a new instance of me, containing only the five arguments as
  1577.     elements."
  1578.  
  1579.     | newCollection |
  1580.     newCollection _ self new: 5.
  1581.     newCollection at: 1 put: firstObject.
  1582.     newCollection at: 2 put: secondObject.
  1583.     newCollection at: 3 put: thirdObject.
  1584.     newCollection at: 4 put: fourthObject.
  1585.     newCollection at: 5 put: fifthObject.
  1586.     ^newCollection! !ParseNode subclass: #AssignmentNode
  1587.     instanceVariableNames: 'variable value '
  1588.     classVariableNames: ''
  1589.     poolDictionaries: ''
  1590.     category: 'System-Compiler'!
  1591. AssignmentNode comment: 'I represent a (var_expr) construct.'!
  1592.  
  1593. !AssignmentNode methodsFor: 'initialize-release'!
  1594. toDoIncrement: var
  1595.     var = variable ifFalse: [^ nil].
  1596.     (value isMemberOf: MessageNode) 
  1597.         ifTrue: [^ value toDoIncrement: var]
  1598.         ifFalse: [^ nil]!
  1599. value
  1600.     ^ value!
  1601. variable: aVariable value: expression
  1602.  
  1603.     variable _ aVariable.
  1604.     value _ expression!
  1605. variable: aVariable value: expression from: encoder
  1606.  
  1607.     (aVariable isMemberOf: MessageNode)
  1608.         ifTrue: [^aVariable store: expression from: encoder].
  1609.     variable _ aVariable.
  1610.     value _ expression! !
  1611.  
  1612. !AssignmentNode methodsFor: 'code generation'!
  1613. emitForEffect: stack on: aStream
  1614.  
  1615.     value emitForValue: stack on: aStream.
  1616.     variable emitStorePop: stack on: aStream!
  1617. emitForValue: stack on: aStream
  1618.  
  1619.     value emitForValue: stack on: aStream.
  1620.     variable emitStore: stack on: aStream!
  1621. sizeForEffect: encoder
  1622.  
  1623.     ^(value sizeForValue: encoder)
  1624.         + (variable sizeForStorePop: encoder)!
  1625. sizeForValue: encoder
  1626.  
  1627.     ^(value sizeForValue: encoder)
  1628.         + (variable sizeForStore: encoder)! !
  1629.  
  1630. !AssignmentNode methodsFor: 'printing'!
  1631. printOn: aStream indent: level
  1632.  
  1633.     variable printOn: aStream indent: level.
  1634.     aStream nextPutAll: ' _ '.
  1635.     value printOn: aStream indent: level + 2!
  1636. printOn: aStream indent: level precedence: p
  1637.  
  1638.     p < 4 ifTrue: [aStream nextPutAll: '('].
  1639.     self printOn: aStream indent: level.
  1640.     p < 4 ifTrue: [aStream nextPutAll: ')']! !
  1641.  
  1642. !AssignmentNode methodsFor: 'equation translation'!
  1643. collectVariables
  1644.     ^variable collectVariables, value collectVariables!
  1645. copyReplacingVariables: varDict
  1646.     | t1 t2 | 
  1647.     t1 _ variable copyReplacingVariables: varDict.
  1648.     t2 _ value copyReplacingVariables: varDict.
  1649.     ^self class new variable: t1 value: t2!
  1650. specificMatch: aTree using: matchDict 
  1651.     ^(variable match: aTree variable using: matchDict)
  1652.         and: [value match: aTree value using: matchDict]!
  1653. variable
  1654.     ^variable! !
  1655.  
  1656. !AssignmentNode methodsFor: 'C translation'! !LookupKey subclass: #Association
  1657.     instanceVariableNames: 'value '
  1658.     classVariableNames: ''
  1659.     poolDictionaries: ''
  1660.     category: 'Collections-Support'!
  1661. Association comment:
  1662. 'I represent a pair of associated objects--a key and a value. My instances can serve as entries in a dictionary.'!
  1663.  
  1664. !Association methodsFor: 'accessing'!
  1665. key: aKey value: anObject 
  1666.     "Store the arguments as the variables of the receiver."
  1667.  
  1668.     key _ aKey.
  1669.     value _ anObject!
  1670. value
  1671.     "Answer the value of the receiver."
  1672.  
  1673.     ^value!
  1674. value: anObject 
  1675.     "Store the argument, anObject, as the value of the receiver."
  1676.  
  1677.     value _ anObject! !
  1678.  
  1679. !Association methodsFor: 'printing'!
  1680. printOn: aStream
  1681.  
  1682.     super printOn: aStream.
  1683.     aStream nextPutAll: '->'.
  1684.     value printOn: aStream!
  1685. storeOn: aStream
  1686.     "Store in the format (key->value)"
  1687.     aStream nextPut: $(.
  1688.     key storeOn: aStream.
  1689.     aStream nextPutAll: '->'.
  1690.     value storeOn: aStream.
  1691.     aStream nextPut: $)! !
  1692. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1693.  
  1694. Association class
  1695.     instanceVariableNames: ''!
  1696.  
  1697. !Association class methodsFor: 'instance creation'!
  1698. key: newKey value: newValue
  1699.     "Answer an instance of me with the arguments as the key and value of 
  1700.     the association."
  1701.  
  1702.     ^(super key: newKey) value: newValue! !Collection subclass: #Bag
  1703.     instanceVariableNames: 'contents '
  1704.     classVariableNames: ''
  1705.     poolDictionaries: ''
  1706.     category: 'Collections-Unordered'!
  1707. Bag comment:
  1708. 'I represent an unordered collection of possibly duplicate elements.
  1709.     
  1710. I store these elements in a dictionary, tallying up occurrences of equal objects. Because I store an occurrence only once, my clients should beware that objects they store will not necessarily be retrieved such that == is true. If the client cares, a subclass of me should be created.'!
  1711.  
  1712. !Bag methodsFor: 'accessing'!
  1713. at: index
  1714.  
  1715.     self errorNotKeyed!
  1716. at: index put: anObject
  1717.  
  1718.     self errorNotKeyed!
  1719. size
  1720.  
  1721.     | tally |
  1722.     tally _ 0.
  1723.     contents do: [:each | tally _ tally + each].
  1724.     ^tally!
  1725. sortedCounts
  1726.     "Answer with a collection of counts with elements, sorted by decreasing
  1727.     count."
  1728.  
  1729.     | counts |
  1730.     counts _ SortedCollection sortBlock: [:x :y | x >= y].
  1731.     contents associationsDo:
  1732.         [:assn |
  1733.         counts add: (Association key: assn value value: assn key)].
  1734.     ^counts!
  1735. sortedElements
  1736.     "Answer with a collection of elements with counts, sorted by element."
  1737.  
  1738.     | elements |
  1739.     elements _ SortedCollection new.
  1740.     contents associationsDo: [:assn | elements add: assn].
  1741.     ^elements! !
  1742.  
  1743. !Bag methodsFor: 'testing'!
  1744. includes: anObject 
  1745.     "Refer to the comment in Collection|includes:."
  1746.  
  1747.     ^contents includesKey: anObject!
  1748. occurrencesOf: anObject 
  1749.     "Refer to the comment in Collection|occurrencesOf:."
  1750.  
  1751.     (self includes: anObject)
  1752.         ifTrue: [^contents at: anObject]
  1753.         ifFalse: [^0]! !
  1754.  
  1755. !Bag methodsFor: 'adding'!
  1756. add: newObject 
  1757.     "Refer to the comment in Collection|add:."
  1758.  
  1759.     ^self add: newObject withOccurrences: 1!
  1760. add: newObject withOccurrences: anInteger 
  1761.     "Add the element newObject to the receiver. Do so as though the element 
  1762.     were added anInteger number of times. Answer newObject."
  1763.  
  1764.     (self includes: newObject)
  1765.         ifTrue: [contents at: newObject put: anInteger + (contents at: newObject)]
  1766.         ifFalse: [contents at: newObject put: anInteger].
  1767.     ^newObject! !
  1768.  
  1769. !Bag methodsFor: 'removing'!
  1770. remove: oldObject ifAbsent: exceptionBlock 
  1771.     "Refer to the comment in Collection|remove:ifAbsent:."
  1772.  
  1773.     | count |
  1774.     (self includes: oldObject)
  1775.         ifTrue: [(count _ contents at: oldObject) = 1
  1776.                 ifTrue: [contents removeKey: oldObject]
  1777.                 ifFalse: [contents at: oldObject put: count - 1]]
  1778.         ifFalse: [^exceptionBlock value].
  1779.     ^oldObject! !
  1780.  
  1781. !Bag methodsFor: 'enumerating'!
  1782. do: aBlock 
  1783.     "Refer to the comment in Collection|do:."
  1784.  
  1785.     contents associationsDo: [:assoc | assoc value timesRepeat: [aBlock value: assoc key]]! !
  1786.  
  1787. !Bag methodsFor: 'private'!
  1788. setDictionary
  1789.  
  1790.     contents _ Dictionary new! !
  1791. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1792.  
  1793. Bag class
  1794.     instanceVariableNames: ''!
  1795.  
  1796. !Bag class methodsFor: 'instance creation'!
  1797. new
  1798.  
  1799.     ^super new setDictionary!
  1800. newFrom: aCollection 
  1801.     "Answer an instance of me containing the same elements as aCollection."
  1802.  
  1803.     | newCollection |
  1804.     newCollection _ self new.
  1805.     newCollection addAll: aCollection.
  1806.     ^newCollection
  1807.  
  1808. "    Bag newFrom: {1. 2. 3}
  1809.     {1. 2. 3} as: Bag
  1810. "! !Object subclass: #Behavior
  1811.     instanceVariableNames: 'superclass methodDict format subclasses '
  1812.     classVariableNames: ''
  1813.     poolDictionaries: ''
  1814.     category: 'Kernel-Classes'!
  1815. Behavior comment:
  1816. 'My instances describe the behavior of other objects. I provide the minimum state necessary for compiling methods, and creating and running instances. Most objects are created as instances of the more fully supported subclass, Class, but I am a good starting point for providing instance-specific behavior (as in Metaclass).'!
  1817.  
  1818. !Behavior methodsFor: 'initialize-release'!
  1819. obsolete
  1820.     "Invalidate and recycle local messages. Remove the receiver from its 
  1821.     superclass' subclass list."
  1822.  
  1823.     methodDict _ MethodDictionary new.
  1824.     superclass removeSubclass: self! !
  1825.  
  1826. !Behavior methodsFor: 'accessing'!
  1827. compilerClass
  1828.     "Answer a compiler class appropriate for source methods of this class."
  1829.  
  1830.     ^Compiler!
  1831. confirmRemovalOf: aSelector
  1832.     "Determine if it is okay to remove the given selector.  Answer 1 if it should be removed, 2 if it should be removed followed by a senders browse, and 3 if it should not be removed. 1/17/96 sw
  1833.     9/18/96 sw: made the wording more delicate"
  1834.  
  1835.     | count aMenu answer caption allCalls |
  1836.     (count _ (allCalls _ Smalltalk allCallsOn: aSelector) size) > 0
  1837.         ifTrue:
  1838.             [aMenu _ PopUpMenu labels: 'Remove it
  1839. Remove, then browse senders
  1840. Don''t remove, but show me those senders
  1841. Forget it -- do nothing -- sorry I asked'.
  1842.  
  1843.             caption _ 'This message has ', count printString, ' sender'.
  1844.             count > 1 ifTrue:
  1845.                 [caption _ caption copyWith: $s].
  1846.             answer _ aMenu startUpWithCaption: caption.
  1847.             answer == 3 ifTrue:
  1848.                 [Smalltalk browseMessageList: allCalls
  1849.                     name: 'Senders of ', aSelector
  1850.                     autoSelect: aSelector].
  1851.             answer == 0 ifTrue: [answer _ 3].  "If user didn't answer, treat it as cancel"
  1852.             ^ answer min: 3]
  1853.         ifFalse:
  1854.             [^ 1]
  1855.     !
  1856. decompilerClass
  1857.     "Answer a decompiler class appropriate for compiled methods of this class."
  1858.  
  1859.     ^Decompiler!
  1860. evaluatorClass
  1861.     "Answer an evaluator class appropriate for evaluating expressions in the 
  1862.     context of this class."
  1863.  
  1864.     ^Compiler!
  1865. format
  1866.     "Answer an Integer that encodes the kinds and numbers of variables of 
  1867.     instances of the receiver."
  1868.  
  1869.     ^format!
  1870. parserClass
  1871.     "Answer a parser class to use for parsing method headers."
  1872.  
  1873.     ^self compilerClass parserClass!
  1874. sourceCodeTemplate
  1875.     "Answer an expression to be edited and evaluated in order to define 
  1876.     methods in this class."
  1877.  
  1878.     ^'message selector and argument names
  1879.     "comment stating purpose of message"
  1880.  
  1881.     | temporary variable names |
  1882.     statements'!
  1883. subclassDefinerClass
  1884.     "Answer an evaluator class appropriate for evaluating definitions of new 
  1885.     subclasses of this class."
  1886.  
  1887.     ^Compiler! !
  1888.  
  1889. !Behavior methodsFor: 'testing'!
  1890. instSize
  1891.     "Answer the number of named instance variables
  1892.     (as opposed to indexed variables) of the receiver."
  1893.  
  1894.     ^ ((format bitShift: -1) bitAnd: 16r3F) - 1!
  1895. instSpec
  1896.     ^ (format bitShift: -7) bitAnd: 16rF!
  1897. isBits
  1898.     "Answer whether the receiver contains just bits (not pointers)."
  1899.  
  1900.     ^ self instSpec >= 6!
  1901. isBytes
  1902.     "Answer whether the receiver has 8-bit instance variables."
  1903.  
  1904.     ^ self instSpec >= 8!
  1905. isFixed
  1906.     "Answer whether the receiver does not have a variable (indexable) part."
  1907.  
  1908.     ^self isVariable not!
  1909. isPointers
  1910.     "Answer whether the receiver contains just pointers (not bits)."
  1911.  
  1912.     ^self isBits not!
  1913. isVariable
  1914.     "Answer whether the receiver has indexable variables."
  1915.  
  1916.     ^ self instSpec >= 2!
  1917. isWords
  1918.     "Answer whether the receiver has 16-bit instance variables."
  1919.  
  1920.     ^self isBytes not! !
  1921.  
  1922. !Behavior methodsFor: 'copying'!
  1923. copy
  1924.     "Answer a copy of the receiver without a list of subclasses."
  1925.  
  1926.     | myCopy savedSubclasses |
  1927.     savedSubclasses _ subclasses.
  1928.     subclasses _ nil.         
  1929.     myCopy _ self shallowCopy.
  1930.     subclasses _ savedSubclasses.
  1931.     ^myCopy methodDictionary: methodDict copy! !
  1932.  
  1933. !Behavior methodsFor: 'printing'!
  1934. literalScannedAs: scannedLiteral notifying: requestor
  1935.     "Postprocesses a literal scanned by Scanner scanToken (esp. xLitQuote).
  1936.     If scannedLiteral is not an association, answer it.
  1937.     Else, if it is of the form:
  1938.         nil->#NameOfMetaclass
  1939.     answer nil->theMetaclass, if any has that name, else report an error.
  1940.     Else, if it is of the form:
  1941.         #NameOfGlobalVariable->anythiEng
  1942.     answer the global, class, or pool association with that nameE, if any, else
  1943.     add it to Undeclared a answer the new Association."
  1944.  
  1945.     | key value |
  1946.     (scannedLiteral isMemberOf: Association)
  1947.         ifFalse: [^ scannedLiteral].
  1948.     key _ scannedLiteral key.
  1949.     value _ scannedLiteral value.
  1950.     key isNil 
  1951.         ifTrue: "###<metaclass soleInstance name>"
  1952.             [self scopeHas: value ifTrue:
  1953.                 [:assoc |
  1954.                  (assoc value isKindOf: Behavior)
  1955.                     ifTrue: [^ nil->assoc value class]].
  1956.              requestor notify: 'No such metaclass'.
  1957.              ^false].
  1958.     (key isMemberOf: Symbol)
  1959.         ifTrue: "##<global var name>"
  1960.             [(self scopeHas: key ifTrue: [:assoc | ^assoc])
  1961.                 ifFalse:
  1962.                     [Undeclared at: key put: nil.
  1963.                      ^ Undeclared associationAt: key]].
  1964.     requestor notify: '## must be followed by a non-local variable name'.
  1965.     ^false
  1966.  
  1967. "    Form literalScannedAs: 14 notifying: nil 14
  1968.     Form literalScannedAs: #OneBitForm notiEfying: nil  OneBitForm
  1969.     Form literalScannedAs: ##OneBitForm notifying: nil  OneBitForm->a Form
  1970.     Form literalScannedAs: ##Form notifying: nil   Form->Form
  1971.     Form literalScannedAs: ###Form notifying: nil   nilE->Form class
  1972. "!
  1973. printHierarchy
  1974.     "Answer a description containing the names and instance variable names 
  1975.     of all of the subclasses and superclasses of the receiver."
  1976.  
  1977.     | aStream index |
  1978.     index _ 0.
  1979.     aStream _ WriteStream on: (String new: 16).
  1980.     self allSuperclasses reverseDo: 
  1981.         [:aClass | 
  1982.         aStream crtab: index.
  1983.         index _ index + 1.
  1984.         aStream nextPutAll: aClass name.
  1985.         aStream space.
  1986.         aStream print: aClass instVarNames].
  1987.     aStream cr.
  1988.     self printSubclassesOn: aStream level: index.
  1989.     ^aStream contents!
  1990. printOn: aStream 
  1991.     "Refer to the comment in Object|printOn:." 
  1992.  
  1993.     aStream nextPutAll: 'a descendent of '.
  1994.     superclass printOn: aStream!
  1995. storeLiteral: aCodeLiteral on: aStream
  1996.     "Store aCodeLiteral on aStream, changing an Association to ##GlobalName
  1997.      or ###MetaclassSoleInstanceName format if appropriate"
  1998.     | key value |
  1999.     (aCodeLiteral isMemberOf: Association)
  2000.         ifFalse:
  2001.             [aCodeLiteral storeOn: aStream.
  2002.              ^self].
  2003.     key _ aCodeLiteral key.
  2004.     (key isNil and: [(value _ aCodeLiteral value) isMemberOf: Metaclass])
  2005.         ifTrue:
  2006.             [aStream nextPutAll: '###'; nextPutAll: value soleInstance name.
  2007.              ^self].
  2008.     ((key isMemberOf: Symbol) and: [self scopeHas: key ifTrue: [:ignore]])
  2009.         ifTrue:
  2010.             [aStream nextPutAll: '##'; nextPutAll: key.
  2011.              ^self].
  2012.     aCodeLiteral storeOn: aStream! !
  2013.  
  2014. !Behavior methodsFor: 'creating class hierarchy'!
  2015. addSubclass: aSubclass 
  2016.     "Make the argument, aSubclass, be one of the subclasses of the receiver. 
  2017.     Create an error notification if the argument's superclass is not the 
  2018.     receiver."
  2019.     
  2020.     aSubclass superclass ~~ self 
  2021.         ifTrue: [self error: aSubclass name , ' is not my subclass']
  2022.         ifFalse: [subclasses == nil
  2023.                     ifTrue:    [subclasses _ Set with: aSubclass]
  2024.                     ifFalse:    [subclasses add: aSubclass]]!
  2025. removeSubclass: aSubclass 
  2026.     "If the argument, aSubclass, is one of the receiver's subclasses, remove it."
  2027.  
  2028.     subclasses == nil ifFalse:
  2029.         [subclasses remove: aSubclass ifAbsent: [].
  2030.         subclasses isEmpty ifTrue: [subclasses _ nil]]!
  2031. superclass: aClass 
  2032.     "Change the receiver's superclass to be aClass."
  2033.  
  2034.     (aClass isKindOf: Behavior)
  2035.         ifTrue: [superclass _ aClass]
  2036.         ifFalse: [self error: 'superclass must be a class-describing object']! !
  2037.  
  2038. !Behavior methodsFor: 'creating method dictionary'!
  2039. addSelector: selector withMethod: compiledMethod 
  2040.     "Add the message selector with the corresponding compiled method to the 
  2041.     receiver's method dictionary."
  2042.  
  2043.     methodDict at: selector put: compiledMethod.
  2044.     self flushCache!
  2045. compile: code 
  2046.     "Compile the argument, code, as source code in the context of the 
  2047.     receiver. Create an error notification if the code can not be compiled. 
  2048.     The argument is either a string or an object that converts to a string or a 
  2049.     PositionableStream on an object that converts to a string."
  2050.  
  2051.     ^self compile: code notifying: nil!
  2052. compile: code notifying: requestor 
  2053.     "Compile the argument, code, as source code in the context of the 
  2054.     receiver and insEtall the result in the receiver's method dictionary. The 
  2055.     second argument, requestor, is to be notified if an error occurs. The 
  2056.     argument code is either a striEng or an object that converts to a string or 
  2057.     a PEositionableStrean an object that converts to a string. This method 
  2058.     also saves the source code."
  2059.  
  2060.     | method selector |
  2061.     method _ self
  2062.         compile: code
  2063.         notifying: requestor
  2064.         trailer: #(0 0 0 )
  2065.         ifFail: [^nil]
  2066.         elseSetSelectorAndNode: 
  2067.             [:sel :methodNode | selector _ sel].
  2068.     method putSource: code asString inFile: 2.
  2069.     ^selector!
  2070. compile: code notifying: requestor trailer: bytes 
  2071.     "Compile the argument, code, as source code in the context of the 
  2072.     receiver. Use the default faiEl code [^nil]. Does not save source code. Th 
  2073.     second argument, requestor, is to be notified if an error occurs. The 
  2074.     argument code is either a string or an object that converts to a string or 
  2075.     a PositionableStream on an object that converts to a string. The third 
  2076.     argument, bytes, is a trailer, that is, an array of three bytes that should 
  2077.     be added to the end of the compiled method. These point to the location 
  2078.     of the source code (on a file)."
  2079.  
  2080.     ^ self compile: code notifying: requestor trailer: bytes
  2081.         ifFail: [^ nil]
  2082.         elseSetSelectorAndNode: [:s :n]!
  2083. compileAll
  2084.     ^ self compileAllFrom: self!
  2085. compileAllFrom: oldClass
  2086.     "Compile all the methods in the receiver's method dictionary.
  2087.     This validates sourceCode and variable references and forces
  2088.     all methods to use the current bytecode set"
  2089.  
  2090.     self selectorsDo: [:sel | self recompile: sel from: oldClass]!
  2091. decompile: selector 
  2092.     "Find the compiled code associated with the argument, selector, as a 
  2093.     message selector in the receiver's method dictionary and decompile it. 
  2094.     Answer the resulting source code as a string. Create an error notification 
  2095.     if the selector is not in the receiver's method dictionary."
  2096.  
  2097.     ^self decompilerClass new decompile: selector in: self!
  2098. defaultSelectorForMethod: aMethod 
  2099.     "Given a method, invent and answer an appropriate message selector (a 
  2100.     Symbol), that is, one that will parse with the correct number of 
  2101.     arguments."
  2102.  
  2103.     | aStream |
  2104.     aStream _ WriteStream on: (String new: 16).
  2105.     aStream nextPutAll: 'DoIt'.
  2106.     1 to: aMethod numArgs do: [:i | aStream nextPutAll: 'with:'].
  2107.     ^aStream contents asSymbol!
  2108. methodDictionary: aDictionary 
  2109.     "Store the argument, aDictionary, as the method dictionary of the 
  2110.     receiver."
  2111.  
  2112.     methodDict _ aDictionary!
  2113. recompile: selector from: oldClass
  2114.     "Compile the method associated with selector in the receiver's method dictionary."
  2115.  
  2116.     | method trailer methodNode |
  2117.     method _ self compiledMethodAt: selector.
  2118.     trailer _ (method size - 2 to: method size) collect: [:i | method at: i].
  2119.     methodNode _ self compilerClass new
  2120.                 compile: (oldClass sourceCodeAt: selector)
  2121.                 in: self
  2122.                 notifying: nil
  2123.                 ifFail: [].
  2124.     methodNode == nil  "Try again after proceed from SyntaxError"
  2125.         ifTrue: [^self recompile: selector from: oldClass].
  2126.     selector == methodNode selector ifFalse: [self error: 'selector changed!!'].
  2127.     self addSelector: selector withMethod: (methodNode generate: trailer).
  2128. !
  2129. recompileChanges
  2130.     "Compile all the methods that are in the changes file.
  2131.     This validates sourceCode and variable references and forces
  2132.     methods to use the current bytecode set"
  2133.  
  2134.     self selectorsDo:
  2135.         [:sel | (self compiledMethodAt: sel) fileIndex > 1 ifTrue:
  2136.             [self recompile: sel from: self]]!
  2137. removeSelector: selector 
  2138.     "Assuming that the argument, selector (a Symbol), is a message selector 
  2139.     in the receiver's method dictionary, remove it. If the selector is not in 
  2140.     the method dictionary, create an error notification."
  2141.  
  2142.     methodDict removeKey: selector.
  2143.     self flushCache! !
  2144.  
  2145. !Behavior methodsFor: 'instance creation'!
  2146. basicNew
  2147.     "Primitive. Answer an instance of the receiver (which is a class) with no 
  2148.     indexable variables. Fail if the class is indexable. Essential. See Object 
  2149.     documentation whatIsAPrimitive."
  2150.  
  2151.     <primitive: 70>
  2152.     self isVariable ifTrue: [ ^ self basicNew: 0 ].
  2153.     "space must be low"
  2154.     Smalltalk signalLowSpace.
  2155.     ^ self basicNew  "retry if user proceeds"
  2156. !
  2157. basicNew: anInteger 
  2158.     "Primitive. Answer an instance of the receiver (which is a class) with the 
  2159.     number of indexable variables specified by the argument, anInteger. Fail 
  2160.     if the class is not indexable or if the argument is not a positive Integer. 
  2161.     Essential. See Object documentation whatIsAPrimitive."
  2162.  
  2163.     <primitive: 71>
  2164.     (anInteger isInteger and: [anInteger >= 0]) ifTrue: [
  2165.         "arg okay; space must be low"
  2166.         Smalltalk signalLowSpace.
  2167.         ^ self basicNew: anInteger  "retry if user proceeds"
  2168.     ].
  2169.     self primitiveFailed!
  2170. new
  2171.     "Primitive. Answer an instance of the receiver (which is a class) with no 
  2172.     indexable variables. Fail if the class is indexable. Essential. See Object 
  2173.     documentation whatIsAPrimitive."
  2174.  
  2175.     <primitive: 70>
  2176.     self isVariable ifTrue: [ ^ self new: 0 ].
  2177.     "space must be low"
  2178.     Smalltalk signalLowSpace.
  2179.     ^ self new  "retry if user proceeds"
  2180. !
  2181. new: anInteger 
  2182.     "Primitive. Answer an instance of the receiver (which is a class) with the 
  2183.     number of indexable variables specified by the argument, anInteger. Fail 
  2184.     if the class is not indexable or if the argument is not a positive Integer. 
  2185.     Essential. See Object documentation whatIsAPrimitive."
  2186.  
  2187.     <primitive: 71>
  2188.     (anInteger isInteger and: [anInteger >= 0]) ifTrue: [
  2189.         "arg okay; space must be low"
  2190.         Smalltalk signalLowSpace.
  2191.         ^ self new: anInteger  "retry if user proceeds"
  2192.     ].
  2193.     self primitiveFailed! !
  2194.  
  2195. !Behavior methodsFor: 'accessing class hierarchy'!
  2196. allSubclasses
  2197.     "Answer a Set of the receiver's and the receiver's descendent's subclasses."
  2198.  
  2199.     | aSet |
  2200.     aSet _ Set new.
  2201.     aSet addAll: self subclasses.
  2202.     self subclasses do: [:eachSubclass | aSet addAll: eachSubclass allSubclasses].
  2203.     ^aSet!
  2204. allSuperclasses
  2205.     "Answer an OrderedCollection of the receiver's and the receiver's 
  2206.     ancestor's superclasses. The first element is the receiver's immediate 
  2207.     superclass, followed by its superclass; the last element is Object."
  2208.  
  2209.     | temp |
  2210.     superclass == nil
  2211.         ifTrue: [^OrderedCollection new]
  2212.         ifFalse: [temp _ superclass allSuperclasses.
  2213.                 temp addFirst: superclass.
  2214.                 ^temp]!
  2215. subclasses
  2216.     "Answer a Set containing the receiver's subclasses."
  2217.  
  2218.     subclasses == nil
  2219.         ifTrue: [^Set new]
  2220.         ifFalse: [^subclasses copy]!
  2221. superclass
  2222.     "Answer the receiver's superclass, a Class."
  2223.  
  2224.     ^superclass!
  2225. withAllSubclasses
  2226.     "Answer a Set of the receiver, the receiver's descendent's, and the 
  2227.     receiver's descendent's subclasses."
  2228.  
  2229.     | aSet |
  2230.     aSet _ Set with: self.
  2231.     aSet addAll: self subclasses.
  2232.     self subclasses do: [:eachSubclass | aSet addAll: eachSubclass allSubclasses].
  2233.     ^aSet!
  2234. withAllSuperclasses
  2235.     "Answer an OrderedCollection of the receiver and the receiver's 
  2236.     superclasses. The first element is the receiver, 
  2237.     followed by its superclass; the last element is Object."
  2238.  
  2239.     | temp |
  2240.     temp _ self allSuperclasses.
  2241.     temp addFirst: self.
  2242.     ^ temp! !
  2243.  
  2244. !Behavior methodsFor: 'accessing method dictionary'!
  2245. allSelectors
  2246.     "Answer a Set of all the message selectors that instances of the receiver 
  2247.     can understand."
  2248.  
  2249.     | temp |
  2250.     superclass == nil
  2251.         ifTrue: [^self selectors]
  2252.         ifFalse: [temp _ superclass allSelectors.
  2253.                 temp addAll: self selectors.
  2254.                 ^temp]
  2255.  
  2256.     "Point allSelectors"!
  2257. changeRecordsAt: selector
  2258.     "Return a list of ChangeRecords for all versions of the method at selector.
  2259.     Source code can be retrieved by sending string to any one"
  2260.     "(Pen changeRecordsAt: #go:) collect: [:cRec | cRec string]"
  2261.     ^ (ChangeList new
  2262.             scanVersionsOf: (self compiledMethodAt: selector)
  2263.             class: self meta: self isMeta
  2264.             category: (self whichCategoryIncludesSelector: selector)
  2265.             selector: selector)
  2266.         changeList!
  2267. compiledMethodAt: selector 
  2268.     "Answer the compiled method associated with the argument, selector (a 
  2269.     Symbol), a message selector in the receiver's method dictionary. If the 
  2270.     selector is not in the dictionary, create an error notification."
  2271.  
  2272.     ^methodDict at: selector!
  2273. compressedSourceCodeAt: selector
  2274.     "(Paragraph compressedSourceCodeAt: #displayLines:affectedRectangle:) size 721 1921
  2275.     Paragraph selectors inject: 0 into: [:tot :sel | tot + (Paragraph compressedSourceCodeAt: sel) size] 13606 31450"
  2276.     | rawText parse |
  2277.     rawText _ self sourceCodeAt: selector.
  2278.     parse _ self compilerClass new parse: rawText in: self notifying: nil.
  2279.     ^ rawText compressWithTable:
  2280.         ((selector keywords ,
  2281.         parse tempNames ,
  2282.         self instVarNames ,
  2283.         #(self super ifTrue: ifFalse:) ,
  2284.         ((0 to: 7) collect:
  2285.             [:i | String streamContents:
  2286.                 [:s | s cr. i timesRepeat: [s tab]]]) ,
  2287.         (self compiledMethodAt: selector) literalStrings)
  2288.             asSortedCollection: [:a :b | a size > b size])!
  2289. copySourceCodeAt: selector to: aFileStream
  2290.     | code method dict |
  2291.     method _ methodDict at: selector.
  2292.     (Sensor leftShiftDown or: [(method copySourceTo: aFileStream) == false])
  2293.         ifTrue: [aFileStream nextChunkPut: (self decompilerClass new
  2294.                     decompile: selector
  2295.                     in: self
  2296.                     method: method) decompileString]
  2297. !
  2298. firstCommentAt:  selector
  2299.     "Answer a string representing the first comment in the method associated with selector.  Return an empty string if the relevant source file is not available, or if the method's source code does not contain a comment.  Not smart enough to bypass quotes in string constants, but ""clever"" enough to map doubled quotes into a single quote.  5/1/96 sw"
  2300.     "Behavior firstCommentAt: #firstCommentAt:"
  2301.  
  2302.     | sourceString commentStart  pos nextQuotePos |
  2303.  
  2304.     sourceString _ self sourceCodeAt: selector.
  2305.     sourceString size == 0 ifTrue: [^ ''].
  2306.     commentStart _ sourceString findString: '"' startingAt: 1.
  2307.     commentStart == 0 ifTrue: [^ ''].
  2308.     pos _ commentStart + 1.
  2309.     [(nextQuotePos _ sourceString findString: '"' startingAt: pos) == (sourceString findString: '""' startingAt: pos)]
  2310.         whileTrue:
  2311.             [pos _ nextQuotePos + 2].
  2312.             
  2313.     ^ (sourceString copyFrom: commentStart + 1 to: nextQuotePos - 1) copyReplaceAll: '""' with: '"'!
  2314. selectorAtMethod: method setClass: classResultBlock 
  2315.     "Answer both the message selector associated with the compiled method 
  2316.     and the class in which that selector is defined."
  2317.  
  2318.     | sel |
  2319.     sel _ methodDict keyAtValue: method
  2320.                 ifAbsent: 
  2321.                     [superclass == nil
  2322.                         ifTrue: 
  2323.                             [classResultBlock value: self.
  2324.                             ^self defaultSelectorForMethod: method].
  2325.                     sel _ superclass selectorAtMethod: method setClass: classResultBlock.
  2326.                     "Set class to be self, rather than that returned from 
  2327.                     superclass. "
  2328.                     sel == (self defaultSelectorForMethod: method) ifTrue: [classResultBlock value: self].
  2329.                     ^sel].
  2330.     classResultBlock value: self.
  2331.     ^sel!
  2332. selectors
  2333.     "Answer a Set of all the message selectors specified in the receiver's 
  2334.     method dictionary."
  2335.  
  2336.     ^methodDict keys  
  2337.  
  2338.     "Point selectors."!
  2339. selectorsDo: selectorBlock
  2340.     "Evaluate selectorBlock for all the message selectors in my method dictionary."
  2341.  
  2342.     ^methodDict keysDo: selectorBlock!
  2343. sourceCodeAt: selector
  2344.     | code method dict |
  2345.     method _ methodDict at: selector.
  2346.     Sensor leftShiftDown
  2347.         ifTrue: [code _ (self decompilerClass new
  2348.                         decompile: selector
  2349.                         in: self
  2350.                         method: method) decompileString]
  2351.         ifFalse: 
  2352.             [code _ method getSource.
  2353.             code == nil
  2354.                 ifTrue: 
  2355.                     [code _ (self decompilerClass new
  2356.                                     decompile: selector
  2357.                                     in: self
  2358.                                     method: method) decompileString]].
  2359.     ^code!
  2360. sourceMethodAt: selector 
  2361.     "Answer the paragraph corresponding to the source code for the 
  2362.     argument."
  2363.  
  2364.     ^(self sourceCodeAt: selector) asText makeSelectorBoldIn: self! !
  2365.  
  2366. !Behavior methodsFor: 'accessing instances and variables'!
  2367. allClassVarNames
  2368.     "Answer a Set of the names of the receiver's and the receiver's ancestor's 
  2369.     class variables."
  2370.  
  2371.     ^superclass allClassVarNames!
  2372. allInstances 
  2373.     "Answer a Set of all current instances of the receiver."
  2374.  
  2375.     | aCollection |
  2376.     aCollection _ OrderedCollection new.
  2377.     self allInstancesDo:
  2378.         [:x | x == aCollection ifFalse: [aCollection add: x]].
  2379.     ^aCollection!
  2380. allInstVarNames
  2381.     "Answer an Array of the names of the receiver's instance variables. The 
  2382.     Array ordering is the order in which the variables are stored and 
  2383.     accessed by the interpreter."
  2384.  
  2385.     | vars |
  2386.     superclass == nil
  2387.         ifTrue: [vars _ self instVarNames copy]    "Guarantee a copy is answered."
  2388.         ifFalse: [vars _ superclass allInstVarNames , self instVarNames].
  2389.     ^vars!
  2390. allSharedPools
  2391.     "Answer a Set of the names of the pools (Dictionaries) that the receiver 
  2392.     and the receiver's ancestors share."
  2393.  
  2394.     ^superclass allSharedPools!
  2395. allSubInstances 
  2396.     "Answer a list of all current instances of the receiver and all of its subclasses.  1/26/96 sw."
  2397.  
  2398.     | aCollection |
  2399.     aCollection _ self allInstances.
  2400.     self allSubInstancesDo:
  2401.         [:x | x == aCollection ifFalse: [aCollection add: x]].
  2402.     ^ aCollection!
  2403. classVarNames
  2404.     "Answer a Set of the receiver's class variable names."
  2405.  
  2406.     ^Set new!
  2407. inspectAllInstances 
  2408.     "Inpsect all instances of the receiver.  1/26/96 sw"
  2409.  
  2410.     | all allSize prefix |
  2411.     all _ self allInstances.
  2412.     (allSize _ all size) == 0 ifTrue: [^ self notify: 'There are no 
  2413. instances of ', self name].
  2414.     prefix _ allSize == 1
  2415.         ifTrue:     ['The lone instance']
  2416.         ifFalse:    ['The ', allSize printString, ' instances'].
  2417.     
  2418.     all asArray inspectWithLabel: (prefix, ' of ', self name)!
  2419. inspectSubInstances 
  2420.     "Inspect all instances of the receiver and all its subclasses.  CAUTION - don't do this for something as generic as Object!!  1/26/96 sw"
  2421.  
  2422.     | all allSize prefix |
  2423.     all _ self allSubInstances.
  2424.     (allSize _ all size) == 0 ifTrue: [^ self notify: 'There are no 
  2425. instances of ', self name, '
  2426. or any of its subclasses'].
  2427.     prefix _ allSize == 1
  2428.         ifTrue:     ['The lone instance']
  2429.         ifFalse:    ['The ', allSize printString, ' instances'].
  2430.     
  2431.     all asArray inspectWithLabel: (prefix, ' of ', self name, ' & its subclasses')!
  2432. instanceCount
  2433.     "Answer the number of instances of the receiver that are currently in 
  2434.     use."
  2435.  
  2436.     | count |
  2437.     count _ 0.
  2438.     self allInstancesDo: [:x | count _ count + 1].
  2439.     ^count!
  2440. instVarNames
  2441.     "Answer an Array of the instance variable names. Behaviors must make 
  2442.     up fake local instance variable names because Behaviors have instance 
  2443.     variables for the purpose of compiling methods, but these are not named 
  2444.     instance variables."
  2445.  
  2446.     | mySize superSize |
  2447.     mySize _ self instSize.
  2448.     superSize _ 
  2449.         superclass == nil
  2450.             ifTrue: [0]
  2451.             ifFalse: [superclass instSize].
  2452.     mySize = superSize ifTrue: [^#()].    
  2453.     ^(superSize + 1 to: mySize) collect: [:i | 'inst' , i printString]!
  2454. sharedPools
  2455.     "Answer a Set of the names of the pools (Dictionaries) that the receiver 
  2456.     shares.
  2457.     9/12/96 tk  sharedPools have an order now"
  2458.  
  2459.     ^ OrderedCollection new!
  2460. someInstance
  2461.     "Primitive. Answer the first instance in the enumeration of all instances 
  2462.     of the receiver. Fails if there are none. Essential. See Object 
  2463.     documentation whatIsAPrimitive."
  2464.  
  2465.     <primitive: 77>
  2466.     ^nil!
  2467. subclassInstVarNames
  2468.     "Answer a Set of the names of the receiver's subclasses' instance 
  2469.     variables."
  2470.     | vars |
  2471.     vars _ Set new.
  2472.     self allSubclasses do: [:aSubclass | vars addAll: aSubclass instVarNames].
  2473.     ^vars! !
  2474.  
  2475. !Behavior methodsFor: 'testing class hierarchy'!
  2476. inheritsFrom: aClass 
  2477.     "Answer whether the argument, aClass, is on the receiver's superclass 
  2478.     chain."
  2479.  
  2480.     | aSuperclass |
  2481.     aSuperclass _ superclass.
  2482.     [aSuperclass == nil]
  2483.         whileFalse: 
  2484.             [aSuperclass == aClass ifTrue: [^true].
  2485.             aSuperclass _ aSuperclass superclass].
  2486.     ^false!
  2487. kindOfSubclass 
  2488.     "Answer a String that is the keyword that describes the receiver's kind of 
  2489.     subclass, either a regular subclass, a variableSubclass, a 
  2490.     variableByteSubclass, or a variableWordSubclass."
  2491.  
  2492.     self isVariable
  2493.         ifTrue: [self isBits
  2494.                     ifTrue: [self isBytes
  2495.                                 ifTrue: [^' variableByteSubclass: ']
  2496.                                 ifFalse: [^' variableWordSubclass: ']]
  2497.                     ifFalse: [^' variableSubclass: ']]
  2498.         ifFalse: [^' subclass: ']! !
  2499.  
  2500. !Behavior methodsFor: 'testing method dictionary'!
  2501. allUnsentMessages
  2502.     "Answer an array of all the messages defined by the receiver that are not sent anywhere in the system.  5/8/96 sw"
  2503.  
  2504.     ^ Smalltalk allUnSentMessagesIn: self selectors!
  2505. canUnderstand: selector 
  2506.     "Answer whether the receiver can respond to the message whose selector 
  2507.     is the argument. The selector can be in the method dictionary of the 
  2508.     receiver's class or any of its superclasses."
  2509.  
  2510.     (self includesSelector: selector) ifTrue: [^true].
  2511.     superclass == nil ifTrue: [^false].
  2512.     ^superclass canUnderstand: selector!
  2513. hasMethods
  2514.     "Answer whether the receiver has any methods in its method dictionary."
  2515.  
  2516.     ^methodDict size > 0!
  2517. includesSelector: aSymbol 
  2518.     "Answer whether the message whose selector is the argument is in the 
  2519.     method dictionary of the receiver's class."
  2520.  
  2521.     ^methodDict includesKey: aSymbol!
  2522. scopeHas: name ifTrue: assocBlock 
  2523.     "If the argument name is a variable known to the receiver, then evaluate 
  2524.     the second argument, assocBlock."
  2525.  
  2526.     ^superclass scopeHas: name ifTrue: assocBlock!
  2527. whichClassIncludesSelector: aSymbol 
  2528.     "Answer the class on the receiver's superclass chain where the argument, 
  2529.     aSymbol (a message selector), will be found. Answer nil if none found."
  2530.  
  2531.     (methodDict includesKey: aSymbol) ifTrue: [^self].
  2532.     superclass == nil ifTrue: [^nil].
  2533.     ^superclass whichClassIncludesSelector: aSymbol
  2534.  
  2535.     "Rectangle whichClassIncludesSelector: #inspect."!
  2536. whichSelectorsAccess: instVarName 
  2537.     "Answer a Set of selectors whose methods access the argument, 
  2538.     instVarName, as a named instance variable."
  2539.  
  2540.     | instVarIndex |
  2541.     instVarIndex _ self allInstVarNames indexOf: instVarName ifAbsent: [^Set new].
  2542.     ^methodDict keys select: 
  2543.         [:sel | 
  2544.         ((methodDict at: sel)
  2545.             readsField: instVarIndex)
  2546.             or: [(methodDict at: sel) writesField: instVarIndex]]
  2547.  
  2548.     "Point whichSelectorsAccess: 'x'."!
  2549. whichSelectorsReferTo: literal 
  2550.     "Answer a Set of selectors whose methods access the argument as a literal."
  2551.  
  2552.     | special |
  2553.     special _ Smalltalk hasSpecialSelector: literal ifTrueSetByte: [:byte ].
  2554.     ^self whichSelectorsReferTo: literal special: special byte: byte
  2555.  
  2556.     "Rectangle whichSelectorsReferTo: #+."!
  2557. whichSelectorsReferTo: literal special: specialFlag byte: specialByte
  2558.     "Answer a set of selectors whose methods access the argument as a literal."
  2559.     | who method methodArray |
  2560.     who _ Set new.
  2561.     methodDict associationsDo:
  2562.         [:assn |
  2563.         method _ assn value.
  2564.         ((method pointsTo: literal "faster than hasLiteral:") or:
  2565.                 [specialFlag and: [method scanFor: specialByte]])
  2566.             ifTrue:
  2567.             [((literal isKindOf: Association) not
  2568.                 or: [method sendsToSuper not
  2569.                     or: [(method literals copyFrom: 1
  2570.                         to: method numLiterals-1)
  2571.                             includes: literal]])
  2572.                 ifTrue: [who add: assn key]]].
  2573.     ^who!
  2574. whichSelectorsStoreInto: instVarName 
  2575.     "Answer a Set of selectors whose methods access the argument, 
  2576.     instVarName, as a named instance variable."
  2577.     | instVarIndex |
  2578.     instVarIndex _ self allInstVarNames indexOf: instVarName ifAbsent: [^Set new].
  2579.     ^ methodDict keys select: 
  2580.         [:sel | (methodDict at: sel) writesField: instVarIndex]
  2581.  
  2582.     "Point whichSelectorsStoreInto: 'x'."! !
  2583.  
  2584. !Behavior methodsFor: 'enumerating'!
  2585. allInstancesDo: aBlock 
  2586.     "Evaluate the argument, aBlock, for each of the current instances of the 
  2587.     receiver."
  2588.     | inst next |
  2589.     self ==  UndefinedObject ifTrue: [^ aBlock value: nil].
  2590.     inst _ self someInstance.
  2591.     [inst == nil]
  2592.         whileFalse:
  2593.         [aBlock value: inst.
  2594.         inst _ inst nextInstance]!
  2595. allSubclassesDo: aBlock 
  2596.     "Evaluate the argument, aBlock, for each of the receiver's subclasses."
  2597.  
  2598.     self subclassesDo: 
  2599.         [:cl | 
  2600.         aBlock value: cl.
  2601.         cl allSubclassesDo: aBlock]!
  2602. allSubInstancesDo: aBlock 
  2603.     "Evaluate the argument, aBlock, for each of the current instances of the 
  2604.     receiver's subclasses."
  2605.  
  2606.     self allSubclassesDo: [:sub | sub allInstancesDo: aBlock]!
  2607. allSuperclassesDo: aBlock 
  2608.     "Evaluate the argument, aBlock, for each of the receiver's superclasses."
  2609.  
  2610.     superclass == nil
  2611.         ifFalse: [aBlock value: superclass.
  2612.                 superclass allSuperclassesDo: aBlock]!
  2613. selectSubclasses: aBlock 
  2614.     "Evaluate the argument, aBlock, with each of the receiver's (next level) 
  2615.     subclasses as its argument. Collect into a Set only those subclasses for 
  2616.     which aBlock evaluates to true. In addition, evaluate aBlock for the 
  2617.     subclasses of each of these successful subclasses and collect into the set 
  2618.     those for which aBlock evaluates true. Answer the resulting set."
  2619.  
  2620.     | aSet |
  2621.     aSet _ Set new.
  2622.     self allSubclasses do: 
  2623.         [:aSubclass | 
  2624.         (aBlock value: aSubclass) ifTrue: [aSet add: aSubclass]].
  2625.     ^aSet!
  2626. selectSuperclasses: aBlock 
  2627.     "Evaluate the argument, aBlock, with the receiver's superclasses as the 
  2628.     argument. Collect into an OrderedCollection only those superclasses for 
  2629.     which aBlock evaluates to true. In addition, evaluate aBlock for the 
  2630.     superclasses of each of these successful superclasses and collect into the 
  2631.     OrderedCollection ones for which aBlock evaluates to true. Answer the 
  2632.     resulting OrderedCollection."
  2633.  
  2634.     | aSet |
  2635.     aSet _ Set new.
  2636.     self allSuperclasses do: 
  2637.         [:aSuperclass | 
  2638.         (aBlock value: aSuperclass) ifTrue: [aSet add: aSuperclass]].
  2639.     ^aSet!
  2640. subclassesDo: aBlock 
  2641.     "Evaluate the argument, aBlock, for each of the receiver's immediate subclasses."
  2642.     subclasses == nil ifFalse:
  2643.         [subclasses do: [:cl | aBlock value: cl]]!
  2644. withAllSubclassesDo: aBlock 
  2645.     "Evaluate the argument, aBlock, for the receiver and each of its 
  2646.     subclasses."
  2647.  
  2648.     aBlock value: self.
  2649.     self allSubclassesDo: aBlock! !
  2650.  
  2651. !Behavior methodsFor: 'user interface'!
  2652. allCallsOn: aSymbol
  2653.     "Answer a SortedCollection of all the methods that call on aSymbol."
  2654.  
  2655.     | aSortedCollection special |
  2656.     aSortedCollection _ SortedCollection new.
  2657.     special _ Smalltalk hasSpecialSelector: aSymbol ifTrueSetByte: [:byte ].
  2658.     self withAllSubclassesDo:
  2659.         [:class | (class whichSelectorsReferTo: aSymbol special: special byte: byte) do:
  2660.             [:sel | sel ~~ #DoIt ifTrue: [aSortedCollection add: class name , ' ' , sel]]].
  2661.     ^aSortedCollection!
  2662. browseAllAccessesTo: instVarName     "Collection browseAllAccessesTo: 'contents'."
  2663.     "Create and schedule a Message Set browser for all the receiver's methods 
  2664.     or any methods of a subclass that refer to the instance variable name."
  2665.     | coll |
  2666.     coll _ OrderedCollection new.
  2667.     Cursor wait 
  2668.         showWhile: 
  2669.             [self withAllSubclasses do:
  2670.                 [:class | 
  2671.                 (class whichSelectorsAccess: instVarName) do: 
  2672.                     [:sel | sel ~~ #DoIt ifTrue: [coll add: class name , ' ' , sel]]].
  2673.             self allSuperclasses do:
  2674.                 [:class | 
  2675.                 (class whichSelectorsAccess: instVarName) do: 
  2676.                     [:sel | sel ~~ #DoIt ifTrue: [coll add: class name , ' ' , sel]]]].
  2677.     ^ Smalltalk browseMessageList: coll name: 'Accesses to ' , instVarName autoSelect: instVarName!
  2678. browseAllCallsOn: aSymbol 
  2679.     "Create and schedule a Message Set browser for all the methods that call 
  2680.     on aSymbol."
  2681.     | key label |
  2682.     (aSymbol isKindOf: LookupKey)
  2683.             ifTrue: [label _ 'Users of ' , (key _ aSymbol key)]
  2684.             ifFalse: [label _ 'Senders of ' , (key _ aSymbol)].
  2685.     ^ Smalltalk browseMessageList: (self allCallsOn: aSymbol) asSortedCollection
  2686.         name: label autoSelect: key
  2687.  
  2688.     "Number browseAllCallsOn: #/."!
  2689. browseAllStoresInto: instVarName     "Collection browseAllStoresInto: 'contents'."
  2690.     "Create and schedule a Message Set browser for all the receiver's methods 
  2691.     or any methods of a subclass that refer to the instance variable name."
  2692.     | coll |
  2693.     coll _ OrderedCollection new.
  2694.     Cursor wait 
  2695.         showWhile: 
  2696.             [self withAllSubclasses do:
  2697.                 [:class | 
  2698.                 (class whichSelectorsStoreInto: instVarName) do: 
  2699.                     [:sel | sel ~~ #DoIt ifTrue: [coll add: class name , ' ' , sel]]].
  2700.             self allSuperclasses do:
  2701.                 [:class | 
  2702.                 (class whichSelectorsStoreInto: instVarName) do: 
  2703.                     [:sel | sel ~~ #DoIt ifTrue: [coll add: class name , ' ' , sel]]]].
  2704.     ^ Smalltalk browseMessageList: coll name: 'Stores into ' , instVarName autoSelect: instVarName!
  2705. crossReference
  2706.     "Answer an Array of arrays of size 2 whose first element is a message selector in the receiver's method dictionary and whose second element is a set of all message selectors in the method dictionary whose methods send a message with that selector. Subclasses are not included."
  2707.  
  2708.     ^self selectors asSortedCollection asArray collect: [:x |         Array 
  2709.             with: (String with: Character cr), x 
  2710.             with: (self whichSelectorsReferTo: x)]
  2711.  
  2712.     "Point crossReference."!
  2713. unreferencedInstanceVariables
  2714.     "Return a list of the instance variables defined in the receiver which are not referenced in the receiver or any of its subclasses.  2/26/96 sw"
  2715.  
  2716.     | any |
  2717.  
  2718.     ^ self instVarNames copy reject:
  2719.         [:ivn | any _ false.
  2720.         self withAllSubclasses do:
  2721.             [:class |  (class whichSelectorsAccess: ivn) do: 
  2722.                     [:sel | sel ~~ #DoIt ifTrue: [any _ true]]].
  2723.         any]
  2724.  
  2725. "Ob unreferencedInstanceVariables"! !
  2726.  
  2727. !Behavior methodsFor: 'fileIn/Out'!
  2728. printMethodChunk: selector on: aFileStream moveSource: moveSource toFile: fileIndex
  2729.     "Print the source code for the method associated with the argument 
  2730.     selector onto the fileStream. aFileStream, and, for backup, if the 
  2731.     argument moveSource (a Boolean) is true, also set the file index within 
  2732.     the method to be the argument fileIndex."
  2733.  
  2734.     | position |
  2735.     aFileStream cr; cr.
  2736.     moveSource ifTrue: [position _ aFileStream position].
  2737.     self copySourceCodeAt: selector to: aFileStream.
  2738.     moveSource 
  2739.         ifTrue: [(self compiledMethodAt: selector)
  2740.                     setSourcePosition: position inFile: fileIndex]! !
  2741.  
  2742. !Behavior methodsFor: 'private'!
  2743. becomeCompact
  2744.     | cct index |
  2745.     cct _ Smalltalk compactClassesArray.
  2746.     (self indexIfCompact > 0 or: [cct includes: self])
  2747.         ifTrue: [^ self halt: self name , 'is already compact'].
  2748.     index _ cct indexOf: nil
  2749.         ifAbsent: [^ self halt: 'compact class table is full'].
  2750.     "Install this class in the compact class table"
  2751.     cct at: index put: self.
  2752.     "Update instspec so future instances will be compact"
  2753.     format _ format + (index bitShift: 11).
  2754.     "Make up new instances and become old ones into them"
  2755.     self updateInstancesFrom: self.
  2756.     "Purge any old instances"
  2757.     Smalltalk garbageCollect.!
  2758. becomeUncompact
  2759.     | cct index |
  2760.     cct _ Smalltalk compactClassesArray.
  2761.     (index _ self indexIfCompact) = 0
  2762.         ifTrue: [^ self].
  2763.     (cct includes: self)
  2764.         ifFalse: [^ self halt  "inconsistent state"].
  2765.     "Update instspec so future instances will not be compact"
  2766.     format _ format - (index bitShift: 11).
  2767.     "Make up new instances and become old ones into them"
  2768.     self updateInstancesFrom: self.
  2769.     "Make sure there are no compact ones left around"
  2770.     Smalltalk garbageCollect.
  2771.     "Remove this class from the compact class table"
  2772.     cct at: index put: nil.
  2773. !
  2774. flushCache
  2775.     "Tell the interpreter to remove the contents of its method lookup cache, if it has 
  2776.     one.  Essential.  See Object documentation whatIsAPrimitive."
  2777.  
  2778.     <primitive: 89>
  2779.     self primitiveFailed!
  2780. format: nInstVars variable: isVar words: isWords pointers: isPointers 
  2781.     "Set the format for the receiver (a Class)."
  2782.     | cClass instSpec |
  2783.     "<5 bits=cClass><4 bits=instSpec><6 bits=instSize> all shifted left 1"
  2784.     cClass _ 0.  "for now"
  2785.     instSpec _ isPointers
  2786.         ifTrue: [isVar
  2787.                 ifTrue: [nInstVars>0 ifTrue: [3] ifFalse: [2]]
  2788.                 ifFalse: [nInstVars>0 ifTrue: [1] ifFalse: [0]]]
  2789.         ifFalse: [isWords ifTrue: [6] ifFalse: [8]].
  2790.     format _ cClass.
  2791.     format _ (format bitShift: 4) + instSpec.
  2792.     format _ (format bitShift: 6) + nInstVars+1.
  2793.     format _ (format bitShift: 1)!
  2794. indexIfCompact
  2795.     "If these 5 bits are non-zero, then instances of this class
  2796.     will be compact.  It is crucial that there be an entry in
  2797.     Smalltalk compactClassesArray for any class so optimized.
  2798.     See the msgs becomeCompact and becomeUncompact."
  2799.     ^ (format bitShift: -11) bitAnd: 16r1F
  2800. "
  2801. Smalltalk compactClassesArray doWithIndex: 
  2802.     [:c :i | c == nil ifFalse:
  2803.         [c indexIfCompact = i ifFalse: [self halt]]]
  2804. "!
  2805. printSubclassesOn: aStream level: level 
  2806.     "As part of the algorithm for printing a description of the receiver, print the
  2807.     subclass on the file stream, aStream, indenting level times."
  2808.  
  2809.     | subclassNames subclass |
  2810.     aStream crtab: level.
  2811.     aStream nextPutAll: self name.
  2812.     aStream space; print: self instVarNames.
  2813.     self == Class
  2814.         ifTrue: 
  2815.             [aStream crtab: level + 1; nextPutAll: '[ ... all the Metaclasses ... ]'.
  2816.             ^self].
  2817.     subclassNames _ self subclasses collect: [:subC | subC name].
  2818.     "Print subclasses in alphabetical order"
  2819.     subclassNames asSortedCollection do:
  2820.         [:name |
  2821.         subclass _ self subclasses detect: [:subC | subC name = name].
  2822.         subclass printSubclassesOn: aStream level: level + 1]!
  2823. removeSelectorSimply: selector 
  2824.     "Remove the message selector from the receiver's method dictionary.
  2825.     Internal access from compiler."
  2826.  
  2827.     methodDict removeKey: selector ifAbsent: [^self].
  2828.     self flushCache!
  2829. sourceTextAt: selector 
  2830.     ^(self sourceCodeAt: selector) asText! !Object subclass: #BitBlt
  2831.     instanceVariableNames: 'destForm sourceForm halftoneForm combinationRule destX destY width height sourceX sourceY clipX clipY clipWidth clipHeight colorMap '
  2832.     classVariableNames: ''
  2833.     poolDictionaries: ''
  2834.     category: 'Graphics-Support'!
  2835. BitBlt comment:
  2836. 'I represent a block transfer (BLT) of pixels into a rectangle (destX, destY, width, height) of the destinationForm.  The source of pixels may be a similar rectangle (at sourceX, sourceY) in the sourceForm, or a constant color, currently called halftoneForm.  If both are specified, their pixel values are combined with a logical AND function prior to transfer.  In any case, the pixels from the source are combined with those of the destination by as specified by the combinationRule.
  2837.  
  2838. The combination rule whose value is 0 through 15 programs the transfer to produce 1 or 0 according to its 4-bit representation as follows:
  2839.     8:    if source is 0 and destination is 0
  2840.     4:    if source is 0 and destination is 1
  2841.     2:    if source is 1 and destination is 0
  2842.     1:    if source is 1 and destination is 1.
  2843. At each pixel the corresponding bits of the source and destination pixel values determine one of these conditions;  if the combination rule has a 1 in the corresponding bit position, then the new destination value will be 1, otherwise it will be zero.
  2844.     Combination rule 16 is "paint bits".  It uses the 1-bit deep sourceForm to cut a hole in the destination.  Then it ORs in the sourceForm using the fillColor.
  2845.     Combination rule 17 is "erase bits".  The source Form must be 1 bit deep.  It is used to cut a hole (put in zeros) in the destination Form.
  2846.     Forms may be of different depths, see comment in class Form.
  2847.  
  2848. The color specified by halftoneForm may be either a Color or a Pattern.   A Color is converted to a pixelValue for the depth of the destinationForm.  If a Pattern, BitBlt will simply interpret its bitmap as an array of Color pixelValues.  BitBlt aligns the first element of this array with the top scanline of the destinationForm, the second with the second, and so on, cycling through the color array as necessary.  Within each scan line the 32-bit value is repeated from left to right across the form.  If the value repeats on pixels boudaries, the effect will be a constant color;  if not, it will produce a halftone that repeats on 32-bit boundaries.
  2849.  
  2850. Any transfer specified is further clipped by the specified rectangle (clipX, clipY, clipWidth, clipHeight), and also by the bounds of the source and destination forms.
  2851.     To make a small Form repeat and fill a big form, use an InfiniteForm as the source.
  2852.     To write on a form and leave with both transparent and opapue areas, use a MaskedForm as the source.
  2853.  
  2854. Pixels from a source to a destination whose pixels have a different depth are converted based on the optional colorMap.  If colorMap is nil, then conversion to more bits is done by filling the new high-order bits with zero, and conversion to fewer bits is done by truncating the lost high-order bits.  The colorMap, if specified, must be a word array (ie Bitmap) with 2^n elements, where n is the pixel depth of the source.  For every source pixel, BitBlt will then index this array, and select the corresponding pixelValue and mask it to the destination pixel size before storing.
  2855.     When blitting from a 32 or 16 bit deep Form to one 8 bits or less, the default is truncation.  This will produce very strange colors, since truncation of the high bits does not produce the nearest encoded color.  Supply a 512 long colorMap, and red, green, and blue will be shifted down to 3 bits each, and mapped.  The message copybits...stdColors will use the best map to the standard colors for destinations of depths 8, 4, 2 and 1.
  2856.     Colors can be remapped at the same depth.  Sometimes a Form is in terms of colors that are not the standard colors for this depth, for example in a GIF file.  Convert the Form to a MaskedForm and send colorMap: the list of colors that the picture is in terms of.  MaskedForm will use the colorMap when copying to the display or another Form. (Note also that a Form can be copied to itself, and transformed in the process, if a non-nil colorMap is supplied.)'!
  2857.  
  2858. !BitBlt methodsFor: 'accessing'!
  2859. clipHeight: anInteger 
  2860.     "Set the receiver's clipping area height to be the argument, anInteger."
  2861.  
  2862.     clipHeight _ anInteger!
  2863. clipRect
  2864.     "Answer the receiver's clipping area rectangle."
  2865.  
  2866.     ^clipX @ clipY extent: clipWidth @ clipHeight!
  2867. clipRect: aRectangle 
  2868.     "Set the receiver's clipping area rectangle to be the argument, aRectangle."
  2869.  
  2870.     clipX _ aRectangle left.
  2871.     clipY _ aRectangle top.
  2872.     clipWidth _ aRectangle width.
  2873.     clipHeight _ aRectangle height!
  2874. clipWidth: anInteger 
  2875.     "Set the receiver's clipping area width to be the argument, anInteger."
  2876.  
  2877.     clipWidth _ anInteger!
  2878. clipX: anInteger 
  2879.     "Set the receiver's clipping area top left x coordinate to be the argument, 
  2880.     anInteger."
  2881.  
  2882.     clipX _ anInteger!
  2883. clipY: anInteger 
  2884.     "Set the receiver's clipping area top left y coordinate to be the argument, 
  2885.     anInteger."
  2886.  
  2887.     clipY _ anInteger!
  2888. colorMap: map
  2889.     "See last part of BitBlt comment. 6/18/96 tk"
  2890.     colorMap _ map!
  2891. combinationRule: anInteger 
  2892.     "Set the receiver's combination rule to be the argument, anInteger, a 
  2893.     number in the range 0-15."
  2894.  
  2895.     combinationRule _ anInteger!
  2896. destForm
  2897.     ^ destForm!
  2898. destOrigin: aPoint 
  2899.     "Set the receiver's destination top left coordinates to be those of the 
  2900.     argument, aPoint."
  2901.  
  2902.     destX _ aPoint x.
  2903.     destY _ aPoint y!
  2904. destRect: aRectangle 
  2905.     "Set the receiver's destination form top left coordinates to be the origin of 
  2906.     the argument, aRectangle, and set the width and height of the receiver's 
  2907.     destination form to be the width and height of aRectangle."
  2908.  
  2909.     destX _ aRectangle left.
  2910.     destY _ aRectangle top.
  2911.     width _ aRectangle width.
  2912.     height _ aRectangle height!
  2913. destX: anInteger 
  2914.     "Set the top left x coordinate of the receiver's destination form to be the 
  2915.     argument, anInteger."
  2916.  
  2917.     destX _ anInteger!
  2918. destY: anInteger 
  2919.     "Set the top left y coordinate of the receiver's destination form to be the 
  2920.     argument, anInteger."
  2921.  
  2922.     destY _ anInteger!
  2923. fillColor: aColorOrPattern 
  2924.     "The destForm will be filled with this color or pattern of colors.  May be an old Color, a new type Color, a Bitmap (see BitBlt comment), a Pattern, or a Form.  6/18/96 tk"
  2925.  
  2926.     aColorOrPattern == nil ifTrue: [halftoneForm _ nil. ^ self].
  2927.     destForm == nil ifTrue: [self error: 'Must set destForm first'].
  2928.     halftoneForm _ aColorOrPattern bitPatternForDepth: destForm depth!
  2929. height: anInteger 
  2930.     "Set the receiver's destination form height to be the argument, anInteger."
  2931.  
  2932.     height _ anInteger!
  2933. sourceForm: aForm 
  2934.     "Set the receiver's source form to be the argument, aForm."
  2935.  
  2936.     sourceForm _ aForm!
  2937. sourceOrigin: aPoint 
  2938.     "Set the receiver's source form coordinates to be those of the argument, 
  2939.     aPoint."
  2940.  
  2941.     sourceX _ aPoint x.
  2942.     sourceY _ aPoint y!
  2943. sourceRect: aRectangle 
  2944.     "Set the receiver's source form top left x and y, width and height to be 
  2945.     the top left coordinate and extent of the argument, aRectangle."
  2946.  
  2947.     sourceX _ aRectangle left.
  2948.     sourceY _ aRectangle top.
  2949.     width _ aRectangle width.
  2950.     height _ aRectangle height!
  2951. sourceX: anInteger 
  2952.     "Set the receiver's source form top left x to be the argument, anInteger."
  2953.  
  2954.     sourceX _ anInteger!
  2955. sourceY: anInteger 
  2956.     "Set the receiver's source form top left y to be the argument, anInteger."
  2957.  
  2958.     sourceY _ anInteger!
  2959. width: anInteger 
  2960.     "Set the receiver's destination form width to be the argument, anInteger."
  2961.  
  2962.     width _ anInteger! !
  2963.  
  2964. !BitBlt methodsFor: 'copying'!
  2965. copy: destRectangle from: sourcePt in: srcForm
  2966.     | destOrigin |
  2967.     sourceForm _ srcForm.
  2968.     halftoneForm _ nil.
  2969.     combinationRule _ 3.  "store"
  2970.     destOrigin _ destRectangle origin.
  2971.     destX _ destOrigin x.
  2972.     destY _ destOrigin y.
  2973.     sourceX _ sourcePt x.
  2974.     sourceY _ sourcePt y.
  2975.     width _ destRectangle width.
  2976.     height _ destRectangle height.
  2977.     self copyBits!
  2978. copy: destRectangle from: sourcePt in: srcForm fillColor: hf rule: rule
  2979.     "Specify a Color to fill, not a Form. 6/18/96 tk"  
  2980.     | destOrigin |
  2981.     sourceForm _ srcForm.
  2982.     self fillColor: hf.    "sets halftoneForm"
  2983.     combinationRule _ rule.
  2984.     destOrigin _ destRectangle origin.
  2985.     destX _ destOrigin x.
  2986.     destY _ destOrigin y.
  2987.     sourceX _ sourcePt x.
  2988.     sourceY _ sourcePt y.
  2989.     width _ destRectangle width.
  2990.     height _ destRectangle height.
  2991.     ^ self copyBits!
  2992. copy: destRectangle from: sourcePt in: srcForm halftoneForm: hf rule: rule 
  2993.     | destOrigin |
  2994.     sourceForm _ srcForm.
  2995.     self fillColor: hf.        "sets halftoneForm"
  2996.     combinationRule _ rule.
  2997.     destOrigin _ destRectangle origin.
  2998.     destX _ destOrigin x.
  2999.     destY _ destOrigin y.
  3000.     sourceX _ sourcePt x.
  3001.     sourceY _ sourcePt y.
  3002.     width _ destRectangle width.
  3003.     height _ destRectangle height.
  3004.     self copyBits!
  3005. copyBits
  3006.     "Primitive. Perform the movement of bits from the source form to the 
  3007.     destination form. Fail if any variables are not of the right type (Integer 
  3008.     or Form) or if the combination rule is not between 0 and 15 inclusive. 
  3009.     Set the variables and try again (BitBlt|copyBitsAgain, also a Primitive). 
  3010.     Essential. See Object documentation whatIsAPrimitive."
  3011.     <primitive: 96>
  3012.     combinationRule = Form paint ifTrue: [^ self paintBits].
  3013.     combinationRule = Form erase1bitShape ifTrue: [^ self eraseBits].
  3014.     destX _ destX asInteger.
  3015.     destY _ destY asInteger.
  3016.     width _ width asInteger.
  3017.     height _ height asInteger.
  3018.     sourceX _ sourceX asInteger.
  3019.     sourceY _ sourceY asInteger.
  3020.     clipX _ clipX asInteger.
  3021.     clipY _ clipY asInteger.
  3022.     clipWidth _ clipWidth asInteger.
  3023.     clipHeight _ clipHeight asInteger.
  3024.     ^ self copyBitsAgain!
  3025. copyForm: srcForm to: destPt rule: rule
  3026.     sourceForm _ srcForm.
  3027.     halftoneForm _ nil.
  3028.     combinationRule _ rule.
  3029.     destX _ destPt x + sourceForm offset x.
  3030.     destY _ destPt y + sourceForm offset y.
  3031.     sourceX _ 0.
  3032.     sourceY _ 0.
  3033.     width _ sourceForm width.
  3034.     height _ sourceForm height.
  3035.     self copyBits!
  3036. copyForm: srcForm to: destPt rule: rule color: color
  3037.     sourceForm _ srcForm.
  3038.     halftoneForm _ color.
  3039.     combinationRule _ rule.
  3040.     destX _ destPt x + sourceForm offset x.
  3041.     destY _ destPt y + sourceForm offset y.
  3042.     sourceX _ 0.
  3043.     sourceY _ 0.
  3044.     width _ sourceForm width.
  3045.     height _ sourceForm height.
  3046.     self copyBits!
  3047. copyForm: srcForm to: destPt rule: rule fillColor: color
  3048.     sourceForm _ srcForm.
  3049.     self fillColor: color.    "sets halftoneForm"
  3050.     combinationRule _ rule.
  3051.     destX _ destPt x + sourceForm offset x.
  3052.     destY _ destPt y + sourceForm offset y.
  3053.     sourceX _ 0.
  3054.     sourceY _ 0.
  3055.     width _ sourceForm width.
  3056.     height _ sourceForm height.
  3057.     self copyBits!
  3058. copyFrom: sourceRectangle in: srcForm to: destPt
  3059.     | sourceOrigin |
  3060.     sourceForm _ srcForm.
  3061.     halftoneForm _ nil.
  3062.     combinationRule _ 3.  "store"
  3063.     destX _ destPt x.
  3064.     destY _ destPt y.
  3065.     sourceOrigin _ sourceRectangle origin.
  3066.     sourceX _ sourceOrigin x.
  3067.     sourceY _ sourceOrigin y.
  3068.     width _ sourceRectangle width.
  3069.     height _ sourceRectangle height.
  3070.     self copyBits!
  3071. fill: destRect fillColor: grayForm rule: rule
  3072.     "Fill with a Color, not a Form. 6/18/96 tk"
  3073.     sourceForm _ nil.
  3074.     self fillColor: grayForm.        "sets halftoneForm"
  3075.     combinationRule _ rule.
  3076.     destX _ destRect left.
  3077.     destY _ destRect top.
  3078.     sourceX _ 0.
  3079.     sourceY _ 0.
  3080.     width _ destRect width.
  3081.     height _ destRect height.
  3082.     self copyBits!
  3083. pixelAt: aPoint
  3084.     "Assumes this BitBlt has been set up specially (see the init message,
  3085.     BitBlt bitPeekerFromForm:.  Returns the pixel at aPoint."
  3086.     sourceX _ aPoint x.
  3087.     sourceY _ aPoint y.
  3088.     destForm bits at: 1 put: 0.  "Just to be sure"
  3089.     self copyBits.
  3090.     ^ destForm bits at: 1!
  3091. pixelAt: aPoint put: pixelValue
  3092.     "Assumes this BitBlt has been set up specially (see the init message,
  3093.     BitBlt bitPokerToForm:.  Overwrites the pixel at aPoint."
  3094.     destX _ aPoint x.
  3095.     destY _ aPoint y.
  3096.     sourceForm bits at: 1 put: pixelValue.
  3097.     self copyBits
  3098. "
  3099. [Sensor anyButtonPressed] whileFalse:
  3100.     [Display valueAt: Sensor cursorPoint put: 55]
  3101. "! !
  3102.  
  3103. !BitBlt methodsFor: 'line drawing'!
  3104. drawFrom: startPoint to: stopPoint 
  3105.     "Draw a line whose end points are startPoint and stopPoint.
  3106.     The line is formed by repeatedly calling copyBits at every
  3107.     point along the line."
  3108.     | offset point1 point2 |
  3109.     "Always draw down, or at least left-to-right"
  3110.     ((startPoint y = stopPoint y and: [startPoint x < stopPoint x])
  3111.         or: [startPoint y < stopPoint y])
  3112.         ifTrue: [point1 _ startPoint. point2 _ stopPoint]
  3113.         ifFalse: [point1 _ stopPoint. point2 _ startPoint].
  3114.     sourceForm == nil ifTrue:
  3115.         [destX _ (point1 x - (width//2)) rounded.
  3116.         destY _ (point1 y - (height//2)) rounded]
  3117.         ifFalse:
  3118.         [width _ sourceForm width.
  3119.         height _ sourceForm height.
  3120.         offset _ sourceForm offset.
  3121.         destX _ (point1 x + offset x) rounded.
  3122.         destY _ (point1 y + offset y) rounded].
  3123.     self drawLoopX: (point2 x - point1 x) rounded 
  3124.                   Y: (point2 y - point1 y) rounded!
  3125. drawLoopX: xDelta Y: yDelta 
  3126.     "Primitive. Implements the Bresenham plotting algorithm (IBM Systems
  3127.     Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and
  3128.     maintains a potential, P. When P's sign changes, it is time to move in the 
  3129.     minor direction as well. Optional. See Object documentation
  3130.     whatIsAPrimitive."
  3131.  
  3132.     | dx dy px py P |
  3133.     <primitive: 104>
  3134.     dx _ xDelta sign.
  3135.     dy _ yDelta sign.
  3136.     px _ yDelta abs.
  3137.     py _ xDelta abs.
  3138.     self copyBits.
  3139.     py > px
  3140.         ifTrue: 
  3141.             ["more horizontal"
  3142.             P _ py // 2.
  3143.             1 to: py do: 
  3144.                 [:i |
  3145.                 destX _ destX + dx.
  3146.                 (P _ P - px) < 0 ifTrue: 
  3147.                         [destY _ destY + dy.
  3148.                         P _ P + py].
  3149.                 self copyBits]]
  3150.         ifFalse: 
  3151.             ["more vertical"
  3152.             P _ px // 2.
  3153.             1 to: px do:
  3154.                 [:i |
  3155.                 destY _ destY + dy.
  3156.                 (P _ P - py) < 0 ifTrue: 
  3157.                         [destX _ destX + dx.
  3158.                         P _ P + px].
  3159.                 self copyBits]]! !
  3160.  
  3161. !BitBlt methodsFor: 'private'!
  3162. copyBitsAgain
  3163.     "Primitive. See BitBlt|copyBits, also a Primitive. Essential. See Object
  3164.     documentation whatIsAPrimitive."
  3165.  
  3166.     <primitive: 96>
  3167.     self primitiveFailed!
  3168. eraseBits
  3169.     "Perform the erase operation, which puts 0's in the destination
  3170.     wherever the source (which is assumed to be just 1 bit deep)
  3171.     has a 1.  This requires the colorMap to be set in order to AND
  3172.     all 1's into the destFrom pixels regardless of their size."
  3173.     | oldMask oldMap |
  3174.     oldMask _ halftoneForm.
  3175.     halftoneForm _ nil.
  3176.     oldMap _ colorMap.
  3177.     self colorMap: (Bitmap with: 0 with: 16rFFFFFFFF).
  3178.     combinationRule _ Form erase.
  3179.     self copyBits.         "Erase the dest wherever the source is 1"
  3180.     halftoneForm _ oldMask.    "already converted to a Bitmap"
  3181.     colorMap _ oldMap!
  3182. paintBits
  3183.     "Perform the paint operation, which requires two calls to BitBlt."
  3184.     | color oldMap saveRule |
  3185.     sourceForm depth = 1 ifFalse: 
  3186.         [^ self halt: 'paint operation is only defined for 1-bit deep sourceForms'].
  3187.     saveRule _ combinationRule.
  3188.     color _ halftoneForm.  halftoneForm _ nil.
  3189.     oldMap _ colorMap.
  3190.     "Map 1's to ALL ones, not just one"
  3191.     self colorMap: (Bitmap with: 0 with: 16rFFFFFFFF).
  3192.     combinationRule _ Form erase.
  3193.     self copyBits.         "Erase the dest wherever the source is 1"
  3194.     halftoneForm _ color.
  3195.     combinationRule _ Form under.
  3196.     self copyBits.    "then OR, with whatever color, into the hole"
  3197.     colorMap _ oldMap.
  3198.     combinationRule _ saveRule
  3199.  
  3200. "(Form dotOfSize: 32)
  3201.     displayOn: Display
  3202.     at: Sensor cursorPoint
  3203.     clippingBox: Display boundingBox
  3204.     rule: Form paint
  3205.     mask: Form lightGray"!
  3206. setDestForm: df
  3207.     | bb |
  3208.     bb _ df boundingBox.
  3209.     destForm _ df.
  3210.     clipX _ bb left.
  3211.     clipY _ bb top.
  3212.     clipWidth _ bb width.
  3213.     clipHeight _ bb height!
  3214. setDestForm: df sourceForm: sf fillColor: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin extent: extent clipRect: clipRect
  3215.  
  3216.     | aPoint |
  3217.     destForm _ df.
  3218.     sourceForm _ sf.
  3219.     self fillColor: hf.    "sets halftoneForm"
  3220.     combinationRule _ cr.
  3221.     destX _ destOrigin x.
  3222.     destY _ destOrigin y.
  3223.     sourceX _ sourceOrigin x.
  3224.     sourceY _ sourceOrigin y.
  3225.     width _ extent x.
  3226.     height _ extent y.
  3227.     aPoint _ clipRect origin.
  3228.     clipX _ aPoint x.
  3229.     clipY _ aPoint y.
  3230.     aPoint _ clipRect corner.
  3231.     clipWidth _ aPoint x - clipX.
  3232.     clipHeight _ aPoint y - clipY.
  3233.     (sourceForm isMemberOf: TwoToneForm)
  3234.         ifTrue: [colorMap _ sourceForm colorMapForDepth: destForm depth]
  3235.         ifFalse: [(destForm depth > 8 and: [sourceForm depth = 1])
  3236.                     ifTrue: [colorMap _ Bitmap with: 16rFFFFFFFF with: 0]]! !
  3237. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3238.  
  3239. BitBlt class
  3240.     instanceVariableNames: ''!
  3241.  
  3242. !BitBlt class methodsFor: 'instance creation'!
  3243. bitPeekerFromForm: sourceForm
  3244.     "Answer an instance to be used for valueAt: aPoint.
  3245.     The destination for a 1x1 copyBits will be the low order of (bits at: 1)"
  3246.     | pixPerWord |
  3247.     pixPerWord _ 32//sourceForm depth.
  3248.     ^ self destForm: (Form extent: pixPerWord@1 depth: sourceForm depth)
  3249.          sourceForm: sourceForm halftoneForm: nil combinationRule: Form over
  3250.         destOrigin: (pixPerWord-1)@0 sourceOrigin: 0@0
  3251.         extent: 1@1 clipRect: (0@0 extent: pixPerWord@1)
  3252. !
  3253. bitPokerToForm: destForm
  3254.     "Answer an instance to be used for valueAt: aPoint put: pixValue.
  3255.     The source for a 1x1 copyBits will be the low order of (bits at: 1)"
  3256.     | pixPerWord |
  3257.     pixPerWord _ 32//destForm depth.
  3258.     ^ self destForm: destForm
  3259.          sourceForm: (Form extent: pixPerWord@1 depth: destForm depth)
  3260.         halftoneForm: nil combinationRule: Form over
  3261.         destOrigin: 0@0 sourceOrigin: (pixPerWord-1)@0
  3262.         extent: 1@1 clipRect: (0@0 extent: destForm extent)
  3263. !
  3264. destForm: df sourceForm: sf fillColor: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin extent: extent clipRect: clipRect 
  3265.     "Answer an instance of me with values set according to the arguments."
  3266.  
  3267.     ^ self new
  3268.         setDestForm: df
  3269.         sourceForm: sf
  3270.         fillColor: hf
  3271.         combinationRule: cr
  3272.         destOrigin: destOrigin
  3273.         sourceOrigin: sourceOrigin
  3274.         extent: extent
  3275.         clipRect: clipRect!
  3276. destForm: df sourceForm: sf halftoneForm: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin extent: extent clipRect: clipRect 
  3277.     "Answer an instance of me with values set according to the arguments."
  3278.  
  3279.     ^ self new
  3280.         setDestForm: df
  3281.         sourceForm: sf
  3282.         fillColor: hf
  3283.         combinationRule: cr
  3284.         destOrigin: destOrigin
  3285.         sourceOrigin: sourceOrigin
  3286.         extent: extent
  3287.         clipRect: clipRect!
  3288. toForm: aForm
  3289.     ^ self new setDestForm: aForm! !
  3290.  
  3291. !BitBlt class methodsFor: 'examples'!
  3292. alphaBlendDemo: sz  "Display restoreAfter: [BitBlt alphaBlendDemo: 30]"
  3293.     "Displays 10 different alphas, and then paints with a gradient brush"
  3294.     | f |  "Get out of painting with option-click"
  3295.     1 to: 10 do: [:i | Display fill: (50*i@10 extent: 50@50)
  3296.                         rule: Form blend
  3297.                         fillColor: (Color red alpha: i/10)].
  3298.     f _ Form extent: sz asPoint depth: 32.
  3299.     1 to: 5 do: 
  3300.         [:i | f fillShape: (Form dotOfSize: sz*(6-i)//5)
  3301.                 fillColor: (Color red alpha: (i/5 raisedTo: 2))
  3302.                 at: f extent // 2].
  3303.     [Sensor yellowButtonPressed] whileFalse:
  3304.         [Sensor redButtonPressed ifTrue:
  3305.             [(BitBlt toForm: Display) copyForm: f to: Sensor cursorPoint rule: Form blend]]!
  3306. exampleOne
  3307.     "This tests BitBlt by displaying the result of all sixteen combination rules that BitBlt is capable of using. (Please see the comment in BitBlt for the meaning of the combination rules)."
  3308.     | path |
  3309.     path _ Path new.
  3310.     0 to: 3 do: [:i | 0 to: 3 do: [:j | path add: j * 100 @ (i * 75)]].
  3311.     Display fillWhite.
  3312.     path _ path translateBy: 60 @ 40.
  3313.     1 to: 16 do: [:index | BitBlt
  3314.             exampleAt: (path at: index)
  3315.             rule: index - 1
  3316.             fillColor: Color gray]
  3317.  
  3318.     "BitBlt exampleOne"!
  3319. exampleTwo
  3320.     "This is to test painting with a gray tone. It also tests that the seaming with gray patterns is correct in the microcode. Lets you paint for a while and then automatically stops."
  3321.     | f aBitBlt |
  3322.     "create a small black Form source as a brush. "
  3323.     f _ Form extent: 20 @ 20.
  3324.     f fillBlack.
  3325.     "create a BitBlt which will OR gray into the display. "
  3326.     aBitBlt _ BitBlt
  3327.         destForm: Display
  3328.         sourceForm: f
  3329.         fillColor: Color gray
  3330.         combinationRule: Form under
  3331.         destOrigin: Sensor cursorPoint
  3332.         sourceOrigin: 0 @ 0
  3333.         extent: f extent
  3334.         clipRect: Display computeBoundingBox.
  3335.     "paint the gray Form on the screen for a while. "
  3336.     [Sensor anyButtonPressed] whileFalse: 
  3337.         [aBitBlt destOrigin: Sensor cursorPoint.
  3338.         aBitBlt copyBits]
  3339.  
  3340.     "BitBlt exampleTwo"! !
  3341.  
  3342. !BitBlt class methodsFor: 'private'!
  3343. exampleAt: originPoint rule: rule fillColor: mask 
  3344.     "This builds a source and destination form and copies the source to the
  3345.     destination using the specifed rule and mask. It is called from the method
  3346.     named exampleOne."
  3347.  
  3348.     | s d border aBitBlt | 
  3349.     border_Form extent: 32@32.
  3350.     border fillBlack.
  3351.     border fill: (1@1 extent: 30@30) fillColor: Form white.
  3352.     s _ Form extent: 32@32.
  3353.     s fillWhite.
  3354.     s fillBlack: (7@7 corner: 25@25).
  3355.     d _ Form extent: 32@32.
  3356.     d fillWhite.
  3357.     d fillBlack: (0@0 corner: 32@16).
  3358.  
  3359.     s displayOn: Display at: originPoint.
  3360.     border displayOn: Display at: originPoint rule: Form under.
  3361.     d displayOn: Display at: originPoint + (s width @0).
  3362.     border displayOn: Display at: originPoint + (s width @0) rule: Form under.
  3363.  
  3364.     d displayOn: Display at: originPoint + (s extent // (2 @ 1)).
  3365.     aBitBlt _ BitBlt
  3366.         destForm: Display
  3367.         sourceForm: s
  3368.         fillColor: mask
  3369.         combinationRule: rule
  3370.         destOrigin: originPoint + (s extent // (2 @ 1))
  3371.         sourceOrigin: 0 @ 0
  3372.         extent: s extent
  3373.         clipRect: Display computeBoundingBox.
  3374.     aBitBlt copyBits.
  3375.     border 
  3376.         displayOn: Display at: originPoint + (s extent // (2 @ 1))
  3377.         rule: Form under.
  3378.    
  3379.     "BitBlt exampleAt: 100@100 rule: Form over fillColor: Display gray"! !MouseMenuController subclass: #BitEditor
  3380.     instanceVariableNames: 'scale squareForm color transparent '
  3381.     classVariableNames: 'YellowButtonMessages YellowButtonMenu ColorButtons '
  3382.     poolDictionaries: ''
  3383.     category: 'Graphics-Editors'!
  3384. BitEditor comment:
  3385. 'I am a bit-magnifying tool for editing small Forms directly on the display screen. I continue to be active until the user points outside of my viewing area.'!
  3386.  
  3387. !BitEditor methodsFor: 'initialize-release'!
  3388. initialize
  3389.  
  3390.     super initialize.
  3391.     self initializeYellowButtonMenu!
  3392. release
  3393.  
  3394.     super release.
  3395.     squareForm release.
  3396.     squareForm _ nil! !
  3397.  
  3398. !BitEditor methodsFor: 'view access'!
  3399. view: aView
  3400.  
  3401.     super view: aView.
  3402.     scale _ aView transformation scale.    
  3403.     scale _ scale x rounded @ scale y rounded.
  3404.     squareForm _ Form extent: scale depth: aView model depth.
  3405.     squareForm fillBlack! !
  3406.  
  3407. !BitEditor methodsFor: 'basic control sequence'!
  3408. controlInitialize
  3409.  
  3410.     super controlInitialize.
  3411.     Cursor crossHair show!
  3412. controlTerminate
  3413.  
  3414.     Cursor normal show! !
  3415.  
  3416. !BitEditor methodsFor: 'control defaults'!
  3417. isControlActive
  3418.  
  3419.     ^super isControlActive & sensor blueButtonPressed not 
  3420.         & sensor keyboardPressed not!
  3421. redButtonActivity
  3422.     | absoluteScreenPoint formPoint displayPoint |
  3423.     [sensor redButtonPressed]
  3424.       whileTrue: 
  3425.         [absoluteScreenPoint _ sensor cursorPoint.    
  3426.         formPoint _ (view inverseDisplayTransform: absoluteScreenPoint - (scale//2)) rounded.
  3427.         displayPoint _ view displayTransform: formPoint.
  3428.         squareForm 
  3429.             displayOn: Display
  3430.             at: displayPoint 
  3431.             clippingBox: view insetDisplayBox 
  3432.             rule: Form over
  3433.             fillColor: nil.
  3434.         view changeValueAt: formPoint put: color]! !
  3435.  
  3436. !BitEditor methodsFor: 'menu messages'!
  3437. accept
  3438.     "The edited information should now be accepted by the view."
  3439.  
  3440.     view accept!
  3441. cancel
  3442.     "The edited informatin should be forgotten by the view."
  3443.  
  3444.     view cancel!
  3445. fileOut
  3446.     model writeOnFileNamed:
  3447.         (FillInTheBlank request: 'Enter file name'
  3448.                 initialAnswer: 'Filename.icon').
  3449. !
  3450. setColor: aColor
  3451.     "Set the color that the next edited dots of the model to be the argument, 
  3452.     aSymbol. aSymbol can be any color changing message understood by a 
  3453.     Form, such as white or black."
  3454.  
  3455.     color _ aColor pixelValueForDepth: model depth.
  3456.     squareForm fillColor: aColor.
  3457. !
  3458. setTransparentColor
  3459.     squareForm fillColor: Color gray.
  3460.     color _ model transparentPixelValue!
  3461. test
  3462.     view workingForm follow: [Sensor cursorPoint] while: [Sensor noButtonPressed].
  3463.     Sensor waitNoButton! !
  3464.  
  3465. !BitEditor methodsFor: 'private'!
  3466. initializeYellowButtonMenu
  3467.  
  3468.     self yellowButtonMenu: YellowButtonMenu
  3469.         yellowButtonMessages: YellowButtonMessages! !
  3470. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3471.  
  3472. BitEditor class
  3473.     instanceVariableNames: ''!
  3474.  
  3475. !BitEditor class methodsFor: 'class initialization'!
  3476. initialize
  3477.     "The Bit Editor is the only controller to override the use of the blue
  3478.     button with a different pop-up menu. Initialize this menu."
  3479.  
  3480.     YellowButtonMenu _ PopUpMenu labels:
  3481. 'cancel
  3482. accept
  3483. file out
  3484. test' lines: #(2 3).
  3485.     YellowButtonMessages _ #(cancel accept fileOut test)    
  3486.  
  3487.     "BitEditor initialize"! !
  3488.  
  3489. !BitEditor class methodsFor: 'instance creation'!
  3490. openOnForm: aForm 
  3491.     "Create and schedule a BitEditor on the form aForm at its top left corner. 
  3492.     Show the small and magnified view of aForm."
  3493.  
  3494.     | scaleFactor |
  3495.     scaleFactor _ 8 @ 8.
  3496.     ^self openOnForm: aForm
  3497.         at: (self locateMagnifiedView: aForm scale: scaleFactor) topLeft
  3498.         scale: scaleFactor!
  3499. openOnForm: aForm at: magnifiedLocation 
  3500.     "Create and schedule a BitEditor on the form aForm at magnifiedLocation. 
  3501.     Show the small and magnified view of aForm."
  3502.  
  3503.     ^self openOnForm: aForm
  3504.         at: magnifiedLocation
  3505.         scale: 8 @ 8!
  3506. openOnForm: aForm at: magnifiedLocation scale: scaleFactor 
  3507.     "Create and schedule a BitEditor on the form aForm. Show the small and 
  3508.     magnified view of aForm."
  3509.  
  3510.     | aScheduledView |
  3511.     aScheduledView _ self
  3512.                 bitEdit: aForm
  3513.                 at: magnifiedLocation
  3514.                 scale: scaleFactor
  3515.                 remoteView: nil.
  3516.     aScheduledView controller openDisplayAt:
  3517.         aScheduledView displayBox topLeft + (aScheduledView displayBox extent / 2)!
  3518. openScreenViewOnForm: aForm at: formLocation magnifiedAt: magnifiedLocation scale: scaleFactor
  3519.     "Create and schedule a BitEditor on the form aForm. Show the magnified
  3520.     view of aForm in a scheduled window."
  3521.     | smallFormView bitEditor savedForm r |
  3522.     smallFormView _ FormView new model: aForm.
  3523.     smallFormView align: smallFormView viewport topLeft with: formLocation.
  3524.     bitEditor _ self bitEdit: aForm at: magnifiedLocation scale: scaleFactor remoteView: smallFormView.
  3525.     bitEditor controller blueButtonMenu: nil blueButtonMessages: nil.
  3526.     savedForm _ Form fromDisplay: (r _ bitEditor displayBox expandBy: (0@23 corner: 0@0)).
  3527.     bitEditor controller startUp.
  3528.     savedForm displayOn: Display at: r topLeft.
  3529.     bitEditor release.
  3530.     smallFormView release.
  3531.  
  3532.     "BitEditor magnifyOnScreen."! !
  3533.  
  3534. !BitEditor class methodsFor: 'examples'!
  3535. magnifyOnScreen
  3536.     "Bit editing of an area of the display screen. User designates a 
  3537.     rectangular area that is magnified by 8 to allow individual screens dots to
  3538.     be modified. red button is used to set a bit to black and yellow button is
  3539.     used to set a bit to white. Editor is not scheduled in a view. Original
  3540.     screen location is updated immediately. This is the same as FormEditor
  3541.     magnify."
  3542.     | smallRect smallForm scaleFactor tempRect |
  3543.     scaleFactor _ 8 @ 8.
  3544.     smallRect _ Rectangle fromUser.
  3545.     smallRect isNil ifTrue: [^self].
  3546.     smallForm _ Form fromDisplay: smallRect.
  3547.     tempRect _ self locateMagnifiedView: smallForm scale: scaleFactor.
  3548.     "show magnified form size until mouse is depressed"
  3549.     self
  3550.         openScreenViewOnForm: smallForm 
  3551.         at: smallRect topLeft 
  3552.         magnifiedAt: tempRect topLeft 
  3553.         scale: scaleFactor
  3554.  
  3555.     "BitEditor magnifyOnScreen."!
  3556. magnifyWithSmall
  3557. "    Also try:
  3558.     BitEditor openOnForm:
  3559.         (Form extent: 32@32 depth: Display depth)
  3560.     BitEditor openOnForm:
  3561.         ((MaskedForm extent: 32@32 depth: Display depth)
  3562.         withTransparentPixelValue: -1)
  3563. "
  3564.     "Open a BitEditor viewing an area on the screen which the user chooses"
  3565.     | area form |
  3566.     area _ Rectangle fromUser.
  3567.     area isNil ifTrue: [^ self].
  3568.     form _ Form fromDisplay: area.
  3569.     self openOnForm: form
  3570.  
  3571.     "BitEditor magnifyWithSmall."! !
  3572.  
  3573. !BitEditor class methodsFor: 'private'!
  3574. bitEdit: aForm at: magnifiedFormLocation scale: scaleFactor remoteView: remoteView
  3575.     "Create a BitEditor on aForm. That is, aForm is a small image that will 
  3576.     change as a result of the BitEditor changing a second and magnified 
  3577.     view of me. magnifiedFormLocation is where the magnified form is to be 
  3578.     located on the screen. scaleFactor is the amount of magnification. This 
  3579.     method implements a scheduled view containing both a small and 
  3580.     magnified view of aForm. Upon accept, aForm is updated."
  3581.  
  3582.     | aFormView scaledFormView bitEditor topView extent menuView lowerRightExtent |
  3583.     scaledFormView _ FormHolderView new model: aForm.
  3584.     scaledFormView scaleBy: scaleFactor.
  3585.     bitEditor _ self new.
  3586.     scaledFormView controller: bitEditor.
  3587.     bitEditor setColor: Color black.
  3588.     topView _ ColorSystemView new.
  3589.     remoteView == nil ifTrue: [topView label: 'Bit Editor'].
  3590.     topView borderWidth: 2.
  3591.  
  3592.     topView addSubView: scaledFormView.
  3593.     remoteView == nil
  3594.         ifTrue:  "If no remote view, then provide a local view of the form"
  3595.             [aFormView _ FormView new model: scaledFormView workingForm.
  3596.             aFormView controller: NoController new.
  3597.             (aForm isMemberOf: MaskedForm) ifTrue:
  3598.                 [scaledFormView insideColor: Color gray.
  3599.                 aFormView insideColor: Color white].
  3600.             aForm height < 50
  3601.                 ifTrue: [aFormView borderWidthLeft: 0 right: 2 top: 2 bottom: 2]
  3602.                 ifFalse: [aFormView borderWidthLeft: 0 right: 2 top: 2 bottom: 0].
  3603.             topView addSubView: aFormView below: scaledFormView]
  3604.          ifFalse:  "Otherwise, the remote one should view the same form"
  3605.             [remoteView model: scaledFormView workingForm].
  3606.     lowerRightExtent _ remoteView == nil
  3607.             ifTrue:
  3608.                 [(scaledFormView viewport width - aFormView viewport width) @
  3609.                     (aFormView viewport height max: 50)]
  3610.             ifFalse:
  3611.                 [scaledFormView viewport width @ 50].
  3612.     menuView _ self buildColorMenu: lowerRightExtent
  3613.         colorCount: ((aForm isMemberOf: MaskedForm) ifTrue: [2] ifFalse: [1]).
  3614.     menuView model: bitEditor.
  3615.     menuView borderWidthLeft: 0 right: 0 top: 2 bottom: 0.
  3616.     topView
  3617.         addSubView: menuView
  3618.         align: menuView viewport topRight
  3619.         with: scaledFormView viewport bottomRight.
  3620.     extent _ scaledFormView viewport extent + (0 @ lowerRightExtent y)
  3621.             + (4 @ 4).  "+4 for borders"
  3622.     topView minimumSize: extent.
  3623.     topView maximumSize: extent.
  3624.     topView translateBy: magnifiedFormLocation.
  3625.     ^topView!
  3626. buildColorMenu: extent colorCount: nColors
  3627.     "See BitEditor magnifyWithSmall."
  3628.  
  3629.     | menuView index form aSwitchView connector
  3630.     button formExtent highlightForm color leftOffset |
  3631.     connector _ Object new.
  3632.     menuView _ FormMenuView new.
  3633.     menuView window: (0@0 corner: extent).
  3634.     formExtent _ 30@30 min: extent//(nColors*2+1@2).  "compute this better"
  3635.     leftOffset _ extent x-(nColors*2-1*formExtent x)//2.
  3636.     highlightForm _ Form extent: formExtent.
  3637.     highlightForm borderWidth: 4.
  3638.     1 to: nColors do:
  3639.         [:index | 
  3640.         color _ (nColors=1
  3641.             ifTrue: [#(black)]
  3642.             ifFalse: [#(black gray)]) at: index.
  3643.         form _ Form extent: formExtent.
  3644.         form fill: form boundingBox fillColor: (Color perform: color).
  3645.         form borderWidth: 5.
  3646.         form border: form boundingBox width: 4 fillColor: form white.
  3647.         button _ Button new.
  3648.         index = 1 ifTrue:
  3649.             [button onAction: [menuView model setColor: Color fromUser]]
  3650.             ifFalse:
  3651.             [button onAction: [menuView model setTransparentColor]].
  3652.  
  3653.         aSwitchView _ SwitchView new model: button.
  3654.         aSwitchView key: ((nColors=3 ifTrue: ['xvn'] ifFalse: ['xn']) at: index).
  3655.         aSwitchView label: form.
  3656.         aSwitchView window: (0@0 extent: form extent).
  3657.         aSwitchView translateBy: (index-1*2*form width+leftOffset) @ (form height//2).
  3658.         aSwitchView highlightForm: highlightForm.
  3659.     
  3660.         aSwitchView borderWidth: 1.
  3661.         aSwitchView controller selector: #turnOn.
  3662.         menuView addSubView: aSwitchView].
  3663.     ^menuView!
  3664. locateMagnifiedView: aForm scale: scaleFactor
  3665.     "Answer a rectangle at the location where the scaled view of the form,
  3666.     aForm, should be displayed."
  3667.  
  3668.     | tempExtent tempRect |
  3669.     tempExtent _ aForm extent * scaleFactor + (0@50).
  3670.     tempRect _ (Sensor cursorPoint" grid: scaleFactor") extent: tempExtent.
  3671.     "show magnified form size until mouse is depressed"
  3672.     [Sensor redButtonPressed]
  3673.         whileFalse: 
  3674.             [Display reverse: tempRect.
  3675.             Display reverse: tempRect.
  3676.             tempRect _ (Sensor cursorPoint grid: scaleFactor)
  3677.                         extent: tempExtent].
  3678.     ^tempRect! !
  3679.  
  3680. BitEditor initialize!
  3681. ArrayedCollection variableWordSubclass: #Bitmap
  3682.     instanceVariableNames: ''
  3683.     classVariableNames: ''
  3684.     poolDictionaries: ''
  3685.     category: 'Graphics-Support'!
  3686. Bitmap comment:
  3687. 'My instances provide contiguous storage of bits, primarily to hold the graphical data of Forms. Forms and their subclasses provide the additional structural information as to how the bits should be interpreted in two dimensions.'!
  3688.  
  3689. !Bitmap methodsFor: 'initialize-release'!
  3690. fromByteStream: aStream 
  3691.     "Initialize the array of bits by reading integers from the argument, 
  3692.     aStream."
  3693.     aStream nextInto: self! !
  3694.  
  3695. !Bitmap methodsFor: 'filing'!
  3696. readCompressedFrom: aStream 
  3697.     "Initialize the array of bits by reading integers from the argument, 
  3698.     aStream."
  3699.     | pixSize |
  3700.     pixSize _ aStream next.  "1, 2, or 4 bytes"
  3701.     !
  3702. writeCompressedOn: aStream 
  3703.     "Store the array of bits onto the argument, aStream."
  3704.  
  3705.     aStream nextPutAll: self!
  3706. writeOn: aStream 
  3707.     "Store the array of bits onto the argument, aStream."
  3708.  
  3709.     aStream nextInt32Put: self size.
  3710.     aStream nextPutAll: self! !
  3711.  
  3712. !Bitmap methodsFor: 'printing'!
  3713. printOn: aStream
  3714.  
  3715.     aStream nextPutAll: 'a Bitmap of length '.
  3716.     self size printOn: aStream! !
  3717.  
  3718. !Bitmap methodsFor: 'accessing'!
  3719. bitPatternForDepth: depth
  3720.     "The raw call on BitBlt needs a Bitmap to represent this color.  I already am Bitmap like.  I am already adjusted for a specific depth.  Interpret me as an array of (32/depth) Color pixelValues.  BitBlt aligns the first element of this array with the top scanline of the destinationForm, the second with the second, and so on, cycling through the color array as necessary. 6/18/96 tk"
  3721.  
  3722.     ^ self!
  3723. byteAt: byteAddress
  3724.     "Extract a byte from a Bitmap.  Note that this is a byte address and it is one-order.  For repeated use, create an instance of BitBlt and use pixelAt:.  See Form pixelAt:  7/1/96 tk"
  3725.     | lowBits |
  3726.     lowBits _ byteAddress - 1 bitAnd: 3.
  3727.     ^((self at: byteAddress - 1 - lowBits // 4 + 1)
  3728.         bitShift: (lowBits - 3) * 8)
  3729.         bitAnd: 16rFF!
  3730. byteAt: byteAddress put: byte
  3731.     "Insert a byte into a Bitmap.  Note that this is a byte address and it is one-order.  For repeated use, create an instance of BitBlt and use pixelAt:put:.  See Form pixelAt:put:  7/1/96 tk"
  3732.  
  3733.     | longWord shift lowBits longAddr |
  3734.     lowBits _ byteAddress - 1 bitAnd: 3.
  3735.     longWord _ self at: (longAddr _ (byteAddress - 1 - lowBits) // 4 + 1).
  3736.     shift _ (3 - lowBits) * 8.
  3737.     longWord _ longWord - (longWord bitAnd: (16rFF bitShift: shift)) 
  3738.         + (byte bitShift: shift).
  3739.     self at: longAddr put: longWord.
  3740.     ^ byte!
  3741. replaceFrom: start to: stop with: replacement startingAt: repStart 
  3742.     "Primitive. This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the collection, replacement. Answer the receiver. Range checks are performed in the primitive only. Optional. See Object documentation whatIsAPrimitive."
  3743.     <primitive: 105>
  3744.     super replaceFrom: start to: stop with: replacement startingAt: repStart! !
  3745. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3746.  
  3747. Bitmap class
  3748.     instanceVariableNames: ''!
  3749.  
  3750. !Bitmap class methodsFor: 'instance creation'!
  3751. newFromStream: s
  3752.     | len |
  3753.     len _ s nextInt32.
  3754.     len < 0
  3755.         ifTrue: [^ (self new: len negated) readCompressedFrom: s]
  3756.         ifFalse: [^ s nextInto: (self new: len)]! !ContextPart variableSubclass: #BlockContext
  3757.     instanceVariableNames: 'nargs startpc home '
  3758.     classVariableNames: ''
  3759.     poolDictionaries: ''
  3760.     category: 'Kernel-Methods'!
  3761. BlockContext comment:
  3762. 'My instances function similarly to instances of MethodContext, but they hold the dynamic state for execution of a block in Smalltalk. They access all temporary variables and the method sender via their home pointer, so that those values are effectively shared. Their indexable part is used to store their independent value stack during execution.
  3763.     
  3764. My instance must hold onto its home in order to work. This can cause circularities if the home is also pointing (via a temp, perhaps) to the instance. In the rare event that this happens (as in SortedCollection sortBlock:) the message fixTemps will replace home with a copy of home, thus defeating the sharing of temps but, nonetheless, eliminating the circularity.'!
  3765.  
  3766. !BlockContext methodsFor: 'initialize-release'!
  3767. home: aContextPart startpc: position nargs: anInteger 
  3768.     "This is the initialization message. The receiver has been initialized with 
  3769.     the correct size only."
  3770.  
  3771.     home _ aContextPart.
  3772.     startpc _ position.
  3773.     nargs _ anInteger! !
  3774.  
  3775. !BlockContext methodsFor: 'accessing'!
  3776. fixTemps
  3777.     "Fix the values of the temporary variables used in the block that are 
  3778.     ordinarily shared with the method in which the block is defined."
  3779.  
  3780.     home _ home copy.
  3781.     home swapSender: nil!
  3782. hasMethodReturn
  3783.     "Answer whether the receiver has a return ('^') in its code."
  3784.  
  3785.     | method scanner end |
  3786.     method _ self method.
  3787.     "Determine end of block from long jump preceding it"
  3788.     end _ (method at: startpc-2)\\16-4*256 + (method at: startpc-1) + startpc - 1.
  3789.     scanner _ InstructionStream new method: method pc: startpc.
  3790.     scanner scanFor: [:byte | (byte between: 120 and: 124) or: [scanner pc > end]].
  3791.     ^scanner pc <= end!
  3792. home
  3793.     "Answer the context in which the receiver was defined."
  3794.  
  3795.     ^home!
  3796. method
  3797.     "Answer the compiled method in which the receiver was defined."
  3798.  
  3799.     ^home method!
  3800. numArgs
  3801.  
  3802.     ^nargs!
  3803. receiver 
  3804.     "Refer to the comment in ContextPart|receiver."
  3805.  
  3806.     ^home receiver!
  3807. tempAt: index 
  3808.     "Refer to the comment in ContextPart|tempAt:."
  3809.  
  3810.     ^home at: index!
  3811. tempAt: index put: value 
  3812.     "Refer to the comment in ContextPart|tempAt:put:."
  3813.  
  3814.     ^home at: index put: value! !
  3815.  
  3816. !BlockContext methodsFor: 'evaluating'!
  3817. ifError: aBlock
  3818.     | errorBlock lastHandler val activeControllerProcess  |
  3819.     activeControllerProcess _ ScheduledControllers activeControllerProcess.
  3820.     lastHandler _ activeControllerProcess errorHandler.
  3821.     errorBlock _
  3822.         [:aString :aReceiver |  activeControllerProcess errorHandler: lastHandler.
  3823.         ^ aBlock value: aString].
  3824.     activeControllerProcess errorHandler: errorBlock.
  3825.     val _ self value.
  3826.     activeControllerProcess errorHandler: lastHandler.
  3827.     ^ val!
  3828. value
  3829.     "Primitive. Evaluate the block represented by the receiver. Fail if the 
  3830.     block expects any arguments or if the block is already being executed. 
  3831.     Optional. No Lookup. See Object documentation whatIsAPrimitive."
  3832.  
  3833.     <primitive: 81>
  3834.     ^self valueWithArguments: #()!
  3835. value: arg 
  3836.     "Primitive. Evaluate the block represented by the receiver. Fail if the 
  3837.     block expects other than one argument or if the block is already being 
  3838.     executed. Optional. No Lookup. See Object documentation 
  3839.     whatIsAPrimitive."
  3840.  
  3841.     <primitive: 81>
  3842.     ^self valueWithArguments: (Array with: arg)!
  3843. value: arg1 ifError: aBlock
  3844.     | errorBlock lastHandler val activeControllerProcess  |
  3845.     activeControllerProcess _ ScheduledControllers activeControllerProcess.
  3846.     lastHandler _ activeControllerProcess errorHandler.
  3847.     errorBlock _
  3848.         [:aString :aReceiver |  activeControllerProcess errorHandler: lastHandler.
  3849.         ^ aBlock value: aString value: aReceiver].
  3850.     activeControllerProcess errorHandler: errorBlock.
  3851.     val _ self value: arg1.
  3852.     activeControllerProcess errorHandler: lastHandler.
  3853.     ^ val!
  3854. value: arg1 value: arg2 
  3855.     "Primitive. Evaluate the block represented by the receiver. Fail if the 
  3856.     block expects other than two arguments or if the block is already being 
  3857.     executed. Optional. See Object documentation whatIsAPrimitive."
  3858.  
  3859.     <primitive: 81>
  3860.     ^self valueWithArguments: (Array with: arg1 with: arg2)!
  3861. value: arg1 value: arg2 value: arg3 
  3862.     "Primitive. Evaluate the block represented by the receiver. Fail if the 
  3863.     block expects other than three arguments or if the block is already being 
  3864.     executed. Optional. See Object documentation whatIsAPrimitive."
  3865.  
  3866.     <primitive: 81>
  3867.     ^self valueWithArguments: 
  3868.         (Array
  3869.             with: arg1
  3870.             with: arg2
  3871.             with: arg3)!
  3872. valueWithArguments: anArray 
  3873.     "Primitive. Evaluate the block represented by the receiver. The argument 
  3874.     is an Array whose elements are the arguments for the block. Fail if the 
  3875.     length of the Array is not the same as the the number of arguments that 
  3876.     the block was expecting. Fail if the block is already being executed. 
  3877.     Essential. See Object documentation whatIsAPrimitive."
  3878.  
  3879.     <primitive: 82>
  3880.     self valueError! !
  3881.  
  3882. !BlockContext methodsFor: 'controlling'!
  3883. ifFail: aOneArgBlock
  3884.     "Usage:
  3885.         answer _ [code to try] ifFail: [:aFailure | code to run instead].
  3886.      'answer' will become the value of 'code to try', unless that code invokes
  3887.          (Failure name: #aName) propagate
  3888.      or
  3889.          (Failure name: #aName value: anErrCode) propagate
  3890.      in which case 'answer' will become the value of 'code to run instead'.
  3891.  
  3892.      The first time 'propagate' is sent to a failure, three attributes of that failure
  3893.      are determined:
  3894.         The 'instigator' of the failure is that Context executing 'ifFail:' whose
  3895.             receiver is the block whose evaluation called 'propagate'.
  3896.         The 'generator' of the failure is the instigator's receiver-block
  3897.             (the one whose evaluation called 'propagate').
  3898.         The 'handler' of the failure is the instigator's argument-block
  3899.             (the one that will be run because the generator failed).
  3900.  
  3901.      Special things you can do in a handler are explained below.
  3902.  
  3903.      You can access the 'name' and 'value' fields of aFailure.
  3904.  
  3905.      You can create a new failure; it will run the handler of the next outer 'ifFail:'.
  3906.  
  3907.      You can propagate a failure to the next outer 'ifFail:' with:
  3908.         aFailure propagate
  3909.      You can alter the name or value of a failure before propagating it, e.g.:
  3910.         (aFailure name: #anotherName) propagate
  3911.      but the instigator and generator remain unchanged.
  3912.  
  3913.      A failure keeps a stack of its propagators (invocations of propagate).
  3914.      You can print out this stack in a debugger pane with a 'printIt' of:
  3915.         aFailure methods
  3916.      to get a collection of (class selector) two-element-arrays, or with a 'printIt' of:
  3917.         aFailure receivers
  3918.      to get a collection of the objects running those methods.
  3919.  
  3920.      You can invoke:
  3921.         aFailure reply: aReply
  3922.      It will cause the top propagator to be popped from the stack and to
  3923.      return aReply to its caller.  If the stack is empty, it is an error.
  3924.      Thus, a typical call on 'propagate', other than the initial call, is:
  3925.         aFailure reply: aFailure propagate
  3926.      and a typical initial call is:
  3927.         reply _ (Failure name: #aName) propagate
  3928.      To prevent a failure from receiving a reply, send it 'noReply'.  Example:
  3929.         (Failure name: #aName) noReply propagate
  3930.      To find out whether a failure can receive a reply, send it 'canReply'.
  3931.  
  3932.      Note that 'reply:' pops the Context stack, while 'propagate' does not do so.
  3933.      Returning from or falling off the end of a handler also pops the context stack.
  3934.  
  3935.      You can invoke:
  3936.         aFailure retry
  3937.      It will re-evaluate the generator of the failure and answer its value; if it
  3938.      fails again, it will behave like a failure generated by the caller of 'retry',
  3939.      and thus will not run the original handler of aFailure.  A typical call is:
  3940.         [aFailure reply: aFailure retry] ifFail: [:anotherFailure | moreCode].
  3941.      To prevent a failure from being retried, send it 'noRetry'.  Example:
  3942.         answer _ (aFailure name: #newName) noRetry propagate
  3943.      To find out whether a failure can be retried, send it 'canRetry'."
  3944.  
  3945.  
  3946.     aOneArgBlock numArgs = 1 ifFalse:
  3947.         [self notify: 'ifFail: argument must be a one-argument block'].
  3948.     ^self value!
  3949. whileFalse
  3950.     "Ordinarily compiled in-line, and therefore not overridable.
  3951.     This is in case the message is sent to other than a literal block.
  3952.     Evaluate the receiver, as long as its value is false."
  3953.  
  3954.     ^ [self value] whileFalse: []!
  3955. whileFalse: aBlock 
  3956.     "Ordinarily compiled in-line, and therefore not overridable.
  3957.     This is in case the message is sent to other than a literal block.
  3958.     Evaluate the argument, aBlock, as long as the value of the receiver is false."
  3959.  
  3960.     ^ [self value] whileFalse: [aBlock value]!
  3961. whileTrue
  3962.     "Ordinarily compiled in-line, and therefore not overridable.
  3963.     This is in case the message is sent to other than a literal block.
  3964.     Evaluate the receiver, as long as its value is true."
  3965.  
  3966.     ^ [self value] whileTrue: []!
  3967. whileTrue: aBlock 
  3968.     "Ordinarily compiled in-line, and therefore not overridable.
  3969.     This is in case the message is sent to other than a literal block.
  3970.     Evaluate the argument, aBlock, as long as the value of the receiver is true."
  3971.  
  3972.     ^ [self value] whileTrue: [aBlock value]! !
  3973.  
  3974. !BlockContext methodsFor: 'scheduling'!
  3975. fork
  3976.     "Create and schedule a Process running the code in the receiver."
  3977.  
  3978.     self newProcess resume!
  3979. forkAt: priority 
  3980.     "Create and schedule a Process running the code in the receiver. The 
  3981.     priority of the process is the argument, priority."
  3982.  
  3983.     | forkedProcess |
  3984.     forkedProcess _ self newProcess.
  3985.     forkedProcess priority: priority.
  3986.     forkedProcess resume!
  3987. newProcess
  3988.     "Answer a Process running the code in the receiver. The process is not 
  3989.     scheduled."
  3990.  
  3991.     ^Process
  3992.         forContext: 
  3993.             [self value.
  3994.             Processor terminateActive]
  3995.         priority: Processor activePriority!
  3996. newProcessWith: anArray 
  3997.     "Answer a Process running the code in the receiver. The receiver's block 
  3998.     arguments are bound to the contents of the argument, anArray. The 
  3999.     process is not scheduled."
  4000.  
  4001.     ^Process
  4002.         forContext: 
  4003.             [self valueWithArguments: anArray.
  4004.             Processor terminateActive]
  4005.         priority: Processor activePriority! !
  4006.  
  4007. !BlockContext methodsFor: 'instruction decoding'!
  4008. blockReturnTop
  4009.     "Simulate the interpreter's action when a ReturnTopOfStack bytecode is 
  4010.     encountered in the receiver."
  4011.  
  4012.     | save dest |
  4013.     save _ home.    "Needed because return code will nil it"
  4014.     dest _ self return: self pop to: self sender.
  4015.     home _ save.
  4016.     sender _ nil.
  4017.     ^dest! !
  4018.  
  4019. !BlockContext methodsFor: 'printing'!
  4020. printOn: aStream
  4021.  
  4022.     home == nil ifTrue: [^aStream nextPutAll: 'a BlockContext with home=nil'].
  4023.     aStream nextPutAll: '[] in '.
  4024.     super printOn: aStream! !
  4025.  
  4026. !BlockContext methodsFor: 'private'!
  4027. cannotReturn: arg
  4028.     "Kills off processes that didn't terminate properly"
  4029.     "Display reverse; reverse."  "<-- So we can catch the suspend bug"
  4030.     Processor terminateActive!
  4031. startpc
  4032.     "for use by the System Tracer only"
  4033.  
  4034.     ^startpc!
  4035. valueError
  4036.  
  4037.     self error: 'Incompatible number of args, or already active'! !
  4038.  
  4039. !BlockContext methodsFor: 'system simulation'!
  4040. pushArgs: args from: sendr 
  4041.     "Simulates action of the value primitive."
  4042.  
  4043.     args size ~= nargs ifTrue: [^self error: 'incorrect number of args'].
  4044.     stackp _ 0.
  4045.     args do: [:arg | self push: arg].
  4046.     sender _ sendr.
  4047.     pc _ startpc! !ParseNode subclass: #BlockNode
  4048.     instanceVariableNames: 'arguments statements returns nArgsNode size remoteCopyNode '
  4049.     classVariableNames: ''
  4050.     poolDictionaries: ''
  4051.     category: 'System-Compiler'!
  4052. BlockNode comment:
  4053. 'I represent a bracketed block with 0 or more arguments and 1 or more statements. If I am initialized with no statements, I create one. I have a flag to tell whether my last statement returns a value from the enclosing method. My last three fields remember data needed for code generation. I can emit for value in the usual way, in which case I create a literal method (actually a context remotely copied) to be evaluated by sending it value: at run time. Or I can emit code to be evaluated in line; this only happens at the top level of a method and in conditionals and while-loops, none of which have arguments.'!
  4054.  
  4055. !BlockNode methodsFor: 'initialize-release'!
  4056. arguments: argNodes statements: statementsCollection returns: returnBool from: encoder
  4057.     "Compile."
  4058.  
  4059.     arguments _ argNodes.
  4060.     statements _ statementsCollection size > 0
  4061.                 ifTrue: [statementsCollection]
  4062.                 ifFalse: [argNodes size > 0
  4063.                         ifTrue: [statementsCollection copyWith: arguments last]
  4064.                         ifFalse: [Array with: NodeNil]].
  4065.     returns _ returnBool!
  4066. statements: statementsCollection returns: returnBool 
  4067.     "Decompile."
  4068.  
  4069.     | returnLast |
  4070.     returnLast _ returnBool.
  4071.     returns _ false.
  4072.     statements _ 
  4073.         (statementsCollection size > 1 
  4074.             and: [(statementsCollection at: statementsCollection size - 1) 
  4075.                     isReturningIf])
  4076.                 ifTrue: 
  4077.                     [returnLast _ false.
  4078.                     statementsCollection copyFrom: 1 to: statementsCollection size - 1]
  4079.                 ifFalse: [statementsCollection size = 0
  4080.                         ifTrue: [Array with: NodeNil]
  4081.                         ifFalse: [statementsCollection]].
  4082.     arguments _ Array new: 0.
  4083.     returnLast ifTrue: [self returnLast]! !
  4084.  
  4085. !BlockNode methodsFor: 'accessing'!
  4086. arguments: argNodes 
  4087.     "Decompile."
  4088.  
  4089.     arguments _ argNodes!
  4090. firstArgument
  4091.     ^ arguments first!
  4092. numberOfArguments
  4093.  
  4094.     ^arguments size!
  4095. returnLast
  4096.  
  4097.     self returns
  4098.         ifFalse: 
  4099.             [returns _ true.
  4100.             statements at: statements size put: statements last asReturnNode]!
  4101. returnSelfIfNoOther
  4102.  
  4103.     self returns
  4104.         ifFalse: 
  4105.             [statements last == NodeSelf ifFalse: [statements add: NodeSelf].
  4106.             self returnLast]! !
  4107.  
  4108. !BlockNode methodsFor: 'testing'!
  4109. canBeSpecialArgument
  4110.     "Can I be an argument of (e.g.) ifTrue:?"
  4111.  
  4112.     ^arguments size = 0!
  4113. isComplex
  4114.  
  4115.     ^statements size > 1 or: [statements size = 1 and: [statements first isComplex]]!
  4116. isJust: node
  4117.  
  4118.     returns ifTrue: [^false].
  4119.     ^statements size = 1 and: [statements first == node]!
  4120. isJustCaseError
  4121.  
  4122.     ^ statements size = 1 and:
  4123.         [statements first
  4124.             isMessage: #caseError
  4125.             receiver: [:r | r==NodeSelf]
  4126.             arguments: nil]!
  4127. isQuick
  4128.     ^ statements size = 1
  4129.         and: [statements first isVariableReference
  4130.                 or: [statements first isSpecialConstant]]!
  4131. returns
  4132.  
  4133.     ^returns or: [statements last isReturningIf]! !
  4134.  
  4135. !BlockNode methodsFor: 'code generation'!
  4136. code
  4137.  
  4138.     ^statements first code!
  4139. emitExceptLast: stack on: aStream
  4140.     | nextToLast |
  4141.     nextToLast _ statements size - 1.
  4142.     nextToLast < 1 ifTrue: [^ self].  "Only one statement"
  4143.     1 to: nextToLast - 1 do:
  4144.         [:i | (statements at: i) emitForEffect: stack on: aStream].
  4145.     (returns  "Don't pop before a return"
  4146.             and: [(statements at: nextToLast) prefersValue])
  4147.         ifTrue: [(statements at: nextToLast) emitForValue: stack on: aStream]
  4148.         ifFalse: [(statements at: nextToLast) emitForEffect: stack on: aStream]!
  4149. emitForEvaluatedEffect: stack on: aStream
  4150.  
  4151.     self returns
  4152.         ifTrue: 
  4153.             [self emitForEvaluatedValue: stack on: aStream.
  4154.             stack pop: 1]
  4155.         ifFalse: 
  4156.             [self emitExceptLast: stack on: aStream.
  4157.             statements last emitForEffect: stack on: aStream]!
  4158. emitForEvaluatedValue: stack on: aStream
  4159.     self emitExceptLast: stack on: aStream.
  4160.     statements last emitForValue: stack on: aStream.
  4161.     (returns and: [statements size > 1
  4162.             and: [(statements at: statements size-1) prefersValue]])
  4163.         ifTrue: [stack pop: 1]  "compensate for elided pop prior to return"!
  4164. emitForValue: stack on: aStream
  4165.     | arg |
  4166.     aStream nextPut: LdThisContext.
  4167.     stack push: 1.
  4168.     nArgsNode emitForValue: stack on: aStream.
  4169.     remoteCopyNode
  4170.         emit: stack
  4171.         args: 1
  4172.         on: aStream.
  4173.     "Force a two byte jump."
  4174.     self emitLong: size code: JmpLong on: aStream.
  4175.     stack push: arguments size.
  4176.     arguments reverseDo: [:arg | arg emitStorePop: stack on: aStream].
  4177.     self emitForEvaluatedValue: stack on: aStream.
  4178.     self returns ifFalse: [aStream nextPut: EndRemote].
  4179.     stack pop: 1!
  4180. sizeExceptLast: encoder
  4181.     | codeSize nextToLast |
  4182.     nextToLast _ statements size - 1.
  4183.     nextToLast < 1 ifTrue: [^ 0]. "Only one statement"
  4184.     codeSize _ 0.
  4185.     1 to: nextToLast - 1 do: 
  4186.         [:i | codeSize _ codeSize + ((statements at: i) sizeForEffect: encoder)].
  4187.     ^ (returns  "Don't pop before a return"
  4188.             and: [(statements at: nextToLast) prefersValue])
  4189.         ifTrue: [codeSize + ((statements at: nextToLast) sizeForValue: encoder)]
  4190.         ifFalse: [codeSize + ((statements at: nextToLast) sizeForEffect: encoder)]!
  4191. sizeForEvaluatedEffect: encoder
  4192.  
  4193.     self returns ifTrue: [^self sizeForEvaluatedValue: encoder].
  4194.     ^(self sizeExceptLast: encoder)
  4195.         + (statements last sizeForEffect: encoder)!
  4196. sizeForEvaluatedValue: encoder
  4197.  
  4198.     ^(self sizeExceptLast: encoder)
  4199.         + (statements last sizeForValue: encoder)!
  4200. sizeForValue: encoder
  4201.     nArgsNode _ encoder encodeLiteral: arguments size.
  4202.     remoteCopyNode _ encoder encodeSelector: #blockCopy:.
  4203.     size _ (self sizeForEvaluatedValue: encoder)
  4204.                 + (self returns ifTrue: [0] ifFalse: [1]). "endBlock"
  4205.     arguments _ arguments collect:  "Chance to prepare debugger remote temps"
  4206.                 [:arg | arg asStorableNode: encoder].
  4207.     arguments do: [:arg | size _ size + (arg sizeForStorePop: encoder)].
  4208.     ^1 + (nArgsNode sizeForValue: encoder) 
  4209.         + (remoteCopyNode size: encoder args: 1 super: false) + 2 + size! !
  4210.  
  4211. !BlockNode methodsFor: 'printing'!
  4212. printArgumentsOn: aStream indent: level
  4213.  
  4214.     arguments size = 0
  4215.         ifFalse: 
  4216.             [arguments do: 
  4217.                 [:arg | 
  4218.                 aStream nextPut: $:.
  4219.                 aStream nextPutAll: arg key.
  4220.                 aStream space].
  4221.             aStream nextPutAll: '| '.
  4222.             "If >0 args and >1 statement, put all statements on separate lines"
  4223.             statements size > 1 ifTrue: [aStream crtab: level]]!
  4224. printOn: aStream indent: level
  4225.  
  4226.     statements size <= 1 ifFalse: [aStream crtab: level].
  4227.     aStream nextPut: $[.
  4228.     self printArgumentsOn: aStream indent: level.
  4229.     self printStatementsOn: aStream indent: level.
  4230.     aStream nextPut: $]!
  4231. printStatementsOn: aStream indent: level
  4232.  
  4233.     | len shown thisStatement |
  4234.     comment == nil
  4235.         ifFalse: 
  4236.             [self printCommentOn: aStream indent: level.
  4237.             aStream crtab: level].
  4238.     len _ shown _ statements size.
  4239.     (level = 1 and: [statements last isReturnSelf])
  4240.         ifTrue: [shown _ 1 max: shown - 1]
  4241.         ifFalse: [(len = 1 and: [((statements at: 1) == NodeNil) & (arguments size = 0)])
  4242.                     ifTrue: [shown _ shown - 1]].
  4243.     1 to: shown do: 
  4244.         [:i | 
  4245.         thisStatement _ statements at: i.
  4246.         thisStatement == NodeSelf
  4247.             ifFalse: 
  4248.                 [thisStatement printOn: aStream indent: level.
  4249.                 i < shown ifTrue: [aStream nextPut: $.; crtab: level].
  4250.                 thisStatement comment size > 0
  4251.                     ifTrue: 
  4252.                         [i = shown ifTrue: [aStream crtab: level].
  4253.                         thisStatement printCommentOn: aStream indent: level.
  4254.                         i < shown ifTrue: [aStream crtab: level]]]]! !
  4255.  
  4256. !BlockNode methodsFor: 'equation translation'!
  4257. collectVariables
  4258.     ^statements inject: Array new into: [:array :statement | array, statement collectVariables]!
  4259. copyReplacingVariables: varDict 
  4260.     | t1 |
  4261.     t1 _ statements collect: [:s | s copyReplacingVariables: varDict].
  4262.     ^(self copy) statements: t1; yourself!
  4263. specificMatch: aTree using: matchDict 
  4264.     statements with: aTree statements do: [:s1 :s2 |
  4265.             (s1 match: s2 using: matchDict) ifFalse: [^false]].
  4266.     ^true!
  4267. statements
  4268.     ^statements!
  4269. statements: val
  4270.     statements _ val! !
  4271.  
  4272. !BlockNode methodsFor: 'C translation'! !
  4273. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  4274.  
  4275. BlockNode class
  4276.     instanceVariableNames: ''!
  4277.  
  4278. !BlockNode class methodsFor: 'instance creation'!
  4279. withJust: aNode
  4280.     "Used to create a simple block, eg: withJust: NodeNil"
  4281.     ^ self new statements: (Array with: aNode) returns: false! !WaveTableSound subclass: #BoinkSound
  4282.     instanceVariableNames: ''
  4283.     classVariableNames: ''
  4284.     poolDictionaries: ''
  4285.     category: 'Sound'!
  4286.  
  4287. !BoinkSound methodsFor: 'initialization'!
  4288. setPitch: p dur: d loudness: l
  4289.     "This is just a WaveTableSound that decays by default."
  4290.     "(BoinkSound pitch: 880.0 dur: 2.0 loudness: 1000) play"
  4291.  
  4292.     super setPitch: p dur: d loudness: l.
  4293.     decayRate _ 0.92.
  4294. ! !Object subclass: #Boolean
  4295.     instanceVariableNames: ''
  4296.     classVariableNames: ''
  4297.     poolDictionaries: ''
  4298.     category: 'Kernel-Objects'!
  4299. Boolean comment:
  4300. 'I represent logical values, providing boolean operations and conditional control structures.'!
  4301.  
  4302. !Boolean methodsFor: 'logical operations'!
  4303. & aBoolean 
  4304.     "Evaluating conjunction. Evaluate the argument. Then answer true if 
  4305.     both the receiver and the argument are true."
  4306.  
  4307.     self subclassResponsibility!
  4308. eqv: aBoolean 
  4309.     "Answer true if the receiver is equivalent to aBoolean."
  4310.  
  4311.     ^self == aBoolean!
  4312. not
  4313.     "Negation. Answer true if the receiver is false, answer false if the 
  4314.     receiver is true."
  4315.  
  4316.     self subclassResponsibility!
  4317. xor: aBoolean 
  4318.     "Exclusive OR. Answer true if the receiver is not equivalent to aBoolean."
  4319.  
  4320.     ^(self == aBoolean) not!
  4321. | aBoolean 
  4322.     "Evaluating disjunction (OR). Evaluate the argument. Then answer true 
  4323.     if either the receiver or the argument is true."
  4324.  
  4325.     self subclassResponsibility! !
  4326.  
  4327. !Boolean methodsFor: 'controlling'!
  4328. and: alternativeBlock 
  4329.     "Nonevaluating conjunction. If the receiver is true, answer the value of 
  4330.     the argument, alternativeBlock; otherwise answer false without 
  4331.     evaluating the argument."
  4332.  
  4333.     self subclassResponsibility!
  4334. ifFalse: alternativeBlock 
  4335.     "If the receiver is true (i.e., the condition is true), then the value is the 
  4336.     true alternative, which is nil. Otherwise answer the result of evaluating 
  4337.     the argument, alternativeBlock. Create an error notification if the 
  4338.     receiver is nonBoolean. Execution does not actually reach here because 
  4339.     the expression is compiled in-line."
  4340.  
  4341.     self subclassResponsibility!
  4342. ifFalse: falseAlternativeBlock ifTrue: trueAlternativeBlock 
  4343.     "Same as ifTrue:ifFalse:."
  4344.  
  4345.     self subclassResponsibility!
  4346. ifTrue: alternativeBlock 
  4347.     "If the receiver is false (i.e., the condition is false), then the value is the 
  4348.     false alternative, which is nil. Otherwise answer the result of evaluating 
  4349.     the argument, alternativeBlock. Create an error notification if the 
  4350.     receiver is nonBoolean. Execution does not actually reach here because 
  4351.     the expression is compiled in-line."
  4352.  
  4353.     self subclassResponsibility!
  4354. ifTrue: trueAlternativeBlock ifFalse: falseAlternativeBlock
  4355.     "If the receiver is true (i.e., the condition is true), then answer the value 
  4356.     of the argument trueAlternativeBlock. If the receiver is false, answer the 
  4357.     result of evaluating the argument falseAlternativeBlock. If the receiver 
  4358.     is a nonBoolean then create an error notification. Execution does not 
  4359.     actually reach here because the expression is compiled in-line."
  4360.  
  4361.     self subclassResponsibility!
  4362. or: alternativeBlock 
  4363.     "Nonevaluating disjunction. If the receiver is false, answer the value of 
  4364.     the argument, alternativeBlock; otherwise answer true without 
  4365.     evaluating the argument."
  4366.  
  4367.     self subclassResponsibility! !
  4368.  
  4369. !Boolean methodsFor: 'copying'!
  4370. deepCopy 
  4371.     "Receiver has two concrete subclasses, True and False.
  4372.     Only one instance of each should be made, so return self."!
  4373. forRom
  4374.     "A 'primitive type' for ToolBox traps"!
  4375. shallowCopy 
  4376.     "Receiver has two concrete subclasses, True and False.
  4377.     Only one instance of each should be made, so return self."! !
  4378.  
  4379. !Boolean methodsFor: 'printing'!
  4380. storeOn: aStream 
  4381.     "Refer to the comment in Object|storeOn:."
  4382.  
  4383.     self printOn: aStream! !
  4384. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  4385.  
  4386. Boolean class
  4387.     instanceVariableNames: ''!
  4388.  
  4389. !Boolean class methodsFor: 'instance creation'!
  4390. new
  4391.     self error: 'You may not create any more Booleans - this is two-valued logic'! !Object subclass: #BraceConstructor
  4392.     instanceVariableNames: 'elements initIndex subBraceSize constructor decompiler '
  4393.     classVariableNames: ''
  4394.     poolDictionaries: ''
  4395.     category: 'System-Compiler'!
  4396.  
  4397. !BraceConstructor methodsFor: 'constructing'!
  4398. codeBrace: numElements fromBytes: aDecompiler withConstructor: aConstructor
  4399.     "Decompile.  Consume at least a Pop and usually several stores into variables
  4400.      or braces.  See BraceNode<formBrace for details."
  4401.  
  4402.     decompiler _ aDecompiler.
  4403.     constructor _ aConstructor.
  4404.     elements _ Array new: (initIndex _ numElements).
  4405.     [decompiler interpretNextInstructionFor: self.
  4406.      initIndex = 0]
  4407.         whileFalse: [].
  4408.     ^constructor codeBrace: elements! !
  4409.  
  4410. !BraceConstructor methodsFor: 'instruction decoding'!
  4411. doPop
  4412.     "Decompile."!
  4413. popIntoLiteralVariable: association
  4414.     "Decompile."
  4415.  
  4416.     elements at: initIndex put: (constructor codeAnyLitInd: association).
  4417.     initIndex _ initIndex - 1!
  4418. popIntoReceiverVariable: offset
  4419.     "Decompile."
  4420.  
  4421.     elements at: initIndex put: (constructor codeInst: offset).
  4422.     initIndex _ initIndex - 1!
  4423. popIntoTemporaryVariable: offset
  4424.     "Decompile."
  4425.  
  4426.     elements at: initIndex put: (decompiler tempAt: offset).
  4427.     initIndex _ initIndex - 1!
  4428. pushConstant: value
  4429.  
  4430.     subBraceSize _ value!
  4431. send: selector super: superFlag numArgs: numArgs
  4432.  
  4433.     selector == #toBraceStack:
  4434.         ifFalse: [self error: 'Malformed brace-variable code'].
  4435.     elements at: initIndex put:
  4436.         (BraceConstructor new
  4437.             codeBrace: subBraceSize
  4438.             fromBytes: decompiler
  4439.             withConstructor: constructor).
  4440.     initIndex _ initIndex - 1! !
  4441. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  4442.  
  4443. BraceConstructor class
  4444.     instanceVariableNames: ''!
  4445.  
  4446. !BraceConstructor class methodsFor: 'examples'!
  4447. example
  4448.     "Test the {a. b. c} syntax.  For more examples, see SequenceableCollection-casing
  4449.      and Dictionary-casing."
  4450.  
  4451.     | a b c d e x y |
  4452.     x _ {1. {2. 3}. 4}.
  4453.     {a. {b. c}. d. e} _ x, {5}, {}.
  4454.     y _ {a} _ {0}.
  4455.     {} _ {}.
  4456.     ^{e. d. c. b. a + 1. y first} as: Set
  4457.  
  4458. "BraceNode example"
  4459. "Smalltalk garbageCollect.
  4460.  Time millisecondsToRun: [20 timesRepeat: [BraceNode example]] 1097 2452"! !ParseNode subclass: #BraceNode
  4461.     instanceVariableNames: 'elements sourceLocations collClassNode nElementsNode fromBraceStackNode toBraceStackNode withNode '
  4462.     classVariableNames: ''
  4463.     poolDictionaries: ''
  4464.     category: 'System-Compiler'!
  4465.  
  4466. !BraceNode methodsFor: 'initialize-release'!
  4467. collClass: aParseNode
  4468.  
  4469.     collClassNode _ aParseNode!
  4470. elements: collection
  4471.     "Decompile."
  4472.  
  4473.     elements _ collection!
  4474. elements: collection sourceLocations: locations
  4475.     "Compile."
  4476.  
  4477.     elements _ collection.
  4478.     sourceLocations _ locations! !
  4479.  
  4480. !BraceNode methodsFor: 'testing'!
  4481. assignmentCheck: encoder at: location
  4482.  
  4483.     | loc |
  4484.     elements do:
  4485.         [:element |
  4486.         (loc _ element assignmentCheck: encoder at: location) >= 0 ifTrue: [^loc]].
  4487.     ^-1!
  4488. blockAssociationCheck: encoder
  4489.     "If all elements are MessageNodes of the form [block]->[block], and there is at
  4490.      least one element, answer true.
  4491.      Otherwise, notify encoder of an error."
  4492.  
  4493.     elements size = 0
  4494.         ifTrue: [^encoder notify: 'At least one case required'].
  4495.     elements with: sourceLocations do:
  4496.             [:x :loc |
  4497.             (x     isMessage: #->
  4498.                 receiver:
  4499.                     [:rcvr |
  4500.                     (rcvr isKindOf: BlockNode) and: [rcvr numberOfArguments = 0]]
  4501.                 arguments:
  4502.                     [:arg |
  4503.                     (arg isKindOf: BlockNode) and: [arg numberOfArguments = 0]])
  4504.               ifFalse:
  4505.                 [^encoder notify: 'Association between 0-argument blocks required' at: loc]].
  4506.     ^true!
  4507. numElements
  4508.  
  4509.     ^ elements size! !
  4510.  
  4511. !BraceNode methodsFor: 'code generation'!
  4512. emitForValue: stack on: aStream
  4513.     "elem1, ..., elemN, collectionClass, N, fromBraceStack:"
  4514.  
  4515.     | element |
  4516.     elements do: [:element | element emitForValue: stack on: aStream].
  4517.     collClassNode emitForValue: stack on: aStream.
  4518.     nElementsNode emitForValue: stack on: aStream.
  4519.     fromBraceStackNode emit: stack args: 1 on: aStream.
  4520.     stack pop: elements size!
  4521. emitStore: stack on: aStream
  4522.  
  4523.     aStream nextPut: Dup. stack push: 1.
  4524.     self emitStorePop: stack on: aStream!
  4525. emitStorePop: stack on: aStream
  4526.     "N, toBraceStack:, pop, pop elemN, ..., pop elem1"
  4527.  
  4528.     nElementsNode emitForValue: stack on: aStream.
  4529.     toBraceStackNode emit: stack args: 1 on: aStream.
  4530.     stack push: elements size.
  4531.     aStream nextPut: Pop. stack pop: 1.
  4532.     elements reverseDo: [:element | element emitStorePop: stack on: aStream]!
  4533. sizeForStore: encoder
  4534.  
  4535.     ^1 + (self sizeForStorePop: encoder)!
  4536. sizeForStorePop: encoder
  4537.     "N, toBraceStack:, pop, pop elemN, ..., pop elem1"
  4538.  
  4539.     nElementsNode _ encoder encodeLiteral: elements size.
  4540.     toBraceStackNode _ encoder encodeSelector: #toBraceStack:.
  4541.     ^elements inject:
  4542.         (nElementsNode sizeForValue: encoder) +
  4543.         (toBraceStackNode size: encoder args: 1 super: false) + 1 into:
  4544.             [:subTotal :element |
  4545.              subTotal + (element sizeForStorePop: encoder)]!
  4546. sizeForValue: encoder
  4547.     "elem1, ..., elemN, collectionClass, N, fromBraceStack:"
  4548.  
  4549.     nElementsNode _ encoder encodeLiteral: elements size.
  4550.     collClassNode isNil ifTrue:
  4551.         [collClassNode _ encoder encodeVariable: #Array].
  4552.     fromBraceStackNode _ encoder encodeSelector: #fromBraceStack:.
  4553.     ^elements inject:
  4554.         (nElementsNode sizeForValue: encoder) +
  4555.         (collClassNode sizeForValue: encoder) +
  4556.         (fromBraceStackNode size: encoder args: 1 super: false)
  4557.      into:
  4558.         [:subTotal :element |
  4559.          subTotal + (element sizeForValue: encoder)]! !
  4560.  
  4561. !BraceNode methodsFor: 'enumerating'!
  4562. casesForwardDo: aBlock
  4563.     "For each case in forward order, evaluate aBlock with three arguments:
  4564.      the key block, the value block, and whether it is the last case."
  4565.  
  4566.     | numCases case |
  4567.     1 to: (numCases _ elements size) do:
  4568.         [:i |
  4569.         case _ elements at: i.
  4570.         aBlock value: case receiver value: case arguments first value: i=numCases]!
  4571. casesReverseDo: aBlock
  4572.     "For each case in reverse order, evaluate aBlock with three arguments:
  4573.      the key block, the value block, and whether it is the last case."
  4574.  
  4575.     | numCases case |
  4576.     (numCases _ elements size) to: 1 by: -1 do:
  4577.         [:i |
  4578.         case _ elements at: i.
  4579.         aBlock value: case receiver value: case arguments first value: i=numCases]!
  4580. do: aBlock
  4581.     "For each element in order, evaluate aBlock with two arguments: the element,
  4582.      and whether it is the last element."
  4583.  
  4584.     | numElements |
  4585.     1 to: (numElements _ elements size) do:
  4586.         [:i | aBlock value: (elements at: i) value: i=numElements]!
  4587. reverseDo: aBlock
  4588.     "For each element in reverse order, evaluate aBlock with two arguments: the element,
  4589.      and whether it is the last element."
  4590.  
  4591.     | numElements |
  4592.     (numElements _ elements size) to: 1 by: -1 do:
  4593.         [:i | aBlock value: (elements at: i) value: i=numElements]! !
  4594.  
  4595. !BraceNode methodsFor: 'printing'!
  4596. printOn: aStream indent: level
  4597.  
  4598.     | shown |
  4599.     aStream nextPut: ${.
  4600.     shown _ elements size.
  4601.     1 to: shown do: 
  4602.         [:i | 
  4603.         (elements at: i) printOn: aStream indent: level.
  4604.         i < shown ifTrue: [aStream nextPut: $.; space]].
  4605.     aStream nextPut: $}! !
  4606. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  4607.  
  4608. BraceNode class
  4609.     instanceVariableNames: ''!
  4610.  
  4611. !BraceNode class methodsFor: 'examples'!
  4612. example
  4613.     "Test the {a. b. c} syntax."
  4614.  
  4615.     | a b c d e x y |
  4616.     x _ {1. {2. 3}. 4}.
  4617.     {a. {b. c}. d. e} _ x, {5}, {}.
  4618.     y _ {a} _ {0}.
  4619.     {} _ {}.
  4620.     ^{e. d. c. b. a + 1. y first} as: Set
  4621.  
  4622. "BraceNode example"
  4623. "Smalltalk garbageCollect.
  4624.  Time millisecondsToRun: [20 timesRepeat: [BraceNode example]] 1097 2452"! !StringHolder subclass: #Browser
  4625.     instanceVariableNames: 'systemOrganizer classOrganizer metaClassOrganizer systemCategoryListIndex classListIndex messageCategoryListIndex messageListIndex editSelection metaClassIndicated '
  4626.     classVariableNames: 'PostOpenSuggestion '
  4627.     poolDictionaries: ''
  4628.     category: 'Interface-Browser'!
  4629. Browser comment:
  4630. 'I represent a query path into the class descriptions, the software of the system.'!
  4631.  
  4632. !Browser methodsFor: 'initialize-release'!
  4633. browserWindowActivated
  4634.     "Called when a window whose model is the receiver is reactivated, giving the receiver an opportunity to take steps if it wishes.  The default is to do nothing.  8/5/96 sw"!
  4635. defaultBackgroundColor
  4636.     ^ #lightGreen!
  4637. systemOrganizer: aSystemOrganizer 
  4638.     "Initialize the receiver as a perspective on the system organizer, 
  4639.     aSystemOrganizer. Typically there is only one--the system variable 
  4640.     SystemOrganization."
  4641.  
  4642.     super initialize.
  4643.     contents _ nil.
  4644.     systemOrganizer _ aSystemOrganizer.
  4645.     systemCategoryListIndex _ 0.
  4646.     classListIndex _ 0.
  4647.     messageCategoryListIndex _ 0.
  4648.     messageListIndex _ 0.
  4649.     metaClassIndicated _ false.
  4650.     self setClassOrganizer.
  4651.     editSelection _ #none! !
  4652.  
  4653. !Browser methodsFor: 'accessing'!
  4654. contents
  4655.     "Depending on the current selection, different information is retrieved.
  4656.     Answer a string description of that information. This information is the
  4657.     method of the currently selected class and message."
  4658.  
  4659.     editSelection == #none ifTrue: [^''].
  4660.     editSelection == #editSystemCategories 
  4661.         ifTrue: [^systemOrganizer printString].
  4662.     editSelection == #newClass 
  4663.         ifTrue: [^Class template: self selectedSystemCategoryName].
  4664.     editSelection == #editClass 
  4665.         ifTrue: [^self selectedClassOrMetaClass definition].
  4666.     editSelection == #editComment 
  4667.         ifTrue: [^self selectedClassOrMetaClass commentTemplate].
  4668.     editSelection == #hierarchy 
  4669.         ifTrue: [^self selectedClassOrMetaClass printHierarchy].
  4670.     editSelection == #editMessageCategories 
  4671.         ifTrue: [^self classOrMetaClassOrganizer printString].
  4672.     editSelection == #newMessage ifTrue: [^self selectedClassOrMetaClass sourceCodeTemplate].
  4673.     editSelection == #editMessage ifTrue: [^self selectedMessage].
  4674.     self error: 'Browser internal error: unknown edit selection.'!
  4675. contents: input notifying: aController 
  4676.     "The retrieved information has changed and its source must now be 
  4677.     updated. The information can be a variety of things, depending on the 
  4678.     list selections (such as templates for class or message definition, methods) 
  4679.     or the user menu commands (such as definition, comment, hierarchy). 
  4680.     Answer the result of updating the source."
  4681.     | aString aText |
  4682.     aString _ input asString.
  4683.     aText _ input asText.
  4684.  
  4685.     editSelection == #editSystemCategories 
  4686.         ifTrue: [^self changeSystemCategories: aString].
  4687.     editSelection == #editClass | (editSelection == #newClass) 
  4688.         ifTrue: [^self defineClass: aString notifying: aController].
  4689.     editSelection == #editComment 
  4690.         ifTrue: [^self defineComment: aString notifying: aController].
  4691.     editSelection == #hierarchy ifTrue: [^true].
  4692.     editSelection == #editMessageCategories 
  4693.         ifTrue: [^self changeMessageCategories: aString].
  4694.     editSelection == #editMessage | (editSelection == #newMessage) 
  4695.         ifTrue: [^self defineMessage: aText notifying: aController].
  4696.     editSelection == #none ifTrue: [^true].
  4697.     self error: 'unacceptable accept'!
  4698. couldBrowseAnyClass
  4699.     "Answer whether the receiver is equipped to browse any class.  This is in support of the system-brower feature that allows the browser to be redirected at the selected class name.  This implementation is clearly ugly, but the feature it enables is handsome enough.  3/1/96 sw"
  4700.  
  4701.     self dependents detect:
  4702.         [:d | d isKindOf: SystemCategoryListView] ifNone: [^ false].
  4703.     ^ true!
  4704. doItReceiver
  4705.     "This class's classPool has been jimmied to be the classPool of the class being browsed.  A doIt in the code pane will let the user see the value of the class variables."
  4706.     ^ FakeClassPool new!
  4707. editSelection
  4708.     ^editSelection!
  4709. request: prompt initialAnswer: initialAnswer
  4710.     | answer |
  4711.     FillInTheBlank
  4712.         request: prompt
  4713.         displayAt: Sensor cursorPoint
  4714.         centered: true
  4715.         action: [:a | answer _ a] 
  4716.         initialAnswer: initialAnswer.
  4717.     ^ answer
  4718. !
  4719. spawn: aString 
  4720.     "Create and schedule a new browser as though the command browse were 
  4721.     issued with respect to one of the browser's lists. The initial textual 
  4722.     contents is aString, which is the (modified) textual contents of the 
  4723.     receiver."
  4724.  
  4725.     messageListIndex ~= 0 
  4726.         ifTrue: [^self buildMessageBrowserEditString: aString].
  4727.     messageCategoryListIndex ~= 0 
  4728.         ifTrue: [^self buildMessageCategoryBrowserEditString: aString].
  4729.     classListIndex ~= 0 ifTrue: [^self buildClassBrowserEditString: aString].
  4730.     systemCategoryListIndex ~= 0 
  4731.         ifTrue: [^self buildSystemCategoryBrowserEditString: aString].
  4732.     ^BrowserView openBrowserEditString: aString! !
  4733.  
  4734. !Browser methodsFor: 'system category list'!
  4735. selectedSystemCategoryName
  4736.     "Answer the name of the selected system category or nil."
  4737.  
  4738.     systemCategoryListIndex = 0 ifTrue: [^nil].
  4739.     ^self systemCategoryList at: systemCategoryListIndex!
  4740. systemCategoryList
  4741.     "Answer the class categories modelled by the receiver."
  4742.  
  4743.     ^systemOrganizer categories!
  4744. systemCategoryListIndex
  4745.     "Answer the index of the selected class category."
  4746.  
  4747.     ^systemCategoryListIndex!
  4748. systemCategoryListIndex: anInteger 
  4749.     "Set the selected system category index to be anInteger. Update all other 
  4750.     selections to be deselected."
  4751.  
  4752.     systemCategoryListIndex _ anInteger.
  4753.     classListIndex _ 0.
  4754.     messageCategoryListIndex _ 0.
  4755.     messageListIndex _ 0.
  4756.     editSelection _ 
  4757.         anInteger = 0
  4758.                 ifTrue: [#none]
  4759.                 ifFalse: [#newClass].
  4760.     metaClassIndicated _ false.
  4761.     self setClassOrganizer.
  4762.     contents _ nil.
  4763.     self changed: #systemCategorySelectionChanged!
  4764. toggleSystemCategoryListIndex: anInteger 
  4765.     "If anInteger is the current system category index, deselect it. Else make 
  4766.     it the current system category selection."
  4767.  
  4768.     self systemCategoryListIndex: 
  4769.         (systemCategoryListIndex = anInteger
  4770.             ifTrue: [0]
  4771.             ifFalse: [anInteger])! !
  4772.  
  4773. !Browser methodsFor: 'system category functions'!
  4774. addSystemCategory
  4775.     "Prompt for a new category name and add it before the
  4776.     current selection, or at the end if no current selection"
  4777.     | oldIndex newName |
  4778.     self okToChange ifFalse: [^ self].
  4779.     oldIndex _ systemCategoryListIndex.
  4780.     newName _ self
  4781.         request: 'Please type new category name'
  4782.         initialAnswer: 'Category-Name'.
  4783.     newName isEmpty
  4784.         ifTrue: [^ self]
  4785.         ifFalse: [newName _ newName asSymbol].
  4786.     systemOrganizer
  4787.         addCategory: newName
  4788.         before: (systemCategoryListIndex = 0
  4789.                 ifTrue: [nil]
  4790.                 ifFalse: [self selectedSystemCategoryName]).
  4791.     self changed: #systemCategoriesChanged.
  4792.     self systemCategoryListIndex:
  4793.         (oldIndex = 0
  4794.             ifTrue: [systemOrganizer categories size]
  4795.             ifFalse: [oldIndex])!
  4796. buildSystemCategoryBrowser
  4797.     "Create and schedule a new system category browser."
  4798.  
  4799.     self buildSystemCategoryBrowserEditString: nil!
  4800. buildSystemCategoryBrowserEditString: aString 
  4801.     "Create and schedule a new system category browser with initial textual 
  4802.     contents set to aString."
  4803.  
  4804.     | newBrowser |
  4805.     systemCategoryListIndex > 0
  4806.         ifTrue: 
  4807.             [newBrowser _ Browser new.
  4808.             newBrowser systemCategoryListIndex: systemCategoryListIndex.
  4809.             BrowserView openSystemCategoryBrowser: newBrowser editString: aString]!
  4810. changeSystemCategories: aString 
  4811.     "Update the class categories by parsing the argument aString."
  4812.  
  4813.     systemOrganizer changeFromString: aString.
  4814.     self systemCategoryListIndex: 0.
  4815.     self changed: #systemCategoriesChanged.
  4816.     ^true!
  4817. editSystemCategories
  4818.     "Retrieve the description of the class categories of the system organizer."
  4819.  
  4820.     self okToChange ifFalse: [^ self].
  4821.     self systemCategoryListIndex: 0.
  4822.     editSelection _ #editSystemCategories.
  4823.     self changed: #editSystemCategories!
  4824. fileOutSystemCategories
  4825.     "Print a description of each class in the selected category onto a file 
  4826.     whose name is the category name followed by .st."
  4827.  
  4828.     systemCategoryListIndex ~= 0
  4829.         ifTrue: [systemOrganizer fileOutCategory: self selectedSystemCategoryName]!
  4830. removeSystemCategory
  4831.     "If a class category is selected, create a Confirmer so the user can 
  4832.     verify that the currently selected class category and all of its classes
  4833.      should be removed from the system. If so, remove it."
  4834.  
  4835.     | classCategoryName |
  4836.     systemCategoryListIndex = 0 ifTrue: [^ self].
  4837.     self okToChange ifFalse: [^ self].
  4838.     (self classList size = 0
  4839.         or: [self confirm: 'Are you sure you want to
  4840. remove this system category 
  4841. and all its classes?'])
  4842.         ifTrue: 
  4843.         [systemOrganizer removeSystemCategory: self selectedSystemCategoryName.
  4844.         self systemCategoryListIndex: 0.
  4845.         self changed: #systemCategoriesChanged]!
  4846. renameSystemCategory
  4847.     "Prompt for a new category name and add it before the
  4848.     current selection, or at the end if no current selection"
  4849.     | oldIndex oldName newName |
  4850.     (oldIndex _ systemCategoryListIndex) = 0
  4851.         ifTrue: [^ self].  "no selection"
  4852.     self okToChange ifFalse: [^ self].
  4853.     oldName _ self selectedSystemCategoryName.
  4854.     newName _ self
  4855.         request: 'Please type new category name'
  4856.         initialAnswer: oldName.
  4857.     newName isEmpty
  4858.         ifTrue: [^ self]
  4859.         ifFalse: [newName _ newName asSymbol].
  4860.     oldName = newName ifTrue: [^ self].
  4861.     systemOrganizer
  4862.         renameCategory: oldName
  4863.         toBe: newName.
  4864.     self changed: #systemCategoriesChanged.
  4865.     self systemCategoryListIndex: oldIndex!
  4866. updateSystemCategories
  4867.     "The class categories were changed in another browser. The receiver must 
  4868.     reorganize its lists based on these changes."
  4869.  
  4870.     self okToChange ifFalse: [^ self].
  4871.     self systemCategoryListIndex: 0.
  4872.     self changed: #systemCategoriesChanged! !
  4873.  
  4874. !Browser methodsFor: 'class list'!
  4875. classList
  4876.     "Answer an array of the class names of the selected category. Answer an 
  4877.     empty array if no selection exists."
  4878.  
  4879.     systemCategoryListIndex = 0
  4880.         ifTrue: [^Array new]
  4881.         ifFalse: [^systemOrganizer listAtCategoryNumber: systemCategoryListIndex]!
  4882. classListIndex
  4883.     "Answer the index of the current class selection."
  4884.  
  4885.     ^classListIndex!
  4886. classListIndex: anInteger 
  4887.     "Set anInteger to be the index of the current class selection."
  4888.     classListIndex _ anInteger.
  4889.     self setClassOrganizer.
  4890.     messageCategoryListIndex _ 0.
  4891.     messageListIndex _ 0.
  4892.     editSelection _ anInteger = 0
  4893.             ifTrue: [metaClassIndicated
  4894.                 ifTrue: [#none]
  4895.                 ifFalse: [#newClass]]
  4896.             ifFalse: [#editClass].
  4897.     contents _ nil.
  4898.     self changed: #classSelectionChanged!
  4899. selectedClass
  4900.     "Answer the class that is currently selected. Answer nil if no selection 
  4901.     exists."
  4902.  
  4903.     self selectedClassName == nil ifTrue: [^nil].
  4904.     ^Smalltalk at: self selectedClassName!
  4905. selectedClassName
  4906.     "Answer the name of the current class. Answer nil if no selection exists."
  4907.  
  4908.     classListIndex = 0 ifTrue: [^nil].
  4909.     ^self classList at: classListIndex!
  4910. toggleClassListIndex: anInteger 
  4911.     "If anInteger is the current class index, deselect it. Else make it the 
  4912.     current class selection."
  4913.  
  4914.     self classListIndex: 
  4915.         (classListIndex = anInteger
  4916.             ifTrue: [0]
  4917.             ifFalse: [anInteger])! !
  4918.  
  4919. !Browser methodsFor: 'class functions'!
  4920. browseClassRefs
  4921.  
  4922.     classListIndex=0 ifTrue: [^ self].
  4923.     Smalltalk browseAllCallsOn: (Smalltalk associationAt: self selectedClass name)
  4924. !
  4925. browseClassVariables
  4926.     "Browse the class varialbes of the selected class.  2/5/96 sw"
  4927.  
  4928.     classListIndex = 0 ifTrue: [^ self].
  4929.     self selectedClass browseClassVariables!
  4930. browseClassVarRefs
  4931.     "1/17/96 sw: devolve responsibility to the class, so that the code that does the real work can be shared"
  4932.  
  4933.     classListIndex=0 ifTrue: [^ self].
  4934.     self selectedClass browseClassVarRefs!
  4935. browseInstVarDefs 
  4936.  
  4937.     classListIndex = 0 ifTrue: [^ self].
  4938.     self selectedClassOrMetaClass browseInstVarDefs!
  4939. browseInstVarRefs 
  4940.     "1/26/96 sw: real work moved to class, so it can be shared"
  4941.  
  4942.     classListIndex = 0 ifTrue: [^ self].
  4943.     self selectedClassOrMetaClass browseInstVarRefs!
  4944. buildClassBrowser
  4945.     "Create and schedule a new class category browser for the current class 
  4946.     selection, if one exists."
  4947.  
  4948.     self buildClassBrowserEditString: nil!
  4949. buildClassBrowserEditString: aString 
  4950.     "Create and schedule a new class browser for the current selection, if one 
  4951.     exists, with initial textual contents set to aString."
  4952.  
  4953.     | newBrowser myClass |
  4954.     classListIndex ~= 0 ifTrue: 
  4955.         [newBrowser _ Browser new.
  4956.         newBrowser systemCategoryListIndex: systemCategoryListIndex.
  4957.         newBrowser classListIndex: classListIndex.
  4958.         newBrowser metaClassIndicated: metaClassIndicated.
  4959.  
  4960.         myClass _ self selectedClassOrMetaClass.
  4961.         myClass notNil ifTrue: [
  4962.             Browser postOpenSuggestion: 
  4963.                 (Array with: myClass with: self selectedMessageName)].
  4964.  
  4965.         BrowserView openClassBrowser: newBrowser editString: aString label: 'Class Browser: ', myClass name]!
  4966. defineClass: aString notifying: aController 
  4967.     "The receiver's textual content is a request to define a new class. The 
  4968.     source code is aString. If any errors occur in compilation, notify 
  4969.     aController."
  4970.  
  4971.     | oldClass class |
  4972.     oldClass _ self selectedClassOrMetaClass.
  4973.     oldClass isNil ifTrue: [oldClass _ Object].
  4974.     class _ oldClass subclassDefinerClass
  4975.                 evaluate: aString
  4976.                 notifying: aController
  4977.                 logged: true.
  4978.     (class isKindOf: Behavior)
  4979.         ifTrue: 
  4980.             [self changed: #classListChanged.
  4981.             self classListIndex: 
  4982.                 (self classList indexOf: 
  4983.                     ((class isKindOf: Metaclass)
  4984.                         ifTrue: [class soleInstance name]
  4985.                         ifFalse: [class name])).
  4986.             self unlock; editClass.
  4987.             ^true]
  4988.         ifFalse: [^false]!
  4989. defineComment: aString notifying: aController 
  4990.     "The receiver's textual content is a request to define a new comment for 
  4991.     the selected class. The comment is defined by the message expression, 
  4992.     aString. If any errors occur in evaluation, notify aController."
  4993.  
  4994.     | oldClass class |
  4995.     oldClass _ self selectedClassOrMetaClass.
  4996.     oldClass isNil ifTrue: [oldClass _ Object].
  4997.     class _ oldClass evaluatorClass
  4998.                 evaluate: aString
  4999.                 notifying: aController
  5000.                 logged: true.
  5001.     (class isKindOf: Behavior)
  5002.         ifTrue: 
  5003.             [self unlock; editComment. ^true]
  5004.         ifFalse: [^false]!
  5005. editClass
  5006.     "Retrieve the description of the class definition."
  5007.  
  5008.     classListIndex = 0 ifTrue: [^ self].
  5009.     self okToChange ifFalse: [^ self].
  5010.     self messageCategoryListIndex: 0.
  5011.     editSelection _ #editClass.
  5012.     self changed: #editClass!
  5013. editComment
  5014.     "Retrieve the description of the class comment."
  5015.  
  5016.     classListIndex = 0 ifTrue: [^ self].
  5017.     self okToChange ifFalse: [^ self].
  5018.     self messageCategoryListIndex: 0.
  5019.     editSelection _ #editComment.
  5020.     self changed: #editClass!
  5021. explainSpecial: string 
  5022.     "Answer a string explaining the code pane selection if it is displaying 
  5023.     one of the special edit functions."
  5024.  
  5025.     | classes whole lits reply |
  5026.     (editSelection == #editClass or: [editSelection == #newClass])
  5027.         ifTrue: 
  5028.             ["Selector parts in class definition"
  5029.             string last == $: ifFalse: [^nil].
  5030.             lits _ Array with:
  5031.                 #subclass:instanceVariableNames:classVariableNames:poolDictionaries:category:.
  5032.             (whole _ lits detect: [:each | (each keywords
  5033.                     detect: [:frag | frag = string] ifNone: []) ~~ nil]
  5034.                         ifNone: []) ~~ nil
  5035.                 ifTrue: [reply _ '"' , string , ' is one part of the message selector ' , whole , '.']
  5036.                 ifFalse: [^nil].
  5037.             classes _ Smalltalk allClassesImplementing: whole.
  5038.             classes _ 'these classes ' , classes printString.
  5039.             ^reply , '  It is defined in ' , classes , '."
  5040. Smalltalk browseAllImplementorsOf: #' , whole].
  5041.  
  5042.     editSelection == #hierarchy
  5043.         ifTrue: 
  5044.             ["Instance variables in subclasses"
  5045.             classes _ self selectedClassOrMetaClass allSubclasses.
  5046.             classes _ classes detect: [:each | (each instVarNames
  5047.                         detect: [:name | name = string] ifNone: []) ~~ nil]
  5048.                     ifNone: [^nil].
  5049.             classes _ classes printString.
  5050.             ^'"is an instance variable in class ' , classes , '."
  5051. ' , classes , ' browseAllAccessesTo: ''' , string , '''.'].
  5052.     editSelection == #editSystemCategories ifTrue: [^nil].
  5053.     editSelection == #editMessageCategories ifTrue: [^nil].
  5054.     ^nil!
  5055. fileOutClass
  5056.     "Print a description of the selected class onto a file whose name is the 
  5057.     category name followed by .st."
  5058.  
  5059.     classListIndex ~= 0 ifTrue: [self selectedClass fileOut]!
  5060. hierarchy
  5061.     "Retrieve a description of the superclass chain and subclasses of the 
  5062.     selected class."
  5063.  
  5064.     classListIndex = 0 ifTrue: [^ self].
  5065.     self okToChange ifFalse: [^ self].
  5066.     self messageCategoryListIndex: 0.
  5067.     editSelection _ #hierarchy.
  5068.     self changed: #editComment!
  5069. removeClass
  5070.     "The selected class should be removed from the system. Use a Confirmer 
  5071.     to make certain the user intends this irrevocable command to be carried 
  5072.     out."
  5073.     | message class className |
  5074.     classListIndex = 0 ifTrue: [^ self].
  5075.     self okToChange ifFalse: [^ self].
  5076.     class _ self selectedClass.
  5077.     className _ class name.
  5078.     message _ 'Are you certain that you
  5079. want to delete the class ', className, '?'.
  5080.     (self confirm: message) ifTrue: 
  5081.             [class subclasses size > 0
  5082.                 ifTrue: [self notify: 'class has subclasses: ' , message].
  5083.             class removeFromSystem.
  5084.             self classListIndex: 0.
  5085.             self changed: #classListChanged]!
  5086. renameClass
  5087.     | oldName newName obs |
  5088.     classListIndex = 0 ifTrue: [^ self].
  5089.     self okToChange ifFalse: [^ self].
  5090.     oldName _ self selectedClass name.
  5091.     newName _ (self request: 'Please type new class name'
  5092.                         initialAnswer: oldName) asSymbol.
  5093.     newName = oldName ifTrue: [^ self].
  5094.     (Smalltalk includesKey: newName)
  5095.         ifTrue: [^ self error: newName , ' already exists'].
  5096.     self selectedClass rename: newName.
  5097.     self changed: #classListChanged.
  5098.     self classListIndex: ((systemOrganizer listAtCategoryNamed: self selectedSystemCategoryName) indexOf: newName).
  5099.     obs _ Smalltalk allCallsOn: (Smalltalk associationAt: newName).
  5100.     obs isEmpty ifFalse:
  5101.         [Smalltalk browseMessageList: obs
  5102.             name: 'Obsolete References to ' , oldName
  5103.             autoSelect: oldName]! !
  5104.  
  5105. !Browser methodsFor: 'message category list'!
  5106. messageCategoryList
  5107.     "Answer the selected category of messages."
  5108.  
  5109.     classListIndex = 0
  5110.         ifTrue: [^Array new]
  5111.         ifFalse: [^self classOrMetaClassOrganizer categories]!
  5112. messageCategoryListIndex
  5113.     "Answer the index of the selected message category."
  5114.  
  5115.     ^messageCategoryListIndex!
  5116. messageCategoryListIndex: anInteger 
  5117.     "Set the selected message category to be the one indexed by anInteger."
  5118.  
  5119.     messageCategoryListIndex _ anInteger.
  5120.     messageListIndex _ 0.
  5121.     editSelection _ 
  5122.         anInteger = 0
  5123.             ifTrue: [#none]
  5124.             ifFalse: [#newMessage].
  5125.     contents _ nil.
  5126.     self changed: #messageCategorySelectionChanged!
  5127. selectedMessageCategoryName
  5128.     "Answer the name of the selected message category, if any. Answer nil 
  5129.     otherwise."
  5130.  
  5131.     messageCategoryListIndex = 0 ifTrue: [^nil].
  5132.     ^self messageCategoryList at: messageCategoryListIndex!
  5133. toggleMessageCategoryListIndex: anInteger 
  5134.     "If the currently selected message category index is anInteger, deselect 
  5135.     the category. Otherwise select the category whose index is anInteger."
  5136.  
  5137.     self messageCategoryListIndex: 
  5138.         (messageCategoryListIndex = anInteger
  5139.             ifTrue: [0]
  5140.             ifFalse: [anInteger])! !
  5141.  
  5142. !Browser methodsFor: 'message category functions'!
  5143. addCategory
  5144.     "Prompt for a new category name and add it before the
  5145.     current selection, or at the end if no current selection"
  5146.     | oldIndex newName |
  5147.     self okToChange ifFalse: [^ self].
  5148.     classListIndex = 0 ifTrue: [^ self].
  5149.     oldIndex _ messageCategoryListIndex.
  5150.     newName _ self
  5151.         request: 'Please type new category name'
  5152.         initialAnswer: 'category name'.
  5153.     newName isEmpty
  5154.         ifTrue: [^ self]
  5155.         ifFalse: [newName _ newName asSymbol].
  5156.     self classOrMetaClassOrganizer
  5157.         addCategory: newName
  5158.         before: (messageCategoryListIndex = 0
  5159.                 ifTrue: [nil]
  5160.                 ifFalse: [self selectedMessageCategoryName]).
  5161.     self changed: #classSelectionChanged.
  5162.     self messageCategoryListIndex:
  5163.         (oldIndex = 0
  5164.             ifTrue: [self selectedClass organization categories size]
  5165.             ifFalse: [oldIndex])!
  5166. buildMessageCategoryBrowser
  5167.     "Create and schedule a message category browser for the currently 
  5168.     selected message category."
  5169.  
  5170.     self buildMessageCategoryBrowserEditString: nil!
  5171. buildMessageCategoryBrowserEditString: aString 
  5172.     "Create and schedule a message category browser for the currently 
  5173.     selected     message category. The initial text view contains the characters 
  5174.     in aString."
  5175.  
  5176.     | newBrowser |
  5177.     messageCategoryListIndex ~= 0
  5178.         ifTrue: 
  5179.             [newBrowser _ Browser new.
  5180.             newBrowser systemCategoryListIndex: systemCategoryListIndex.
  5181.             newBrowser classListIndex: classListIndex.
  5182.             newBrowser metaClassIndicated: metaClassIndicated.
  5183.             newBrowser messageCategoryListIndex: messageCategoryListIndex.
  5184.             BrowserView openMessageCategoryBrowser: newBrowser editString: aString]!
  5185. changeMessageCategories: aString 
  5186.     "The characters in aString represent an edited version of the the message 
  5187.     categories for the selected class. Update this information in the system 
  5188.     and inform any dependents that the categories have been changed. This 
  5189.     message is invoked because the user had issued the categories command 
  5190.     and edited the message categories. Then the user issued the accept 
  5191.     command."
  5192.  
  5193.     self classOrMetaClassOrganizer changeFromString: aString.
  5194.     Smalltalk changes reorganizeClass: self selectedClassOrMetaClass.
  5195.     self unlock.
  5196.     self editClass.
  5197.     self classListIndex: classListIndex.
  5198.     ^ true!
  5199. editMessageCategories
  5200.     "Indicate to the receiver and its dependents that the message categories of 
  5201.     the selected class have been changed."
  5202.  
  5203.     self okToChange ifFalse: [^ self].
  5204.     classListIndex ~= 0
  5205.         ifTrue: 
  5206.             [self messageCategoryListIndex: 0.
  5207.             editSelection _ #editMessageCategories.
  5208.             self changed: #editMessageCategories]!
  5209. fileOutMessageCategories
  5210.     "Print a description of the selected message category of the selected class 
  5211.     onto an external file."
  5212.  
  5213.     messageCategoryListIndex ~= 0
  5214.         ifTrue: 
  5215.             [self selectedClassOrMetaClass fileOutCategory: self selectedMessageCategoryName]!
  5216. removeMessageCategory
  5217.     "If a message category is selected, create a Confirmer so the user can 
  5218.     verify that the currently selected message category should be removed
  5219.      from the system. If so, remove it."
  5220.  
  5221.     | warning messageCategoryName |
  5222.     messageCategoryListIndex = 0 ifTrue: [^ self].
  5223.     self okToChange ifFalse: [^ self].
  5224.     messageCategoryName _ self selectedMessageCategoryName.
  5225.     (self messageList size = 0
  5226.         or: [self confirm: 'Are you sure you want to
  5227. remove this method category 
  5228. and all its methods?'])
  5229.         ifTrue: 
  5230.             [self selectedClassOrMetaClass removeCategory: messageCategoryName.
  5231.             self messageCategoryListIndex: 0.
  5232.             self changed: #classSelectionChanged]!
  5233. renameCategory
  5234.     "Prompt for a new category name and add it before the
  5235.     current selection, or at the end if no current selection"
  5236.     | oldIndex oldName newName |
  5237.     classListIndex = 0 ifTrue: [^ self].
  5238.     self okToChange ifFalse: [^ self].
  5239.     (oldIndex _ messageCategoryListIndex) = 0 ifTrue: [^ self].
  5240.     oldName _ self selectedMessageCategoryName.
  5241.     newName _ self
  5242.         request: 'Please type new category name'
  5243.         initialAnswer: oldName.
  5244.     newName isEmpty
  5245.         ifTrue: [^ self]
  5246.         ifFalse: [newName _ newName asSymbol].
  5247.     newName = oldName ifTrue: [^ self].
  5248.     self classOrMetaClassOrganizer
  5249.         renameCategory: oldName
  5250.         toBe: newName.
  5251.     Smalltalk changes reorganizeClass: self selectedClassOrMetaClass.
  5252.     self classListIndex: classListIndex.
  5253.     self messageCategoryListIndex: oldIndex! !
  5254.  
  5255. !Browser methodsFor: 'message list'!
  5256. messageList
  5257.     "Answer an Array of the message selectors of the currently selected 
  5258.     message category. Otherwise, answer a new empty Array."
  5259.  
  5260.     messageCategoryListIndex = 0
  5261.         ifTrue: [^Array new]
  5262.         ifFalse: [^self classOrMetaClassOrganizer 
  5263.                     listAtCategoryNumber: messageCategoryListIndex]!
  5264. messageListIndex
  5265.     "Answer the index of the selected message selector into the currently 
  5266.     selected message category."
  5267.  
  5268.     ^messageListIndex!
  5269. messageListIndex: anInteger 
  5270.     "Set the selected message selector to be the one indexed by anInteger."
  5271.  
  5272.     messageListIndex _ anInteger.
  5273.     editSelection _ 
  5274.         anInteger = 0
  5275.             ifTrue: [#newMessage]
  5276.             ifFalse: [#editMessage].
  5277.     contents _ nil.
  5278.     self changed: #messageSelectionChanged!
  5279. selectedMessage
  5280.     "Answer a copy of the source code for the selected message selector."
  5281.  
  5282.     contents == nil 
  5283.         ifTrue: [contents _ 
  5284.                     self selectedClassOrMetaClass 
  5285.                         sourceCodeAt: self selectedMessageName].
  5286.     ^contents copy!
  5287. selectedMessageName
  5288.     "Answer the message selector of the currently selected message, if any. 
  5289.     Answer nil otherwise."
  5290.  
  5291.     messageListIndex = 0 ifTrue: [^nil].
  5292.     ^self messageList at: messageListIndex!
  5293. toggleMessageListIndex: anInteger 
  5294.     "If the currently selected message index is anInteger, deselect the message 
  5295.     selector. Otherwise select the message selector whose index is anInteger."
  5296.  
  5297.     self messageListIndex: 
  5298.         (messageListIndex = anInteger
  5299.             ifTrue: [0]
  5300.             ifFalse: [anInteger])! !
  5301.  
  5302. !Browser methodsFor: 'message functions'!
  5303. browseAllMessages
  5304.     "Create and schedule a message set browser on all implementors of all
  5305.     the messages sent by the current method.  Created 1991 by tck;
  5306.     mofified 1/26/96 sw: put appropriate title on the window"
  5307.  
  5308.     | aClass aName |
  5309.     messageListIndex ~= 0 
  5310.         ifTrue: [Smalltalk browseAllImplementorsOfList:
  5311.                 ((aClass _ self selectedClassOrMetaClass) compiledMethodAt: (aName _ self selectedMessageName))
  5312.                     messages asSortedCollection title:
  5313.         'All messages sent in ', aClass name, '.', aName]!
  5314. browseImplementors
  5315.     "Create and schedule a message set browser on all implementors of the 
  5316.     currently selected message selector. Do nothing if no message is selected."
  5317.  
  5318.     messageListIndex ~= 0 
  5319.         ifTrue: [Smalltalk browseAllImplementorsOf: self selectedMessageName]!
  5320. browseMessages
  5321.     "Show a menu of all messages sent by the currently selected message. 
  5322.     Create and schedule a message set browser of all implementors of the 
  5323.     message chosen. Do nothing if no message is chosen."
  5324.  
  5325.     messageListIndex = 0 ifTrue: [^self].
  5326.     Smalltalk showMenuThenBrowse:
  5327.         (self selectedClassOrMetaClass compiledMethodAt: self selectedMessageName)
  5328.             messages asSortedCollection!
  5329. browseSenders
  5330.     "Create and schedule a message set browser on all methods in which the 
  5331.     currently selected message selector is sent. Do nothing if no message is 
  5332.     selected."
  5333.  
  5334.     messageListIndex ~= 0 
  5335.         ifTrue: [Smalltalk browseAllCallsOn: self selectedMessageName]!
  5336. browseSendersOfMessages
  5337.     "Show a menu of all messages sent by the currently selected message. 
  5338.     Create and schedule a message set browser of all implementors of the 
  5339.     message chosen. Do nothing if no message is chosen."
  5340.  
  5341.     messageListIndex = 0 ifTrue: [^self].
  5342.     Smalltalk showMenuThenBrowseSendersOf:
  5343.         (self selectedClassOrMetaClass compiledMethodAt: self selectedMessageName)
  5344.             messages asSortedCollection!
  5345. browseVersions
  5346.     "Create and schedule a message set browser on all versions of the 
  5347.     currently selected message selector."
  5348.     | class selector |
  5349.     messageListIndex ~= 0 ifTrue:
  5350.         [class _ self selectedClassOrMetaClass.
  5351.         selector _ self selectedMessageName.
  5352.         ChangeList
  5353.             browseVersionsOf: (class compiledMethodAt: selector)
  5354.             class: self selectedClass
  5355.             meta: self metaClassIndicated
  5356.             category: self selectedMessageCategoryName
  5357.             selector: selector]!
  5358. buildMessageBrowser
  5359.     "Create and schedule a message browser on the currently selected 
  5360.     message. Do nothing if no message is selected. The initial text view 
  5361.     contains nothing."
  5362.  
  5363.     self buildMessageBrowserEditString: nil!
  5364. buildMessageBrowserEditString: aString 
  5365.     "Create and schedule a message browser for the receiver in which the 
  5366.     argument, aString, contains characters to be edited in the text view."
  5367.  
  5368.     messageListIndex = 0 ifTrue: [^ self].
  5369.     ^ BrowserView
  5370.         openMessageBrowserForClass: self selectedClassOrMetaClass
  5371.         selector: self selectedMessageName
  5372.         editString: aString!
  5373. defineMessage: aString notifying: aController 
  5374.     "Compile the expressions in aString. Notify aController if a syntax error 
  5375.     occurs. Install the compiled method in the selected class classified under 
  5376.     the currently selected message category name. Answer true if 
  5377.     compilation succeeds, false otherwise."
  5378.  
  5379.     | selectedMessageName selector category oldMessageList notice |
  5380.     selectedMessageName _ self selectedMessageName.
  5381.     oldMessageList _ self messageList.
  5382.     contents _ nil.
  5383.     selector _ 
  5384.         self selectedClassOrMetaClass
  5385.                 compile: aString
  5386.                 classified: (category _ self selectedMessageCategoryName)
  5387.                 notifying: aController.
  5388.     notice _ self selectedClassOrMetaClass checkForPerform: selector in: aController.
  5389.     selector == nil ifTrue: [^false].
  5390.     contents _ aString copy.
  5391.     selector ~~ selectedMessageName
  5392.         ifTrue: 
  5393.             [category = ClassOrganizer nullCategory
  5394.                 ifTrue: [self changed: #classSelectionChanged.
  5395.                         self messageCategoryListIndex: 1].
  5396.             self setClassOrganizer.  "In case organization not cached"
  5397.             (oldMessageList includes: selector)
  5398.                 ifFalse: [self changed: #messageListChanged].
  5399.             self messageListIndex: (self messageList indexOf: selector)].
  5400.     notice size = 0 ifFalse: ["insert the notice"
  5401.             aController notify: notice
  5402.                 at: contents size + 1
  5403.                 in: nil.
  5404.             self lock  "code is dirty"].
  5405.     ^true!
  5406. fileOutMessage
  5407.     "Print a description of the selected message on the serial printer.
  5408.     4/11/96 tk - header, trailer"
  5409.     | fileStream |
  5410.     messageListIndex = 0 ifTrue: [^ self].
  5411.     fileStream _ FileStream newFileNamed: (self selectedClassOrMetaClass name , '-' , (self selectedMessageName copyReplaceAll: ':' with: '')) , '.st'.
  5412.     fileStream header; timeStamp.
  5413.     self selectedClassOrMetaClass printCategoryChunk: self selectedMessageCategoryName
  5414.         on: fileStream.
  5415.     self selectedClassOrMetaClass printMethodChunk: self selectedMessageName
  5416.         on: fileStream
  5417.         moveSource: false
  5418.         toFile: 0.
  5419.     fileStream nextChunkPut: ' '.
  5420.     fileStream trailer; close!
  5421. removeMessage
  5422.     "If a message is selected, create a Confirmer so the user can verify that 
  5423.     the currently selected message should be removed from the system. If so, 
  5424.     remove it.  If the Preference 'confirmMethodRemoves' is set to false, the 
  5425.     confirmer is bypassed.
  5426.     1/15/96 sw: started to modify as per Dan's request"
  5427.  
  5428.     | message messageName confirmation |
  5429.  
  5430.     messageListIndex = 0 ifTrue: [^ self].
  5431.     self okToChange ifFalse: [^ self].
  5432.     messageName _ self selectedMessageName.
  5433.     confirmation _ self selectedClassOrMetaClass confirmRemovalOf: messageName.
  5434.     confirmation == 3 ifTrue: [^ self].
  5435.  
  5436.     self selectedClassOrMetaClass removeSelector: self selectedMessageName.
  5437.     self messageListIndex: 0.
  5438.     self setClassOrganizer.  "In case organization not cached"
  5439.     self changed: #messageListChanged.
  5440.  
  5441.     confirmation == 2 ifTrue:
  5442.         [Smalltalk sendersOf: messageName]! !
  5443.  
  5444. !Browser methodsFor: 'metaclass'!
  5445. classMessagesIndicated
  5446.     "Answer whether the messages to be presented should come from the 
  5447.     metaclass."
  5448.  
  5449.     ^metaClassIndicated!
  5450. classOrMetaClassOrganizer
  5451.     "Answer the class organizer for the metaclass or class, depending on 
  5452.     which (instance or class) is indicated."
  5453.  
  5454.     metaClassIndicated
  5455.         ifTrue: [^metaClassOrganizer]
  5456.         ifFalse: [^classOrganizer]!
  5457. indicateClassMessages
  5458.     "Indicate that the message selection should come from the metaclass 
  5459.     messages."
  5460.  
  5461.     self metaClassIndicated: true!
  5462. indicateInstanceMessages
  5463.     "Indicate that the message selection should come from the class (instance) 
  5464.     messages."
  5465.  
  5466.     self metaClassIndicated: false!
  5467. instanceMessagesIndicated
  5468.     "Answer whether the messages to be presented should come from the 
  5469.     class."
  5470.  
  5471.     ^metaClassIndicated not!
  5472. metaClassIndicated
  5473.     "Answer the boolean flag that indicates which of the method dictionaries, 
  5474.     class or metaclass."
  5475.  
  5476.     ^metaClassIndicated!
  5477. metaClassIndicated: trueOrFalse 
  5478.     "Indicate whether browsing instance or class messages."
  5479.     metaClassIndicated _ trueOrFalse.
  5480.     self setClassOrganizer.
  5481.     systemCategoryListIndex > 0 ifTrue:
  5482.         [editSelection _ classListIndex = 0
  5483.             ifTrue: [metaClassIndicated
  5484.                 ifTrue: [#none]
  5485.                 ifFalse: [#newClass]]
  5486.             ifFalse: [#editClass]].
  5487.     messageCategoryListIndex _ 0.
  5488.     messageListIndex _ 0.
  5489.     contents _ nil.
  5490.     self changed: #classSelectionChanged!
  5491. selectedClassOrMetaClass
  5492.     "Answer the selected class or metaclass."
  5493.  
  5494.     metaClassIndicated
  5495.         ifTrue: [^self selectedClass class]
  5496.         ifFalse: [^self selectedClass]!
  5497. selectedClassOrMetaClassName
  5498.     "Answer the selected class name or metaclass name."
  5499.  
  5500.     ^self selectedClassOrMetaClass name!
  5501. setClassOrganizer
  5502.     "Install whatever organization is appropriate"
  5503.     classOrganizer _ nil.
  5504.     metaClassOrganizer _ nil.
  5505.     classListIndex = 0 ifTrue: [^ self].
  5506.     metaClassIndicated
  5507.         ifTrue: [metaClassOrganizer _ self selectedClass class organization]
  5508.         ifFalse: [classOrganizer _ self selectedClass organization]! !
  5509. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  5510.  
  5511. Browser class
  5512.     instanceVariableNames: ''!
  5513.  
  5514. !Browser class methodsFor: 'instance creation'!
  5515. new
  5516.  
  5517.     ^super new systemOrganizer: SystemOrganization!
  5518. newOnCategory: aCategory
  5519.     "Browse the system category of the given name.  7/13/96 sw"
  5520.  
  5521.     "Browser newOnCategory: 'Interface-Browser'"
  5522.  
  5523.     | newBrowser catList |
  5524.     newBrowser _ Browser new.
  5525.     catList _ newBrowser systemCategoryList.
  5526.     newBrowser systemCategoryListIndex: (catList indexOf: aCategory asSymbol ifAbsent: [^ self inform: 'No such category']).
  5527.     BrowserView openSystemCategoryBrowser: newBrowser label: aCategory editString: nil!
  5528. newOnClass: aClass 
  5529.     "Open a new class browser on this class."
  5530.  
  5531.     | index each newBrowser |
  5532.     newBrowser _ Browser new.
  5533.     newBrowser systemCategoryListIndex:
  5534.         (index _ SystemOrganization numberOfCategoryOfElement: aClass name).
  5535.     newBrowser classListIndex: ((SystemOrganization listAtCategoryNumber: index)
  5536.             findFirst: [:each | each == aClass name]).
  5537.     newBrowser metaClassIndicated: false.
  5538.     BrowserView openClassBrowser: newBrowser editString: nil label: 'Class Browser:', aClass name!
  5539. postOpenSuggestion
  5540.     "Holds class and sel to select after opening"
  5541.     ^ PostOpenSuggestion!
  5542. postOpenSuggestion: anArray
  5543.     "Holds class and sel to select after opening"
  5544.     PostOpenSuggestion _ anArray! !StringHolderController subclass: #BrowserCodeController
  5545.     instanceVariableNames: ''
  5546.     classVariableNames: 'NewLine '
  5547.     poolDictionaries: ''
  5548.     category: 'Interface-Browser'!
  5549. BrowserCodeController comment:
  5550. 'I am a kind of StringHolderController (a ParagraphEditor that adds the doIt, printIt, accept, and cancel commands). I provide control for editing methods in a browser. New commands are:
  5551.     explain    insert an explanation of the current selection just after it
  5552.     format    pretty-print of the code, do not issue an automatic accept
  5553.     spawn    create and schedule a message browser for the, possibly edited but not accepted, code.'!
  5554.  
  5555. !BrowserCodeController methodsFor: 'menu messages'!
  5556. accept
  5557.  
  5558.     model isUnlocked ifTrue: [^view flash].
  5559.     self controlTerminate.
  5560.     (model contents: paragraph text notifying: self) ifTrue: [super accept].
  5561.     self controlInitialize!
  5562. cancel
  5563.     model isUnlocked ifTrue: [^ view flash].
  5564.     super cancel!
  5565. doIt
  5566.     "Allow class variables and pool variables of current class to be accessed in the doIt"
  5567.     | result |
  5568.     model selectedClass == nil ifTrue: [^ super doIt].
  5569.     FakeClassPool classPool: model selectedClass classPool.
  5570.     FakeClassPool sharedPools: model selectedClass sharedPools.
  5571.     result _ super doIt.
  5572.     FakeClassPool classPool: nil.
  5573.     FakeClassPool sharedPools: nil.
  5574.     ^ result!
  5575. explain
  5576.     "Try to shed some light on what kind of entity the current selection is. 
  5577.     The selection must be a single token or construct. Insert the answer after 
  5578.     the selection. Send private messages whose names begin with 'explain' 
  5579.     that return a string if they recognize the selection, else nil."
  5580.  
  5581.     | string tiVars cgVars selectors delimitors numbers symbol sorry reply |
  5582.     Cursor execute
  5583.         showWhile: 
  5584.             [sorry _ '"Sorry, I can''t explain that.  Please select a single token, construct, or special character.'.
  5585.             sorry _ sorry , (model isUnlocked
  5586.                             ifTrue: ['"']
  5587.                             ifFalse: ['  Also, please cancel or accept."']).
  5588.             (string _ self selection asString) isEmpty
  5589.                 ifTrue: [reply _ '']
  5590.                 ifFalse: 
  5591.                     [string _ self explainScan: string.
  5592.                     "Remove space, tab, cr"
  5593.                     "Temps and Instance vars need only test strings that are 
  5594.                     all  
  5595.                     letters"
  5596.                     (string detect: [:char | (char isLetter or: [char isDigit]) not]
  5597.                         ifNone: [])
  5598.                         ~~ nil
  5599.                         ifFalse: 
  5600.                             [tiVars _ self explainTemp: string.
  5601.                             tiVars == nil ifTrue: [tiVars _ self explainInst: string]].
  5602.                     (tiVars == nil and: [model class == Browser])
  5603.                         ifTrue: [tiVars _ model explainSpecial: string].
  5604.                     tiVars == nil
  5605.                         ifTrue: [tiVars _ '']
  5606.                         ifFalse: [tiVars _ tiVars , NewLine].
  5607.                     "Context, Class, Pool, and Global vars, and Selectors need 
  5608.                     only test symbols"
  5609.                     (Symbol hasInterned: string ifTrue: [:symbol | symbol])
  5610.                         ifTrue: 
  5611.                             [cgVars _ self explainCtxt: symbol.
  5612.                             cgVars == nil
  5613.                                 ifTrue: 
  5614.                                     [cgVars _ self explainClass: symbol.
  5615.                                     cgVars == nil ifTrue: [cgVars _ self explainGlobal: symbol]].
  5616.                             "See if it is a Selector (sent here or not)"
  5617.                             selectors _ self explainMySel: symbol.
  5618.                             selectors == nil
  5619.                                 ifTrue: 
  5620.                                     [selectors _ self explainPartSel: string.
  5621.                                     selectors == nil ifTrue: [selectors _ self explainAnySel: symbol]]]
  5622.                         ifFalse: [selectors _ self explainPartSel: string].
  5623.                     cgVars == nil
  5624.                         ifTrue: [cgVars _ '']
  5625.                         ifFalse: [cgVars _ cgVars , NewLine].
  5626.                     selectors == nil
  5627.                         ifTrue: [selectors _ '']
  5628.                         ifFalse: [selectors _ selectors , NewLine].
  5629.                     string size = 1
  5630.                         ifTrue: ["single special characters"
  5631.                             delimitors _ self explainChar: string]
  5632.                         ifFalse: ["matched delimitors"
  5633.                             delimitors _ self explainDelimitor: string].
  5634.                     numbers _ self explainNumber: string.
  5635.                     numbers == nil ifTrue: [numbers _ ''].
  5636.                     delimitors == nil ifTrue: [delimitors _ ''].
  5637.                     reply _ tiVars , cgVars , selectors , delimitors , numbers].
  5638.             reply size = 0 ifTrue: [reply _ sorry].
  5639.             self afterSelectionInsertAndSelect: reply]!
  5640. format
  5641.     "Reformat the contents of the receiver's view, formatted, if the view is unlocked. "
  5642.  
  5643.     | selectedClass aCompiler newText locked |
  5644.     locked _ model isLocked.
  5645.     Sensor leftShiftDown
  5646.         ifTrue: [self miniFormat]
  5647.         ifFalse: 
  5648.             [model messageListIndex = 0 | locked ifTrue: [^view flash].
  5649.             selectedClass _ model selectedClassOrMetaClass.
  5650.             Cursor execute showWhile: 
  5651.                 [aCompiler _ selectedClass compilerClass new.
  5652.                 self deselect; selectInvisiblyFrom: 1 to: paragraph text size.
  5653.                 newText _ aCompiler
  5654.                     format: model contents
  5655.                     in: selectedClass
  5656.                     notifying: self.
  5657.                 newText == nil ifFalse: 
  5658.                     [self replaceSelectionWith:
  5659.                         (newText asText makeSelectorBoldIn: selectedClass).
  5660.                     self selectAt: 1]]].
  5661.     locked ifFalse: [self unlockModel]!
  5662. inspectIt
  5663.     "Allow class variables and pool variables of current class to be accessed in the inspectIt.  6/13/96 sw"
  5664.  
  5665.     | result |
  5666.  
  5667.     model selectedClass == nil ifTrue: [^ super inspectIt].
  5668.     FakeClassPool classPool: model selectedClass classPool.
  5669.     FakeClassPool sharedPools: model selectedClass sharedPools.
  5670.     self controlTerminate.
  5671.  
  5672.     result _ self evaluateSelection.
  5673.     FakeClassPool classPool: nil.
  5674.     FakeClassPool sharedPools: nil.
  5675.  
  5676.     ((result isKindOf: FakeClassPool) or:
  5677.         [result == #failedDoit])
  5678.             ifFalse: [result inspect]
  5679.             ifTrue: [view flash].
  5680.     self controlInitialize.
  5681.  
  5682.     ^ result!
  5683. spawn
  5684.     "Create and schedule a message browser for the code of the model's 
  5685.     selected message. Retain any edits that have not yet been accepted."
  5686.  
  5687.     | code |
  5688.     code _ paragraph text string.
  5689.     self cancel.
  5690.     self controlTerminate.
  5691.     model spawn: code.
  5692.     self controlInitialize!
  5693. spawnIt: characterStream 
  5694.     "Triggered by Cmd-o; spawn a new code window, if it makes sense.  Reimplemented by BrowserCodeController  2/1/96 sw.  Fixed, 2/5/96 sw, so that it really works."
  5695.  
  5696.     self controlTerminate.
  5697.     sensor keyboard.    
  5698.     self spawn.
  5699.     self controlInitialize.
  5700.     ^ true! !
  5701.  
  5702. !BrowserCodeController methodsFor: 'private'!
  5703. explainAnySel: symbol 
  5704.     "Is this any message selector?"
  5705.  
  5706.     | list reply |
  5707.     list _ Smalltalk allClassesImplementing: symbol.
  5708.     list size = 0 ifTrue: [^nil].
  5709.     list size < 12
  5710.         ifTrue: [reply _ ' is a message selector which is defined in these classes ' , list printString]
  5711.         ifFalse: [reply _ ' is a message selector which is defined in many classes'].
  5712.     ^'"' , symbol , reply , '."', NewLine, 'Smalltalk browseAllImplementorsOf: #' , symbol!
  5713. explainChar: string
  5714.     "Does string start with a special character?"
  5715.  
  5716.     | char |
  5717.     char _ string at: 1.
  5718.     char = $. ifTrue: [^'"Period marks the end of a Smalltalk statement.  A period in the middle of a number means a decimal point.  (The number is an instance of Float)."'].
  5719.     char = $' ifTrue: [^'"The characters between two single quotes are made into an instance of class String"'].
  5720.     char = $" ifTrue: [^'"Double quotes enclose a comment.  Smalltalk ignores everything between double quotes."'].
  5721.     char = $# ifTrue: [^'"The characters following a hash mark are made into an instance of class Symbol.  If parenthesis follow a hash mark, an instance of class Array is made."'].
  5722.     (char = $( or: [char = $)]) ifTrue: [^'"Expressions enclosed in parenthesis are evaluated first"'].
  5723.     (char = $[ or: [char = $]]) ifTrue: [^'"The code inside square brackets is an unevaluated block of code.  It becomes an instance of BlockContext and is usually passed as an argument."'].
  5724.     (char = $< or: [char = $>]) ifTrue: [^'"<primitive: xx> means that this method is usually preformed directly by the virtual machine.  If this method is primitive, its Smalltalk code is executed only when the primitive fails."'].
  5725.     char = $^ ifTrue: [^'"Uparrow means return from this method.  The value returned is the expression following the ^"'].
  5726.     char = $| ifTrue: [^'"Vertical bars enclose the names of the temporary variables used in this method.  In a block, the vertical bar separates the argument names from the rest of the code."'].
  5727.     char = $_ ifTrue: [^'"Left arrow means assignment.  The value of the expression after the left arrow is stored into the variable before it."'].
  5728.     char = $; ifTrue: [^'"Semicolon means cascading.  The message after the semicolon is sent to the same object which received the message before the semicolon."'].
  5729.     char = $: ifTrue: [^'"A colon at the end of a keyword means that an argument is expected to follow.  Methods which take more than one argument have selectors with more than one keyword.  (One keyword, ending with a colon, appears before each argument).', NewLine, NewLine, 'A colon before a variable name just inside a block means that the block takes an agrument.  (When the block is evaluated, the argument will be assigned to the variable whose name appears after the colon)."'].
  5730.     char = $$ ifTrue: [^'"The single character following a dollar sign is made into an instance of class Character"'].
  5731.     char = $- ifTrue: [^'"A minus sign in front of a number means a negative number."'].
  5732.     char = $e ifTrue: [^'"An e in the middle of a number means that the exponent follows."'].
  5733.     char = $r ifTrue: [^'"An r in the middle of a bunch of digits is an instance of Integer expressed in a certain radix.  The digits before the r denote the base and the digits after it express a number in that base."'].
  5734.     char = Character space ifTrue: [^'"the space Character"'].
  5735.     char = Character tab ifTrue: [^'"the tab Character"'].
  5736.     char = Character cr ifTrue: [^'"the carriage return Character"'].
  5737.     ^nil!
  5738. explainClass: symbol 
  5739.     "Is symbol a class variable or a pool variable?"
  5740.  
  5741.     | class name pool reply classes |
  5742.     class _ model selectedClass.
  5743.     class == nil ifTrue: [^nil].      "no class is selected"
  5744.     (class isKindOf: Metaclass) ifTrue: [class _ class soleInstance].
  5745.     classes _ (Array with: class) , class allSuperclasses.
  5746.  
  5747.     "class variables"
  5748.     reply _ classes detect: [:each | (each classVarNames
  5749.             detect: [:name | symbol = name] ifNone: [])
  5750.             ~~ nil] ifNone: [].
  5751.     reply == nil ifFalse: [^'"is a class variable; defined in class ' , reply printString, '"', NewLine,
  5752.         'Smalltalk browseAllCallsOn: (', reply printString, ' classPool associationAt: #', symbol, ').'].
  5753.  
  5754.     "pool variables"
  5755.     classes do: [:each | (each sharedPools
  5756.             detect: [:pool | (pool includesKey: symbol) and: [reply _ pool. true]]
  5757.             ifNone: []) ~~ nil].
  5758.     reply == nil ifTrue: [(Undeclared includesKey: symbol) ifTrue: [reply _ Undeclared]].
  5759.     reply == nil
  5760.         ifFalse: 
  5761.             [classes _ WriteStream on: Array new.
  5762.             Smalltalk allBehaviorsDo: [:each |
  5763.                     (each sharedPools detect: [:pool | pool == reply] ifNone: [])
  5764.                     ~~ nil ifTrue: [classes nextPut: each]].
  5765.             "Perhaps not print whole list of classes if too long. (unlikely)"
  5766.             ^'"is a pool variable from the pool ' , (Smalltalk keyAtValue: reply),
  5767.             ', which is used by the following classes ' , classes contents printString , '"', NewLine,
  5768.             'Smalltalk browseAllCallsOn: (', (Smalltalk keyAtValue: reply) printString,
  5769.             ' associationAt: #', symbol, ').'].
  5770.     ^nil!
  5771. explainCtxt: symbol 
  5772.     "Is symbol a context variable?"
  5773.  
  5774.     | reply classes text |
  5775.     symbol = #nil ifTrue: [reply _ '"is a constant.  It is the only instance of class UndefinedObject.  nil is the initial value of all variables."'].
  5776.     symbol = #true ifTrue: [reply _ '"is a constant.  It is the only instance of class True and is the receiver of many control messages."'].
  5777.     symbol = #false ifTrue: [reply _ '"is a constant.  It is the only instance of class False and is the receiver of many control messages."'].
  5778.     model messageListIndex = 0 ifTrue: [^nil].      "no message selected"
  5779.     symbol = #self
  5780.         ifTrue: 
  5781.             [classes _ model selectedClassOrMetaClass withAllSubclasses.
  5782.             classes size > 12
  5783.                 ifTrue: [text _ model selectedClassOrMetaClass printString , ' or a subclass']
  5784.                 ifFalse: 
  5785.                     [classes _ classes printString.
  5786.                     text _ 'one of these classes' , (classes copyFrom: 4 to: classes size)].
  5787.             reply _ '"is the receiver of this message; an instance of ' , text , '"'].
  5788.     symbol = #super ifTrue: [reply _ '"is just like self.  Messages to super are looked up in the superclass (' , model selectedClassOrMetaClass superclass printString , ')"'].
  5789.     symbol = #thisContext ifTrue: [reply _ '"is a context variable.  It''s value is always the MethodContext which is executing this method."'].
  5790.     ^reply!
  5791. explainDelimitor: string
  5792.     "Is string enclosed in delimitors?"
  5793.  
  5794.     | str |
  5795.     (string at: 1) isLetter ifTrue: [^nil].  "only special chars"
  5796.     (string first = string last) ifTrue:
  5797.             [^ self explainChar: (String with: string first)]
  5798.         ifFalse:
  5799.             [(string first = $( and: [string last = $)]) ifTrue:
  5800.                 [^ self explainChar: (String with: string first)].
  5801.             (string first = $[ and: [string last = $]]) ifTrue:
  5802.                 [^ self explainChar: (String with: string first)].
  5803.             (string first = $< and: [string last = $>]) ifTrue:
  5804.                 [^ self explainChar: (String with: string first)].
  5805.             (string first = $# and: [string last = $)]) ifTrue:
  5806.                 [^'"An instance of class Array.  The Numbers, Characters, or Symbols between the parenthesis are the elements of the Array."'].
  5807.             string first = $# ifTrue:
  5808.                 [^'"An instance of class Symbol."'].
  5809.             (string first = $$ and: [string size = 2]) ifTrue:
  5810.                 [^'"An instance of class Character.  This one is the character ', (String with: string last), '."'].
  5811.             (string first = $:) ifTrue:
  5812.                 [str _ (string copyFrom: 2 to: string size).
  5813.                 (self explainTemp: str) ~~ nil ifTrue:
  5814.                     [^'"An argument to this block will be bound to the temporary variable ',
  5815.                         str, '."']]].
  5816.     ^ nil!
  5817. explainGlobal: symbol 
  5818.     "Is symbol a global variable?"
  5819.  
  5820.     | each pool reply classes |
  5821.     reply _ Smalltalk at: symbol ifAbsent: [^nil].
  5822.     (reply isKindOf: Behavior)
  5823.         ifTrue: [^'"is a global variable.  ' , symbol , ' is a class in category ', reply category,
  5824.             '."', NewLine, 'Browser newOnClass: ' , symbol , '.'].
  5825.     symbol == #Smalltalk ifTrue: [^'"is a global.  Smalltalk is the only instance of SystemDictionary and holds all global variables."'].
  5826.     reply class == Dictionary
  5827.         ifTrue: 
  5828.             [classes _ Set new.
  5829.             Smalltalk allBehaviorsDo: [:each | (each sharedPools detect: [:pool | pool == reply]
  5830.                     ifNone: [])
  5831.                     ~~ nil ifTrue: [classes add: each]].
  5832.             classes _ classes printString.
  5833.             ^'"is a global variable.  ' , symbol , ' is a Dictionary.  It is a pool which is used by the following classes' , (classes copyFrom: 4 to: classes size) , '"'].
  5834.     ^'"is a global variable.  ' , symbol , ' is ' , reply printString , '"'!
  5835. explainInst: string 
  5836.     "Is string an instance variable of this class?"
  5837.  
  5838.     | name each classes |
  5839.     model selectedClassOrMetaClass == nil ifTrue: [^nil].      "no class is selected"
  5840.     classes _ (Array with: model selectedClassOrMetaClass)
  5841.                 , model selectedClassOrMetaClass allSuperclasses.
  5842.     classes _ classes detect: [:each | (each instVarNames
  5843.             detect: [:name | name = string] ifNone: [])
  5844.             ~~ nil] ifNone: [^nil].
  5845.     classes _ classes printString.
  5846.     ^ '"is an instance variable of the receiver; defined in class ' , classes , '"',
  5847.         NewLine , classes , ' browseAllAccessesTo: ''' , string , '''.'!
  5848. explainMySel: symbol 
  5849.     "Is symbol the selector of this method?  Is it sent by this method?  If 
  5850.     not, then expalin will call (explainPartSel:) to see if it is a fragment of a 
  5851.     selector sent here.  If not, explain will call (explainAnySel:) to catch any 
  5852.     selector. "
  5853.  
  5854.     | lits classes |
  5855.     model messageListIndex = 0 ifTrue: [^nil].    "not in a message"
  5856.     classes _ Smalltalk allClassesImplementing: symbol.
  5857.     classes size > 12
  5858.         ifTrue: [classes _ 'many classes']
  5859.         ifFalse: [classes _ 'these classes ' , classes printString].
  5860.     model selectedMessageName = symbol
  5861.         ifTrue: [^ '"' , symbol , ' is the selector of this very method!!  It is defined in ',
  5862.             classes , '.  To see the other definitions, go to the message list pane and use yellowbug to select ''implementors''."']
  5863.         ifFalse: 
  5864.             [lits _ (model selectedClassOrMetaClass compiledMethodAt:
  5865.                 model selectedMessageName) messages.
  5866.             (lits detect: [:each | each == symbol]
  5867.                 ifNone: [])
  5868.                 == nil ifTrue: [^nil].
  5869.             ^ '"' , symbol , ' is a message selector which is defined in ', classes , '.  To see the definitions, go to the message list pane and use yellowbug to select ''messages''."'].!
  5870. explainNumber: string 
  5871.     "Is string a Number?"
  5872.  
  5873.     | strm c |
  5874.     (c _ string at: 1) isDigit ifFalse: [(c = $- and: [string size > 1])
  5875.             ifFalse: [^nil]].
  5876.     strm _ ReadStream on: string.
  5877.     c _ Number readFrom: strm.
  5878.     strm atEnd ifFalse: [^nil].
  5879.     c printString = string
  5880.         ifTrue: [^'"' , string , ' is a ' , c class name , '"']
  5881.         ifFalse: [^'"' , string , ' (= ' , c printString , ') is a ' , c class name , '"']!
  5882. explainPartSel: string 
  5883.     "Is this a fragment of a multiple-argument selector sent in this method?"
  5884.  
  5885.     | lits frag whole reply classes s |
  5886.     model messageListIndex = 0 ifTrue: [^nil].  "not in a message"
  5887.     string last == $: ifFalse: [^nil].
  5888.     "Name of this method"
  5889.     lits _ Array with: model selectedMessageName.
  5890.     (whole _ lits detect: [:each | (each keywords detect: [:frag | frag = string]
  5891.                     ifNone: []) ~~ nil]
  5892.                 ifNone: []) ~~ nil
  5893.         ifTrue: [reply _ ', which is the selector of this very method!!'.
  5894.             s _ '.  To see the other definitions, go to the message list pane and use yellowbug to select ''implementors''."']
  5895.         ifFalse: 
  5896.             ["Selectors called from this method"
  5897.             lits _ (model selectedClassOrMetaClass compiledMethodAt:
  5898.                 model selectedMessageName) messages.
  5899.             (whole _ lits detect: [:each | (each keywords detect: [:frag | frag = string]
  5900.                             ifNone: []) ~~ nil]
  5901.                         ifNone: []) ~~ nil
  5902.                 ifFalse: [string = 'primitive:'
  5903.                     ifTrue: [^self explainChar: '<']
  5904.                     ifFalse: [^nil]].
  5905.             reply _ '.'.
  5906.             s _ '.  To see the definitions, go to the message list pane and use yellowbug to select ''messages''."'].
  5907.     classes _ Smalltalk allClassesImplementing: whole.
  5908.     classes size > 12
  5909.         ifTrue: [classes _ 'many classes']
  5910.         ifFalse: [classes _ 'these classes ' , classes printString].
  5911.     ^ '"' , string , ' is one part of the message selector ' , whole, reply , '  It is defined in ' , classes , s!
  5912. explainScan: string 
  5913.     "Remove beginning and trailing space, tab, cr."
  5914.  
  5915.     | c beg end |
  5916.     beg _ 1.
  5917.     end _ string size.
  5918.     
  5919.     [beg = end ifTrue: [^string copyFrom: 1 to: 1].
  5920.     "if all blank, tell about the first"
  5921.     c _ string at: beg.
  5922.     c = Character space or: [c = Character tab or: [c = Character cr]]]
  5923.         whileTrue: [beg _ beg + 1].
  5924.     
  5925.     [c _ string at: end.
  5926.     c = Character space or: [c = Character tab or: [c = Character cr]]]
  5927.         whileTrue: [end _ end - 1].
  5928.     ^string copyFrom: beg to: end    "Return purely visible characters"!
  5929. explainTemp: string 
  5930.     "Is string the name of a temporary variable (or block argument variable)?"
  5931.  
  5932.     | selectedClass tempNames i reply methodNode method |
  5933.     model messageListIndex = 0 ifTrue: [^nil].    "no message is selected"
  5934.     selectedClass _ model selectedClassOrMetaClass.
  5935.     tempNames _ selectedClass parserClass new parseArgsAndTemps: model selectedMessage notifying: nil.
  5936.     method _ selectedClass compiledMethodAt: model selectedMessageName.
  5937.     (i _ tempNames findFirst: [:each | each = string]) = 0 ifTrue: [
  5938.         (method numTemps > tempNames size)
  5939.             ifTrue: 
  5940.                 ["It must be an undeclared block argument temporary"
  5941.                 methodNode _ selectedClass compilerClass new
  5942.                             parse: model selectedMessage
  5943.                             in: model selectedClassOrMetaClass
  5944.                             notifying: nil.
  5945.                 tempNames _ methodNode tempNames]
  5946.             ifFalse: [^nil]].
  5947.     (i _ tempNames findFirst: [:each | each = string]) > 0 ifTrue: [i > method numArgs
  5948.             ifTrue: [reply _ '"is a temporary variable in this method"']
  5949.             ifFalse: [reply _ '"is an argument to this method"']].
  5950.     ^reply!
  5951. miniFormat
  5952.     "Replace selection with selection un-wrapped."
  5953.  
  5954.     | inStream outStream char |
  5955.     inStream _ ReadStream on: (self selection copyWithout: Character tab).
  5956.     outStream _ WriteStream on: (String new: self selection size).
  5957.     [inStream atEnd]
  5958.         whileFalse: 
  5959.             [char _ inStream next.
  5960.             char isSeparator
  5961.                 ifTrue: 
  5962.                     [outStream space.
  5963.                     [inStream atEnd not and: [inStream peek isSeparator]]
  5964.                         whileTrue: [inStream next]]
  5965.                 ifFalse: [outStream nextPut: char]].
  5966.     self deselect.
  5967.     self replaceSelectionWith: outStream contents asText.
  5968.     self select! !
  5969. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  5970.  
  5971. BrowserCodeController class
  5972.     instanceVariableNames: ''!
  5973.  
  5974. !BrowserCodeController class methodsFor: 'class initialization'!
  5975. initialize
  5976.     "BrowserCodeController initialize"
  5977.     "1/8/96 sw: added senders/implementors/references.  1/15/96 added browse it.
  5978.     1/22/96 sw: show command-key equivalents
  5979.     1/24/96 sw: put many into shifted side, added find & more etc.
  5980.     1/26/96 sw: fixed up cmd key equivalent
  5981.     1/31/96 sw: BrowserCodeYellowButtonMenu/Msgs no longer used"
  5982.  
  5983.     NewLine _ String with: Character cr.  "used to append cr in explain messages"
  5984.     self allInstancesDo: [:i | i initializeYellowButtonMenu]! !
  5985.  
  5986. BrowserCodeController initialize!
  5987. StringHolderView subclass: #BrowserCodeView
  5988.     instanceVariableNames: ''
  5989.     classVariableNames: ''
  5990.     poolDictionaries: ''
  5991.     category: 'Interface-Browser'!
  5992. BrowserCodeView comment:
  5993. 'I am a StringHolderView of the source code retrieved in a Browser. BrowserCodeController is my default controller.'!
  5994.  
  5995. !BrowserCodeView methodsFor: 'controller access'!
  5996. defaultControllerClass
  5997.  
  5998.     ^BrowserCodeController! !
  5999.  
  6000. !BrowserCodeView methodsFor: 'updating'!
  6001. update: aSymbol
  6002.     aSymbol == #messageListChanged ifTrue: [^ self].
  6003.     aSymbol == #classListChanged ifTrue: [^ self].
  6004.     aSymbol == #autoSelect ifTrue:
  6005.         [controller setSearch: model autoSelectString;
  6006.                 againOrSame: true.
  6007.         ^ self].
  6008.     ^ super update: aSymbol!
  6009. updateDisplayContents 
  6010.     "Refer to the comment in StringHolderView|updateDisplayContents."
  6011.  
  6012.     | contents |
  6013.     contents _ model contents.
  6014.     displayContents asString ~= contents
  6015.         ifTrue: 
  6016.             [model messageListIndex ~= 0
  6017.                 ifTrue: [contents _ contents asText
  6018.                                 makeSelectorBoldIn: model selectedClassOrMetaClass].
  6019.             self editString: contents.
  6020.             self displayView.
  6021.             model editSelection == #newMessage ifTrue:
  6022.                 [controller selectFrom: 1 to: contents size]]! !ListController subclass: #BrowserListController
  6023.     instanceVariableNames: ''
  6024.     classVariableNames: ''
  6025.     poolDictionaries: ''
  6026.     category: 'Interface-Browser'!
  6027. BrowserListController comment:
  6028. 'I am a kind of ListController that blocks new selections if the model is locked--i.e., has been changed in some way that still requires completion.'!
  6029.  
  6030. !BrowserListController methodsFor: 'control defaults'!
  6031. redButtonActivity
  6032.     model okToChange  "Dont change selection if model is locked"
  6033.         ifTrue: [^ super redButtonActivity]! !ListView subclass: #BrowserListView
  6034.     instanceVariableNames: 'singleItemMode '
  6035.     classVariableNames: ''
  6036.     poolDictionaries: ''
  6037.     category: 'Interface-Browser'!
  6038. BrowserListView comment:
  6039. 'I am a ListView whose items are elements of the system, such as class categories or class names. I am abstract; my subclasses provide the connection between items to be viewed and aspects of an instance of Browser.'!
  6040.  
  6041. !BrowserListView methodsFor: 'initialize-release'!
  6042. initialize
  6043.  
  6044.     singleItemMode _ false.
  6045.     super initialize! !
  6046.  
  6047. !BrowserListView methodsFor: 'accessing'!
  6048. singleItemMode
  6049.     "Answer whether the list contains one item."
  6050.  
  6051.     ^singleItemMode!
  6052. singleItemMode: aBoolean 
  6053.     "The argument indicates whether the list contains one element. If it does, 
  6054.     select it."
  6055.  
  6056.     singleItemMode _ aBoolean.
  6057.     singleItemMode ifTrue: [selection _ 1]! !
  6058.  
  6059. !BrowserListView methodsFor: 'selecting'!
  6060. findSelection: aPoint 
  6061.     "Refer to the comment in ListView|findSelection:."
  6062.  
  6063.     singleItemMode
  6064.         ifTrue: 
  6065.             [self flash.
  6066.             ^nil]
  6067.         ifFalse: [^super findSelection: aPoint]! !
  6068.  
  6069. !BrowserListView methodsFor: 'updating'!
  6070. getList
  6071.     "Answer an Array of the items in the list."
  6072.  
  6073.     self subclassResponsibility!
  6074. getListAndDisplayView
  6075.     "Display the list of items."
  6076.  
  6077.     | newList |
  6078.     newList _ self getList.
  6079.     isEmpty & newList isEmpty
  6080.         ifTrue: [^self]
  6081.         ifFalse: 
  6082.             [self list: newList.
  6083.             self displayView; emphasizeView]! !
  6084.  
  6085. !BrowserListView methodsFor: 'model access'!
  6086. model: aBrowser
  6087.  
  6088.     super model: aBrowser.
  6089.     self list: self getList.
  6090.     singleItemMode ifTrue: [selection _ 1]! !
  6091.  
  6092. !BrowserListView methodsFor: 'list access'!
  6093. list: anArray 
  6094.     "Refer to the comment in ListView|list:."
  6095.  
  6096.     super list: anArray.
  6097.     singleItemMode ifTrue: [selection _ 1]! !StandardSystemView subclass: #BrowserView
  6098.     instanceVariableNames: ''
  6099.     classVariableNames: ''
  6100.     poolDictionaries: ''
  6101.     category: 'Interface-Browser'!
  6102. BrowserView comment:
  6103. 'I am a StandardSystemView that provides initialization methods (messages to myself) to create and schedule the various system browsers: System Browser, System Category Browser, Class Browser, Message Category Browser, Message Browser. The number of subViews I contain depends on which of the browsing functions I am providing.'!
  6104.  
  6105. !BrowserView methodsFor: 'emphasis'!
  6106. emphasizeSubViews
  6107.     "Give the model a chance to know that things may have changed behind its back.  8/5/96 sw"
  6108.  
  6109.     model browserWindowActivated.
  6110.     super emphasizeSubViews! !
  6111. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  6112.  
  6113. BrowserView class
  6114.     instanceVariableNames: ''!
  6115.  
  6116. !BrowserView class methodsFor: 'instance creation'!
  6117. browser: aBrowser 
  6118.     "Answer an instance of me on the model, aBrowser. The instance consists 
  6119.     of five subviews, starting with the list view of system categories. The 
  6120.     initial text view part is empty."
  6121.  
  6122.     self browser: aBrowser editString: nil!
  6123. browser: aBrowser editString: aString 
  6124.     "Answer an instance of me on the model, aBrowser. The instance consists 
  6125.     of five subviews, starting with the list view of system categories. The 
  6126.     initial text view part is a view of the characters in aString."
  6127.  
  6128.     | browserView systemCategoryListView classListView messageCategoryListView
  6129.     switchView messageListView browserCodeView |
  6130.  
  6131.     browserView _ self new model: aBrowser.
  6132.     systemCategoryListView _ self buildSystemCategoryListView: aBrowser.
  6133.     classListView _ self buildClassListView: aBrowser.
  6134.     switchView _ self buildInstanceClassSwitchView: aBrowser.
  6135.     messageCategoryListView _ self buildMessageCategoryListView: aBrowser.
  6136.     messageListView _ self buildMessageListView: aBrowser.
  6137.     browserCodeView _ self buildBrowserCodeView: aBrowser editString: aString.
  6138.  
  6139.     browserView addSubView: systemCategoryListView.
  6140.     browserView addSubView: classListView.
  6141.     browserView addSubView: switchView.
  6142.     browserView addSubView: messageCategoryListView.
  6143.     browserView addSubView: messageListView.
  6144.     browserView addSubView: browserCodeView.
  6145.  
  6146.     classListView 
  6147.         align: classListView viewport topLeft     
  6148.         with: systemCategoryListView viewport topRight.
  6149.     switchView
  6150.         align: switchView viewport topLeft
  6151.         with: classListView viewport bottomLeft.
  6152.     messageCategoryListView 
  6153.         align: messageCategoryListView viewport topLeft 
  6154.         with: classListView viewport topRight.
  6155.     messageListView 
  6156.         align: messageListView viewport topLeft 
  6157.         with: messageCategoryListView viewport topRight.
  6158.     browserCodeView 
  6159.         align: browserCodeView viewport topLeft 
  6160.         with: systemCategoryListView viewport bottomLeft.
  6161.     
  6162.     aString notNil ifTrue: [aBrowser lock].
  6163.  
  6164.     ^browserView!
  6165. classBrowser: aBrowser 
  6166.     "Answer an instance of me on the model, aBrowser. The instance consists 
  6167.     of four subviews, starting with the list view of classes in the model's 
  6168.     currently selected system category. The initial text view part is empty."
  6169.  
  6170.     ^self classBrowser: aBrowser editString: nil!
  6171. classBrowser: aBrowser editString: aString 
  6172.     "Answer an instance of me on the model, aBrowser. The instance consists 
  6173.     of four subviews, starting with the list view of classes in the model's 
  6174.     currently selected system category. The initial text view part is a view 
  6175.     of the characters in aString."
  6176.  
  6177.     | browserView classListView messageCategoryListView switchView
  6178.     messageListView browserCodeView |
  6179.  
  6180.     browserView _ self new model: aBrowser.
  6181.     classListView _ self buildClassListView: aBrowser.
  6182.     switchView _ self buildInstanceClassSwitchView: aBrowser.
  6183.     messageCategoryListView _ self buildMessageCategoryListView: aBrowser.
  6184.     messageListView _ self buildMessageListView: aBrowser.
  6185.     browserCodeView _ self buildBrowserCodeView: aBrowser editString: aString.
  6186.  
  6187.     classListView borderWidthLeft: 2 right: 0 top: 2 bottom: 0.
  6188.     classListView singleItemMode: true.
  6189.     classListView noTopDelimiter.
  6190.     classListView noBottomDelimiter.
  6191.     classListView list: classListView getList.
  6192.     switchView borderWidthLeft: 2 right: 2 top: 2 bottom: 0.
  6193.  
  6194.     browserView addSubView: classListView.
  6195.     browserView addSubView: switchView.
  6196.     browserView addSubView: messageCategoryListView.
  6197.     browserView addSubView: messageListView.
  6198.     browserView addSubView: browserCodeView.
  6199.  
  6200.     messageListView 
  6201.         align: messageListView viewport topLeft 
  6202.         with: messageCategoryListView viewport topRight.
  6203.     classListView 
  6204.         window: classListView window 
  6205.         viewport: (messageCategoryListView viewport topLeft - (0 @ 12) 
  6206.                     corner: messageCategoryListView viewport topRight).
  6207.     switchView 
  6208.         window: switchView window 
  6209.         viewport: (messageListView viewport topLeft - (0 @ 12) 
  6210.                     corner: messageListView viewport topRight).
  6211.     browserCodeView 
  6212.         window: browserCodeView window 
  6213.         viewport: (messageCategoryListView viewport bottomLeft 
  6214.                     corner: messageListView viewport bottomRight + (0 @ 110)).
  6215.     
  6216.     aString notNil ifTrue: [aBrowser lock].
  6217.  
  6218.     ^browserView!
  6219. messageBrowser: aBrowser 
  6220.     "Answer an instance of me on the model, aBrowser. The instance consists 
  6221.     of two subviews, starting with the list view of message selectors in the 
  6222.     model's currently selected category. The initial text view part is empty."
  6223.  
  6224.     ^self messageBrowser: aBrowser editString: nil!
  6225. messageBrowser: aBrowser editString: aString 
  6226.     "Answer an instance of me on the model, aBrowser. The instance consists 
  6227.     of two subviews, starting with the list view of message selectors in the 
  6228.     model's currently selected category. The initial text view part is a view 
  6229.     of the characters in aString."
  6230.  
  6231.     | browserView messageListView browserCodeView |
  6232.  
  6233.     browserView _ self new model: aBrowser.
  6234.     messageListView _ self buildMessageListView: aBrowser.
  6235.     browserCodeView _ self buildBrowserCodeView: aBrowser editString: aString.
  6236.  
  6237.     messageListView borderWidthLeft: 2 right: 2 top: 2 bottom: 2.
  6238.     messageListView singleItemMode: true.
  6239.     messageListView noTopDelimiter.
  6240.     messageListView noBottomDelimiter.
  6241.     messageListView list: messageListView getList.
  6242.  
  6243.     browserView addSubView: messageListView.
  6244.     browserView addSubView: browserCodeView.
  6245.  
  6246.     messageListView 
  6247.         window: messageListView window 
  6248.         viewport: (browserCodeView viewport topLeft - (0 @ 12) 
  6249.                         corner: browserCodeView viewport topRight).
  6250.     
  6251.     aString notNil ifTrue: [aBrowser lock].
  6252.  
  6253.     ^browserView!
  6254. messageCategoryBrowser: aBrowser 
  6255.     "Answer an instance of me on the model, aBrowser. The instance consists 
  6256.     of three subviews, starting with the list view of message categories in 
  6257.     the model's currently selected class. The initial text view part is empty."
  6258.  
  6259.     ^self messageCategoryBrowser: aBrowser editString: nil!
  6260. messageCategoryBrowser: aBrowser editString: aString 
  6261.     "Answer an instance of me on the model, aBrowser. The instance consists 
  6262.     of three subviews, starting with the list view of message categories in 
  6263.     the model's currently selected class. The initial text view part is a view 
  6264.     of the characters in aString."
  6265.  
  6266.     | browserView messageCategoryListView messageListView browserCodeView |
  6267.  
  6268.     browserView _ self new model: aBrowser.
  6269.     messageCategoryListView _ self buildMessageCategoryListView: aBrowser.
  6270.     messageListView _ self buildMessageListView: aBrowser.
  6271.     browserCodeView _ self buildBrowserCodeView: aBrowser editString: aString.
  6272.  
  6273.     messageCategoryListView borderWidthLeft: 2 right: 2 top: 2 bottom: 0.
  6274.     messageCategoryListView singleItemMode: true.
  6275.     messageCategoryListView noTopDelimiter.
  6276.     messageCategoryListView noBottomDelimiter.
  6277.     messageCategoryListView list: messageCategoryListView getList.
  6278.  
  6279.     browserView addSubView: messageCategoryListView.
  6280.     browserView addSubView: messageListView.
  6281.     browserView addSubView: browserCodeView.
  6282.  
  6283.     messageCategoryListView 
  6284.         window: messageCategoryListView window 
  6285.         viewport: (messageListView viewport topLeft - (0 @ 12) 
  6286.                         corner: messageListView viewport topRight).
  6287.     browserCodeView 
  6288.         window: browserCodeView window 
  6289.         viewport: (messageListView viewport bottomLeft 
  6290.                         corner: messageListView viewport bottomRight + (0 @ 110)).
  6291.     
  6292.     aString notNil ifTrue: [aBrowser lock].
  6293.  
  6294.     ^browserView!
  6295. systemCategoryBrowser: aBrowser 
  6296.     "Answer an instance of me on the model, aBrowser. The instance consists 
  6297.     of five subviews, starting with the list view of the currently selected 
  6298.     system class category--a single item list. The initial text view part is 
  6299.     empty."
  6300.  
  6301.     ^self systemCategoryBrowser: aBrowser editString: nil!
  6302. systemCategoryBrowser: aBrowser editString: aString 
  6303.     "Answer an instance of me on the model, aBrowser. The instance consists 
  6304.     of five subviews, starting with the list view of the currently selected 
  6305.     system class category--a single item list. The initial text view part is a 
  6306.     view of the characters in aString."
  6307.  
  6308.     | browserView systemCategoryListView classListView switchView
  6309.         messageCategoryListView messageListView browserCodeView |
  6310.  
  6311.     browserView _ self new model: aBrowser.
  6312.     systemCategoryListView _ self buildSystemCategoryListView: aBrowser.
  6313.     classListView _ self buildClassListView: aBrowser.
  6314.     switchView _ self buildInstanceClassSwitchView: aBrowser.
  6315.     messageCategoryListView _ self buildMessageCategoryListView: aBrowser.
  6316.     messageListView _ self buildMessageListView: aBrowser.
  6317.     browserCodeView _ self buildBrowserCodeView: aBrowser editString: aString.
  6318.  
  6319.     systemCategoryListView borderWidthLeft: 2 right: 2 top: 2 bottom: 0.
  6320.     systemCategoryListView singleItemMode: true.
  6321.     systemCategoryListView noTopDelimiter.
  6322.     systemCategoryListView noBottomDelimiter.
  6323.     systemCategoryListView list: systemCategoryListView getList.
  6324.  
  6325.     browserView addSubView: systemCategoryListView.
  6326.     browserView addSubView: classListView.
  6327.     browserView addSubView: switchView.
  6328.     browserView addSubView: messageCategoryListView.
  6329.     browserView addSubView: messageListView.
  6330.     browserView addSubView: browserCodeView.
  6331.  
  6332.     switchView 
  6333.         align: switchView viewport topLeft 
  6334.         with: classListView viewport bottomLeft.
  6335.     messageCategoryListView 
  6336.         align: messageCategoryListView viewport topLeft 
  6337.         with: classListView viewport topRight.
  6338.     messageListView 
  6339.         align: messageListView viewport topLeft 
  6340.         with: messageCategoryListView viewport topRight.
  6341.     browserCodeView 
  6342.         window: browserCodeView window 
  6343.         viewport: (switchView viewport bottomLeft 
  6344.                         corner: messageListView viewport bottomRight + (0 @ 110)).
  6345.     systemCategoryListView 
  6346.         window: systemCategoryListView window 
  6347.         viewport: (classListView viewport topLeft - (0 @ 12) 
  6348.                         corner: messageListView viewport topRight).
  6349.     
  6350.     aString notNil ifTrue: [aBrowser lock].
  6351.  
  6352.     ^browserView! !
  6353.  
  6354. !BrowserView class methodsFor: 'instance scheduling'!
  6355. browseFullForClass: aClass
  6356.     "Create and schedule a full Browser with the given class chosen. 1/16/96 sw"
  6357.  
  6358.     self browseFullForClass: aClass method: nil!
  6359. browseFullForClass: aClass method: aSelector
  6360.     "Create and schedule a full Browser and then select the class of the master object being inspected.  1/12/96 sw"
  6361.  
  6362.     Browser postOpenSuggestion: (Array with: aClass with: aSelector).
  6363.         "This takes effect after the Browser comes up"
  6364.     self openBrowser!
  6365. browseFullForClass: aClass method: aSelector from: aController
  6366.     "Create and schedule a full Browser and then select the class of the master object being inspected.  1/12/96 sw"
  6367.  
  6368.     aController controlTerminate.
  6369.     self browseFullForClass: aClass method: aSelector.
  6370.     aController controlInitialize!
  6371. openBrowser
  6372.     "Create and schedule a BrowserView with label 'System Browser'. The 
  6373.     view consists of five subviews, starting with the list view of system 
  6374.     categories of SystemOrganization. The initial text view part is empty."
  6375.  
  6376.     self openBrowserEditString: nil!
  6377. openBrowserEditString: aString 
  6378.     "Create and schedule a BrowserView with label 'System Browser'. The 
  6379.     view consists of five subviews, starting with the list view of system 
  6380.     categories of SystemOrganization. The initial text view part is a view of 
  6381.     the characters in aString."
  6382.  
  6383.     self openBrowserView: (self browser: Browser new editString: aString)
  6384.         label: 'System Browser'!
  6385. openBrowserView: aBrowserView label: aString 
  6386.     "Schedule aBrowserView, labelling the view aString."
  6387.     
  6388.     aBrowserView label: aString.
  6389.     aBrowserView minimumSize: 300 @ 200.
  6390.     aBrowserView subViews do: [:each | each controller].
  6391.     aBrowserView controller open!
  6392. openClassBrowser: aBrowser editString: aString label: aLabel
  6393.     "Create and schedule a BrowserView with the specified window title.   The view  consists of four subviews, starting with the list view of classes in the  SystemOrganization's currently selected system category. The initial text  view part is a view of the characters in aString."
  6394.  
  6395.     self openBrowserView: (BrowserView classBrowser: aBrowser editString: aString)
  6396.         label: aLabel!
  6397. openMessageBrowser: aBrowser editString: aString 
  6398.     "Create and schedule a BrowserView with label 'Message Browser' 
  6399.     followed by the name of the selected class or metaclass. The view 
  6400.     consists of two subviews, starting with the list view of message selectors 
  6401.     in the System Organization's currently selected category. The initial text 
  6402.     view part is a view of the characters in aString."
  6403.  
  6404.     self openBrowserView: 
  6405.             (BrowserView messageBrowser: aBrowser editString: aString)
  6406.         label: aBrowser selectedClassOrMetaClassName , ' ' , aBrowser selectedMessageName!
  6407. openMessageBrowserForClass: aBehavior selector: aSymbol editString: aString
  6408.     "Create and schedule a message browser for the class, aBehavior, in 
  6409.     which the argument, aString, contains characters to be edited in the text 
  6410.     view. These characters are the source code for the message selector 
  6411.     aSymbol."
  6412.  
  6413.     | newBrowser aClass systemCatIndex messageCatIndex isMeta |
  6414.     newBrowser _ Browser new.
  6415.     (aBehavior isKindOf: Metaclass)
  6416.         ifTrue: [isMeta _ true. aClass _ aBehavior soleInstance]
  6417.         ifFalse: [isMeta _ false. aClass _ aBehavior].
  6418.     systemCatIndex _ SystemOrganization categories indexOf: aClass category.
  6419.     newBrowser systemCategoryListIndex: systemCatIndex.
  6420.     newBrowser classListIndex:
  6421.             ((SystemOrganization listAtCategoryNumber: systemCatIndex)
  6422.                     indexOf: aClass name).
  6423.     newBrowser metaClassIndicated: isMeta.
  6424.     messageCatIndex _ aBehavior organization numberOfCategoryOfElement: aSymbol.
  6425.     newBrowser messageCategoryListIndex: messageCatIndex.
  6426.     newBrowser messageListIndex:
  6427.             ((aBehavior organization listAtCategoryNumber: messageCatIndex)
  6428.                     indexOf: aSymbol).
  6429.     ^self openMessageBrowser: newBrowser editString: aString!
  6430. openMessageCategoryBrowser: aBrowser editString: aString 
  6431.     "Create and schedule a BrowserView with label 'Message Category 
  6432.     Browser' followed by the name of the selected class or metaclass. The 
  6433.     view consists of three subviews, starting with the list view of message 
  6434.     categories in the System Organization's currently selected class. The 
  6435.     initial text view part is a view of the characters in aString."
  6436.  
  6437.     self openBrowserView: 
  6438.             (BrowserView messageCategoryBrowser: aBrowser editString: aString)
  6439.         label: 
  6440.             'Message Category Browser (' , aBrowser selectedClassOrMetaClassName , ')'!
  6441. openSystemCategoryBrowser: aBrowser editString: aString 
  6442.     "Create and schedule a BrowserView with label 'System Category 
  6443.     Browser'. The view consists of five subviews, starting with the single 
  6444.     item list view of the currently selected system category of the 
  6445.     SystemOrganization. The initial text view part is a view of the characters 
  6446.     in aString."
  6447.  
  6448.     self openBrowserView: 
  6449.             (BrowserView systemCategoryBrowser: aBrowser editString: aString)
  6450.         label:
  6451.             'System Category Browser'!
  6452. openSystemCategoryBrowser: aBrowser label: aLabel editString: aString 
  6453.     "Create and schedule a BrowserView with label 'System Category 
  6454.     Browser'. The view consists of five subviews, starting with the single 
  6455.     item list view of the currently selected system category of the 
  6456.     SystemOrganization. The initial text view part is a view of the characters 
  6457.     in aString.
  6458.     7/13/96 sw: created this variant in which the caller can specifiy the window title"
  6459.  
  6460.     self openBrowserView: (BrowserView systemCategoryBrowser: aBrowser editString: aString)
  6461.         label: aLabel! !
  6462.  
  6463. !BrowserView class methodsFor: 'private'!
  6464. buildBrowserCodeView: aBrowser editString: aString
  6465.  
  6466.     | aBrowserCodeView |
  6467.     aBrowserCodeView _ BrowserCodeView new.
  6468.     aBrowserCodeView model: aBrowser.
  6469.     aBrowserCodeView window: (0 @ 0 extent: 200 @ 110).
  6470.     aBrowserCodeView borderWidthLeft: 2 right: 2 top: 0 bottom: 2.
  6471.     aString ~~ nil ifTrue: [aBrowserCodeView editString: aString].
  6472.     ^aBrowserCodeView!
  6473. buildClassListView: aBrowser
  6474.  
  6475.     | aClassListView |
  6476.     aClassListView _ ClassListView new.
  6477.     aClassListView model: aBrowser.
  6478.     aClassListView window: (0 @ 0 extent: 50 @ 62).
  6479.     aClassListView borderWidthLeft: 2 right: 0 top: 2 bottom: 2.
  6480.     ^aClassListView!
  6481. buildClassSwitchView: aBrowser
  6482.  
  6483.     | aSwitchView |
  6484.     aSwitchView _ SwitchView new.
  6485.     aSwitchView model: aBrowser.
  6486.     aSwitchView controller: LockedSwitchController new.
  6487.     aSwitchView selector: #classMessagesIndicated.
  6488.     aSwitchView controller selector: #indicateClassMessages.
  6489.     aSwitchView window: (0 @ 0 extent: 25 @ 8).
  6490.     aSwitchView label: 'class' asParagraph.
  6491.     ^aSwitchView!
  6492. buildInstanceClassSwitchView: aBrowser
  6493.     | aView aSwitchView |
  6494.     aView _ View new model: aBrowser.
  6495.     aView window: (0 @ 0 extent: 50 @ 8).
  6496.     aView borderWidthLeft: 2 right: 0 top: 0 bottom: 2.
  6497.     aSwitchView _ self buildInstanceSwitchView: aBrowser.
  6498.     aView
  6499.         addSubView: aSwitchView
  6500.         align: aSwitchView viewport topLeft
  6501.         with: aView window topLeft.
  6502.     aSwitchView _ self buildClassSwitchView: aBrowser.
  6503.     aView
  6504.         addSubView: aSwitchView
  6505.         align: aSwitchView viewport topLeft
  6506.         with: aView lastSubView viewport topRight.
  6507.     ^aView!
  6508. buildInstanceSwitchView: aBrowser
  6509.  
  6510.     | aSwitchView |
  6511.     aSwitchView _ SwitchView new.
  6512.     aSwitchView model: aBrowser.
  6513.     aSwitchView controller: LockedSwitchController new.
  6514.     aSwitchView borderWidthLeft: 0 right: 1 top: 0 bottom: 0.
  6515.     aSwitchView selector: #instanceMessagesIndicated.
  6516.     aSwitchView controller selector: #indicateInstanceMessages.
  6517.     aSwitchView window: (0 @ 0 extent: 25 @ 8).
  6518.     aSwitchView label: 'instance' asParagraph.
  6519.     ^aSwitchView!
  6520. buildMessageCategoryListView: aBrowser
  6521.  
  6522.     | aMessageCategoryListView |
  6523.     aMessageCategoryListView _ MessageCategoryListView new.
  6524.     aMessageCategoryListView model: aBrowser.
  6525.     aMessageCategoryListView window: (0 @ 0 extent: 50 @ 70).
  6526.     aMessageCategoryListView borderWidthLeft: 2 right: 0 top: 2 bottom: 2.
  6527.     ^aMessageCategoryListView!
  6528. buildMessageListView: aBrowser
  6529.     | aMessageListView |
  6530.  
  6531.     aMessageListView _ MessageListView new.
  6532.     aMessageListView model: aBrowser.
  6533.     aMessageListView window: (0 @ 0 extent: 50 @ 70).
  6534.     aMessageListView borderWidthLeft: 2 right: 2 top: 2 bottom: 2.
  6535.     ^ aMessageListView!
  6536. buildSystemCategoryListView: aBrowser
  6537.  
  6538.     | aSystemCategoryListView |
  6539.     aSystemCategoryListView _ SystemCategoryListView new.
  6540.     aSystemCategoryListView model: aBrowser.
  6541.     aSystemCategoryListView window: (0 @ 0 extent: 50 @ 70).
  6542.     aSystemCategoryListView borderWidthLeft: 2 right: 0 top: 2 bottom: 2.
  6543.     ^aSystemCategoryListView! !Switch subclass: #Button
  6544.     instanceVariableNames: ''
  6545.     classVariableNames: ''
  6546.     poolDictionaries: ''
  6547.     category: 'Interface-Menus'!
  6548. Button comment:
  6549. 'I am a Switch that turns off automatically after being turned on, that is, I act like a push-button switch.'!
  6550.  
  6551. !Button methodsFor: 'state'!
  6552. turnOff
  6553.     "Sets the state of the receiver to 'off'. The off action of the receiver is not  
  6554.     executed."
  6555.  
  6556.     on _ false!
  6557. turnOn
  6558.     "The receiver remains in the 'off' state'."
  6559.  
  6560.     self doAction: onAction.
  6561.     self doAction: offAction! !
  6562. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  6563.  
  6564. Button class
  6565.     instanceVariableNames: ''!
  6566.  
  6567. !Button class methodsFor: 'instance creation'!
  6568. newOn 
  6569.     "Refer to the comment in Switch|newOn."
  6570.  
  6571.     self error: 'Buttons cannot be created in the on state'.
  6572.     ^nil! !ArrayedCollection variableByteSubclass: #ByteArray
  6573.     instanceVariableNames: ''
  6574.     classVariableNames: ''
  6575.     poolDictionaries: ''
  6576.     category: 'Collections-Arrayed'!
  6577. ByteArray comment:
  6578. 'I represent an ArrayedCollection whose elements can only be integers between 0 and 255. They are stored two bytes to a word.'!
  6579.  
  6580. !ByteArray methodsFor: 'accessing'!
  6581. doubleWordAt: i 
  6582.     "Answer the value of the double word (4 bytes) starting at byte index i."
  6583.  
  6584.     | b0 b1 b2 w |
  6585.     "Primarily for reading socket #s in Pup headers"
  6586.     b0 _ self at: i.  
  6587.     b1 _ self at: i+1.  
  6588.     b2 _ self at: i+2.  
  6589.     w _ self at: i+3.
  6590.     "Following sequence minimizes LargeInteger arithmetic for small results."
  6591.     b2=0 ifFalse: [w _ (b2 bitShift: 8) + w].
  6592.     b1=0 ifFalse: [w _ (b1 bitShift: 16) + w].
  6593.     b0=0 ifFalse: [w _ (b0 bitShift: 24) + w].
  6594.     ^w!
  6595. doubleWordAt: i put: value 
  6596.     "Set the value of the double word (4 bytes) starting at byte index i."
  6597.  
  6598.     | w |
  6599.     "Primarily for setting socket #s in Pup headers"
  6600.     w _ value asInteger.
  6601.     self at: i put: (w digitAt: 4).
  6602.     self at: i + 1 put: (w digitAt: 3).
  6603.     self at: i + 2 put: (w digitAt: 2).
  6604.     self at: i + 3 put: (w digitAt: 1)!
  6605. wordAt: i 
  6606.     "Answer the value of the word (2 bytes) starting at index i."
  6607.  
  6608.     | j |
  6609.     j _ i + i.
  6610.     ^((self at: j - 1) bitShift: 8) + (self at: j)!
  6611. wordAt: i put: v 
  6612.     "Set the value of the word (2 bytes) starting at index i."
  6613.  
  6614.     | j |
  6615.     j _ i + i.
  6616.     self at: j - 1 put: ((v bitShift: -8) bitAnd: 8r377).
  6617.     self at: j put: (v bitAnd: 8r377)! !
  6618.  
  6619. !ByteArray methodsFor: 'private'!
  6620. defaultElement
  6621.  
  6622.     ^0!
  6623. printOn: aStream 
  6624.     "Refer to the comment in Object|printOn:."
  6625.  
  6626.     | tooMany |
  6627.     tooMany _ aStream position + self maxPrint.
  6628.     aStream nextPutAll: self class name, ' ('.
  6629.     self do: 
  6630.         [:element | 
  6631.         aStream position > tooMany ifTrue: [aStream nextPutAll: '...etc...)'. ^self].
  6632.         element asCharacter printOn: aStream.
  6633.         aStream space].
  6634.     aStream nextPut: $)!
  6635. replaceFrom: start to: stop with: replacement startingAt: repStart 
  6636.     "Primitive. This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the collection, replacement. Answer the receiver. Range checks are performed in the primitive only. Optional. See Object documentation whatIsAPrimitive."
  6637.     <primitive: 105>
  6638.     super replaceFrom: start to: stop with: replacement startingAt: repStart! !ParseNode subclass: #CascadeNode
  6639.     instanceVariableNames: 'receiver messages '
  6640.     classVariableNames: ''
  6641.     poolDictionaries: ''
  6642.     category: 'System-Compiler'!
  6643. CascadeNode comment: 'The first message has the common receiver, the rest have receiver == nil, which signifies cascading.'!
  6644.  
  6645. !CascadeNode methodsFor: 'initialize-release'!
  6646. receiver: receivingObject messages: msgs
  6647.     " Transcript show: 'abc'; cr; show: 'def' "
  6648.  
  6649.     receiver _ receivingObject.
  6650.     messages _ msgs! !
  6651.  
  6652. !CascadeNode methodsFor: 'code generation'!
  6653. emitForValue: stack on: aStream
  6654.  
  6655.     receiver emitForValue: stack on: aStream.
  6656.     1 to: messages size - 1 do: 
  6657.         [:i | 
  6658.         aStream nextPut: Dup.
  6659.         stack push: 1.
  6660.         (messages at: i) emitForValue: stack on: aStream.
  6661.         aStream nextPut: Pop.
  6662.         stack pop: 1].
  6663.     messages last emitForValue: stack on: aStream!
  6664. sizeForValue: encoder
  6665.  
  6666.     | size |
  6667.     size _ (receiver sizeForValue: encoder) + (messages size - 1 * 2).
  6668.     messages do: [:aMessage | size _ size + (aMessage sizeForValue: encoder)].
  6669.     ^size! !
  6670.  
  6671. !CascadeNode methodsFor: 'printing'!
  6672. printOn: aStream indent: level
  6673.     self printOn: aStream indent: level precedence: 0!
  6674. printOn: aStream indent: level precedence: p
  6675.     | thisPrec |
  6676.     p > 0 ifTrue: [aStream nextPut: $(].
  6677.     thisPrec _ messages first precedence.
  6678.     receiver printOn: aStream indent: level precedence: thisPrec.
  6679.     1 to: messages size do: 
  6680.         [:i | 
  6681.         (messages at: i) printOn: aStream indent: level.
  6682.         i < messages size
  6683.             ifTrue: [aStream nextPut: $;.
  6684.                     thisPrec >= 2 ifTrue: [aStream crtab: level]]].
  6685.     p > 0 ifTrue: [aStream nextPut: $)]! !
  6686.  
  6687. !CascadeNode methodsFor: 'equation translation'!
  6688. collectVariables
  6689.     ^messages inject: receiver collectVariables into: [:array :message | array, message collectVariables]!
  6690. copyReplacingVariables: varDict 
  6691.     | t1 t2 |
  6692.     t1 _ receiver copyReplacingVariables: varDict.
  6693.     t2 _ messages collect: [:m | m copyReplacingVariables: varDict].
  6694.     ^self class new receiver: t1 messages: t2!
  6695. specificMatch: aTree using: matchDict 
  6696.     (receiver match: aTree receiver using: matchDict)
  6697.         ifFalse: [^false].
  6698.     messages with: aTree messages do: [:m1 :m2 |
  6699.             (m1 match: m2 using: matchDict) ifFalse: [^false]].
  6700.     ^true! !
  6701.  
  6702. !CascadeNode methodsFor: 'C translation'! !StringHolder subclass: #ChangeList
  6703.     instanceVariableNames: 'changeList list listIndex listSelections file hiddenList realIndex '
  6704.     classVariableNames: ''
  6705.     poolDictionaries: ''
  6706.     category: 'Interface-Changes'!
  6707. ChangeList comment:
  6708. 'A ChangeList represents a list of changes recorded on a file in fileOut
  6709. format.  It holds three lists:
  6710.     changeList - a list of ChangeRecords
  6711.     list - a list of one-line printable headers
  6712.     hiddenList - a list of Booleans.
  6713. Any item with a true in hiddenList will not be visible in the list.
  6714. In effect, there a two lists, one hidden and one visible.  They can
  6715. be exchanged by the -show hidden- command, and visible items
  6716. can be put into the hidden list with the -hide selection- command.'!
  6717.  
  6718. !ChangeList methodsFor: 'initialization-release'!
  6719. addItem: item text: text
  6720.     | cr |
  6721.     cr _ Character cr.
  6722.     changeList addLast: item.
  6723.     list addLast: (text collect: [:x | x = cr ifTrue: [$/] ifFalse: [x]])! !
  6724.  
  6725. !ChangeList methodsFor: 'scanning'!
  6726. scanCategory  "or other preamble"
  6727.     | itemPosition item tokens |
  6728.     itemPosition _ file position.
  6729.     item _ file nextChunk.
  6730.     tokens _ Scanner new scanTokens: item.
  6731.     (tokens size >= 3 and: [(tokens at: 2) = #methodsFor:])
  6732.         ifTrue: [self scanCategory: (tokens at: 3) class: (tokens at: 1) meta: false]
  6733.         ifFalse: [(tokens size >= 4 and: [(tokens at: 3) = #methodsFor:])
  6734.             ifTrue: [self scanCategory: (tokens at: 4) class: (tokens at: 1) meta: true]
  6735.             ifFalse: [self addItem: (ChangeRecord new file: file position: itemPosition type: #preamble) text: ('preamble: ' , item contractTo: 50)]]!
  6736. scanCategory: category class: class meta: meta
  6737.     | itemPosition method |
  6738.     [itemPosition _ file position.
  6739.     method _ file nextChunk.
  6740.     method size > 0]                        "done when double terminators"
  6741.         whileTrue:
  6742.         [self addItem: (ChangeRecord new file: file position: itemPosition type: #method
  6743.                             class: class category: category meta: meta)
  6744.             text: 'method: ' , class , (meta ifTrue: [' class '] ifFalse: [' ']) , (Parser new parseSelector: method)]!
  6745. scanFile: aFile from: startPosition to: stopPosition
  6746.     | itemPosition item prevChar |
  6747.     file _ aFile.
  6748.     changeList _ OrderedCollection new.
  6749.     list _ OrderedCollection new.
  6750.     listIndex _ 0.
  6751.     file position: startPosition.
  6752. 'Scanning changes...'
  6753.     displayProgressAt: Sensor cursorPoint
  6754.     from: startPosition to: stopPosition
  6755.     during: [:bar |
  6756.     [file position < stopPosition]
  6757.         whileTrue:
  6758.         [bar value: file position.
  6759.         [file atEnd not and: [file peek isSeparator]]
  6760.                 whileTrue: [prevChar _ file next].
  6761.         (file peekFor: $!!)
  6762.         ifTrue:
  6763.             [prevChar = Character cr ifTrue: [self scanCategory]]
  6764.         ifFalse:
  6765.             [itemPosition _ file position.
  6766.             item _ file nextChunk.
  6767.             item size > 0 ifTrue:
  6768.                 [self addItem: (ChangeRecord new file: file position: itemPosition type: #doIt)
  6769.                     text: 'do it: ' , (item contractTo: 50)]]]].
  6770.     listSelections _ Array new: list size withAll: false!
  6771. scanVersionsOf: method class: class meta: meta
  6772.         category: category selector: selector
  6773.     | sources position prevPos prevFileIndex preamble tokens sourceFilesCopy |
  6774.     changeList _ OrderedCollection new.
  6775.     list _ OrderedCollection new.
  6776.     listIndex _ 0.
  6777.     position _ method filePosition.
  6778.     sourceFilesCopy _ SourceFiles collect:
  6779.         [:x | x isNil ifTrue: [ nil ]
  6780.                 ifFalse: [x readOnlyCopy]].
  6781.     file _ sourceFilesCopy at: method fileIndex.
  6782.     [position notNil & file notNil]
  6783.         whileTrue:
  6784.         [file position: (0 max: position-150).  "Skip back to before the preamble"
  6785.         [file position < (position-1)]  "then pick it up from the front"
  6786.             whileTrue: [preamble _ file nextChunk].
  6787.         prevPos _ nil.
  6788.         (preamble at: (preamble findLast: [:c | c isAlphaNumeric]))
  6789.             isDigit  "Only tokenize if preamble ends with a digit"
  6790.             ifTrue: [tokens _ Scanner new scanTokens: preamble]
  6791.             ifFalse: [tokens _ Array new  "ie cant be back ref"].
  6792.         ((tokens size between: 7 and: 8)
  6793.             and: [(tokens at: tokens size-5) = #methodsFor:])
  6794.             ifTrue:
  6795.                 [prevPos _ tokens at: tokens size-2.
  6796.                 prevPos = 0
  6797.                     ifTrue: [prevPos _ nil] "Zero means no source"
  6798.                     ifFalse: [prevFileIndex _ tokens last]].
  6799.         self addItem:
  6800.                 (ChangeRecord new file: file position: position
  6801.                     type: #method class: class name category: category meta: meta)
  6802.             text: class name , (meta ifTrue: [' class '] ifFalse: [' ']) , selector.
  6803.         position _ prevPos.
  6804.         prevPos notNil ifTrue:
  6805.             [file _ sourceFilesCopy at: prevFileIndex]].
  6806.     sourceFilesCopy do: [:x | x notNil ifTrue: [x close]].
  6807.     listSelections _ Array new: list size withAll: false!
  6808. toggleListIndex: newListIndex
  6809.     "2/1/96 sw: removed changed: call, to avoid extra refresh whenever selection changes. The call had been 'self changed: #contents', but everything appears to work fine with it omitted."
  6810.  
  6811.     (listIndex ~= 0 and: [listIndex ~= newListIndex]) ifTrue:
  6812.         [listSelections at: listIndex put: false].  "turn off old selection if was on"
  6813.     listSelections at: newListIndex  "Complement selection state"
  6814.             put: (listSelections at: newListIndex) not.
  6815.     listIndex _ (listSelections at: newListIndex)
  6816.         ifTrue: [newListIndex]  "and set selection index accordingly"
  6817.         ifFalse: [0].
  6818.     self changed: #listIndex! !
  6819.  
  6820. !ChangeList methodsFor: 'menu actions'!
  6821. deselectAll 
  6822.     listIndex _ 0.
  6823.     listSelections atAllPut: false.
  6824.     self changed: #allSelections!
  6825. fileInSelections 
  6826.     listSelections with: changeList do: 
  6827.         [:selected :item | selected ifTrue: [item fileIn]]!
  6828. fileOutSelections 
  6829.     | f |
  6830.     f _ FileStream newFileNamed: (FillInTheBlank request: 'Enter file name' initialAnswer: 'Filename.st').
  6831.     listSelections with: changeList do: 
  6832.         [:selected :item | selected ifTrue: [item fileOutOn: f]].
  6833.     f close!
  6834. removeDoIts
  6835.     "Remove doits from the receiver, other than initializes. 1/26/96 sw"
  6836.  
  6837.     | newChangeList newList |
  6838.  
  6839.     newChangeList _ OrderedCollection new.
  6840.     newList _ OrderedCollection new.
  6841.  
  6842.     changeList with: list do:
  6843.         [:chRec :str |
  6844.             (chRec type ~~ #doIt or:
  6845.                 [str endsWith: 'initialize'])
  6846.                     ifTrue:
  6847.                         [newChangeList add: chRec.
  6848.                         newList add: str]].
  6849.     newChangeList size < changeList size
  6850.         ifTrue:
  6851.             [changeList _ newChangeList.
  6852.             list _ newList.
  6853.             listIndex _ 0.
  6854.             listSelections _ Array new: list size withAll: false].
  6855.     self changed: #list
  6856.  
  6857.     !
  6858. removeOlderMethodVersions
  6859.     "Remove older versions of entries from the receiver.  1/26/96 sw:"
  6860.  
  6861.     | newChangeList newList found |
  6862.  
  6863.     newChangeList _ OrderedCollection new.
  6864.     newList _ OrderedCollection new.
  6865.     found _ OrderedCollection new.
  6866.  
  6867.     changeList reverseWith: list do:
  6868.         [:chRec :str |
  6869.             (found includes: str)
  6870.                 ifFalse:
  6871.                     [found add: str.
  6872.                     newChangeList add: chRec.
  6873.                     newList add: str]].
  6874.     newChangeList size < changeList size
  6875.         ifTrue:
  6876.             [changeList _ newChangeList reversed.
  6877.             list _ newList reversed.
  6878.             listIndex _ 0.
  6879.             listSelections _ Array new: list size withAll: false].
  6880.     self changed: #list!
  6881. removeSelections
  6882.     "Remove the selected items from the receiver.  9/18/96 sw"
  6883.  
  6884.     | newChangeList newList |
  6885.  
  6886.     newChangeList _ OrderedCollection new.
  6887.     newList _ OrderedCollection new.
  6888.  
  6889.     1 to: changeList size do:
  6890.         [:i | (listSelections at: i) ifFalse:
  6891.             [newChangeList add: (changeList at: i).
  6892.             newList add: (list at: i)]].
  6893.     newChangeList size < changeList size
  6894.         ifTrue:
  6895.             [changeList _ newChangeList.
  6896.             list _ newList.
  6897.             listIndex _ 0.
  6898.             listSelections _ Array new: list size withAll: false].
  6899.     self changed: #list
  6900.  
  6901.     !
  6902. selectAll
  6903.     listIndex _ 0.
  6904.     listSelections atAllPut: true.
  6905.     self changed: #allSelections!
  6906. selectConflicts
  6907.     "Selects all method definitions for which there is ALSO an entry in changes"
  6908.     | change class systemChanges |
  6909.     Cursor read showWhile: 
  6910.     [1 to: changeList size do:
  6911.         [:i | change _ changeList at: i.
  6912.         listSelections at: i put:
  6913.             (change type = #method
  6914.             and: [(class _ change methodClass) notNil
  6915.             and: [(Smalltalk changes atSelector: change methodSelector
  6916.                         class: class) ~~ #none]])]].
  6917.     self changed: #allSelections!
  6918. selectConflicts: changeSetOrList
  6919.     "Selects all method definitions for which there is ALSO an entry in the specified changeSet or changList"
  6920.     | change class systemChanges |
  6921.     Cursor read showWhile: 
  6922.     [(changeSetOrList isKindOf: ChangeSet) ifTrue: [
  6923.     1 to: changeList size do:
  6924.         [:i | change _ changeList at: i.
  6925.         listSelections at: i put:
  6926.             (change type = #method
  6927.             and: [(class _ change methodClass) notNil
  6928.             and: [(changeSetOrList atSelector: change methodSelector
  6929.                         class: class) ~~ #none]])]]
  6930.     ifFalse: ["a ChangeList"
  6931.     1 to: changeList size do:
  6932.         [:i | change _ changeList at: i.
  6933.         listSelections at: i put:
  6934.             (change type = #method
  6935.             and: [(class _ change methodClass) notNil
  6936.             and: [changeSetOrList list includes: (list at: i)]])]]
  6937.     ].
  6938.     self changed: #allSelections!
  6939. selectConflictsWith
  6940.     "Selects all method definitions for which there is ALSO an entry in the specified changeSet or changList chosen by the user. 4/11/96 tk"
  6941.     | aStream all index  coll |
  6942.     aStream _ WriteStream on: (String new: 200).
  6943.     all _ ChangeSet allInstances.
  6944.     all do:
  6945.         [:sel | aStream nextPutAll: (sel name contractTo: 40); cr].
  6946.     coll _ ChangeList allInstances.
  6947.     coll do:
  6948.         [:sel | aStream nextPutAll: (sel file name); cr.
  6949.             all addLast: sel].
  6950.     aStream skip: -1.
  6951.     index _ (PopUpMenu labels: aStream contents) startUp.
  6952.     index > 0 ifTrue: [
  6953.         self selectConflicts: (all at: index)].!
  6954. selectUnchangedMethods
  6955.     "Selects all method definitions for which there is already a method in the current image, whose source is exactly the same.  9/18/96 sw"
  6956.     | change class systemChanges |
  6957.     Cursor read showWhile: 
  6958.     [1 to: changeList size do:
  6959.         [:i | change _ changeList at: i.
  6960.         listSelections at: i put:
  6961.             ((change type = #method and:
  6962.                 [(class _ change methodClass) notNil]) and:
  6963.                     [(class includesSelector: change methodSelector) and:
  6964.                         [change string = (class sourceCodeAt: change methodSelector)]])]].
  6965.     self changed: #allSelections! !
  6966.  
  6967. !ChangeList methodsFor: 'viewing access'!
  6968. contents
  6969.     ^ listIndex = 0
  6970.         ifTrue: ['']
  6971.         ifFalse: [(changeList at: listIndex) string]!
  6972. contents: aString
  6973.     listIndex = 0
  6974.         ifTrue: [self changed: #flash. ^ false]
  6975.         ifFalse: [Cursor read showWhile: [(changeList at: listIndex) fileIn].
  6976.                 ^ true]!
  6977. defaultBackgroundColor
  6978.     ^ #lightBlue!
  6979. list
  6980.     ^ list!
  6981. listIndex
  6982.     ^ listIndex!
  6983. listSelectionAt: index
  6984.     ^ listSelections at: index!
  6985. listSelectionAt: index put: value
  6986.     listIndex _ 0.
  6987.     ^ listSelections at: index put: value! !
  6988.  
  6989. !ChangeList methodsFor: 'accessing'!
  6990. changeList
  6991.     ^ changeList!
  6992. file
  6993.     ^file! !
  6994. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  6995.  
  6996. ChangeList class
  6997.     instanceVariableNames: ''!
  6998.  
  6999. !ChangeList class methodsFor: 'public access'!
  7000. browseFile: fileName    "ChangeList browseFile: 'AutoDeclareFix.st'"
  7001.     "Opens a changeList on the file named fileName"
  7002.     | changesFile changeList |
  7003.     changesFile _ FileStream readOnlyFileNamed: fileName.
  7004.     Cursor read showWhile:
  7005.         [changeList _ self new
  7006.             scanFile: changesFile from: 0 to: changesFile size].
  7007.     changesFile close.
  7008.     self open: changeList name: fileName , ' log'!
  7009. browseRecent: charCount    "ChangeList browseRecent: 5000"
  7010.     "Opens a changeList on the end of the changes log file"
  7011.     | changesFile changeList end |
  7012.     changesFile _ (SourceFiles at: 2) readOnlyCopy.
  7013.     end _ changesFile size.
  7014.     Cursor read showWhile:
  7015.         [changeList _ self new
  7016.             scanFile: changesFile from: (0 max: end-charCount) to: end].
  7017.     changesFile close.
  7018.     self open: changeList name: 'Recent changes'!
  7019. browseRecentLog    "ChangeList browseRecentLog"
  7020.     "Browse changes logged since last quit"
  7021.     ^ self browseRecent: (SourceFiles at: 2) size - Smalltalk lastQuitLogPosition!
  7022. browseVersionsOf: method class: class meta: meta
  7023.         category: category selector: selector 
  7024.     | changeList |
  7025.     Cursor read showWhile:
  7026.         [changeList _ self new
  7027.             scanVersionsOf: method class: class meta: meta
  7028.             category: category selector: selector].
  7029.     self openVersions: changeList name: 'Recent versions of ' , selector!
  7030. versionCountForSelector: aSelector class: aClass
  7031.     "Answer the number of versions known to the system for the given class and method, including the current version.  A result of greater than one means that there is at least one superseded version.  6/28/96 sw"
  7032.     
  7033.     | method |
  7034.     method _ aClass compiledMethodAt: aSelector.
  7035.     ^ (self new
  7036.             scanVersionsOf: method class: aClass meta: aClass isMeta
  7037.             category: nil selector: aSelector) list size! !
  7038.  
  7039. !ChangeList class methodsFor: 'instance creation'!
  7040. open: aChangeList name: aString 
  7041.     "Open a view for the changeList, with a multiple selection list. "
  7042.     ^ self open: aChangeList name: aString
  7043.         withListView: (ListViewOfMany new controller: ChangeListController new)!
  7044. open: aChangeList name: aString withListView: aListView
  7045.     "Create a standard system view for the messageSet, whose label is aString.
  7046.     The listView supplied may be either single or multiple selection type"
  7047.     | topView codeView |
  7048.     topView _ StandardSystemView new.
  7049.     topView model: aChangeList.
  7050.     topView label: aString.
  7051.     topView minimumSize: 180 @ 120.
  7052.     aListView model: aChangeList.
  7053.     aListView list: aChangeList list.
  7054.     aListView window: (0 @ 0 extent: 180 @ 100).
  7055.     aListView borderWidthLeft: 2 right: 2 top: 2 bottom: 0.
  7056.     topView addSubView: aListView.
  7057.     codeView _ StringHolderView new.
  7058.     codeView model: aChangeList.
  7059.     codeView window: (0 @ 0 extent: 180 @ 300).
  7060.     codeView borderWidthLeft: 2 right: 2 top: 2 bottom: 2.
  7061.     topView
  7062.         addSubView: codeView
  7063.         align: codeView viewport topLeft
  7064.         with: aListView viewport bottomLeft.
  7065.     topView controller open !
  7066. openVersions: aChangeList name: aString 
  7067.     "Open a standard system view for the changeList with a normal ListView"
  7068.     ^ self open: aChangeList name: aString
  7069.         withListView: ListView new! !ListControllerOfMany subclass: #ChangeListController
  7070.     instanceVariableNames: ''
  7071.     classVariableNames: 'YellowButtonMenu YellowButtonMessages '
  7072.     poolDictionaries: ''
  7073.     category: 'Interface-Changes'!
  7074.  
  7075. !ChangeListController methodsFor: 'menu actions'!
  7076. deselectAll
  7077.     self controlTerminate.
  7078.     model deselectAll.
  7079.     self controlInitialize!
  7080. fileInSelections
  7081.     self controlTerminate.
  7082.     model fileInSelections.
  7083.     self controlInitialize!
  7084. fileOutSelections
  7085.     self controlTerminate.
  7086.     model fileOutSelections.
  7087.     self controlInitialize!
  7088. removeDoIts
  7089.     "Remove the doits from the browser.  1/26/96 sw"
  7090.  
  7091.     self controlTerminate.
  7092.     model removeDoIts.
  7093.     self controlInitialize!
  7094. removeOlderMethodVersions
  7095.     "Remove older method versions from the browser.  1/26/96 sw"
  7096.  
  7097.     self controlTerminate.
  7098.     model removeOlderMethodVersions.
  7099.     self controlInitialize!
  7100. removeSelections
  7101.     "Remove all selected items from the list.  9/18/96 sw"
  7102.  
  7103.     self controlTerminate.
  7104.     model removeSelections.
  7105.     self controlInitialize!
  7106. selectAll
  7107.     self controlTerminate.
  7108.     model selectAll.
  7109.     self controlInitialize!
  7110. selectConflicts
  7111.     self controlTerminate.
  7112.     model selectConflicts.
  7113.     self controlInitialize!
  7114. selectConflictsWith
  7115.     self controlTerminate.
  7116.     model selectConflictsWith.
  7117.     self controlInitialize!
  7118. selectUnchangedMethods
  7119.     "Select all methods in the receiver whose source is identical to the corresponding source currently in the image.  9/18/96 sw"
  7120.  
  7121.     self controlTerminate.
  7122.     model selectUnchangedMethods.
  7123.     self controlInitialize! !
  7124.  
  7125. !ChangeListController methodsFor: 'initialization'!
  7126. initialize
  7127.     super initialize.
  7128.     self initializeYellowButtonMenu!
  7129. initializeYellowButtonMenu
  7130.     self yellowButtonMenu: YellowButtonMenu 
  7131.         yellowButtonMessages: YellowButtonMessages! !
  7132. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  7133.  
  7134. ChangeListController class
  7135.     instanceVariableNames: ''!
  7136.  
  7137. !ChangeListController class methodsFor: 'class initialization'!
  7138. initialize
  7139.     "Class initialization: initialize the Yellow Button menu.
  7140.      1/26/96 sw: added the remove items
  7141.      9/18/96 sw: added selectUnchangedMethods and removeSelections"
  7142.  
  7143.     YellowButtonMenu _ PopUpMenu 
  7144.         labels:
  7145. 'fileIn selections
  7146. fileOut selections...
  7147. select conflicts
  7148. select conflicts with
  7149. select unchanged methods
  7150. select all
  7151. deselect all
  7152. remove doIts
  7153. remove older versions
  7154. remove selections'
  7155.         lines: #(2 6).
  7156.     YellowButtonMessages _ #(fileInSelections fileOutSelections selectConflicts selectConflictsWith selectUnchangedMethods selectAll deselectAll removeDoIts removeOlderMethodVersions removeSelections)
  7157. "
  7158.     ChangeListController initialize.
  7159.     ChangeListController allInstancesDo:
  7160.         [:x | x initializeYellowButtonMenu].
  7161. "! !
  7162.  
  7163. ChangeListController initialize!
  7164. Object subclass: #ChangeRecord
  7165.     instanceVariableNames: 'file position type class category meta '
  7166.     classVariableNames: ''
  7167.     poolDictionaries: ''
  7168.     category: 'Interface-Changes'!
  7169. ChangeRecord comment:
  7170. 'A ChangeRecord represents a change recorded on a file in fileOut format.
  7171. It includes a type (more needs to be done here), and additional information
  7172. for certain types such as method defs which need class and category.'!
  7173.  
  7174. !ChangeRecord methodsFor: 'access'!
  7175. fileIn
  7176.     | methodClass |
  7177.     Cursor read showWhile:
  7178.         [(methodClass _ self methodClass) notNil ifTrue:
  7179.             [methodClass compile: self string classified: category].
  7180.         type = #doIt ifTrue:
  7181.             [Compiler evaluate: self string]]!
  7182. fileOutOn: f
  7183.     type == #method
  7184.         ifTrue:
  7185.             [f nextPut: $!!.
  7186.             f nextChunkPut: class asString
  7187.                     , (meta ifTrue: [' class methodsFor: ']
  7188.                             ifFalse: [' methodsFor: '])
  7189.                     , category asString printString.
  7190.             f cr]
  7191.         ifFalse:
  7192.             [type == #preamble ifTrue: [f nextPut: $!!]].
  7193.     f nextChunkPut: self string.
  7194.     type == #method ifTrue: [f nextChunkPut: ' '].
  7195.     f cr!
  7196. methodClass 
  7197.     | methodClass |
  7198.     type == #method ifFalse: [^ nil].
  7199.     (Smalltalk includesKey: class asSymbol) ifFalse: [^ nil].
  7200.     methodClass _ Smalltalk at: class asSymbol.
  7201.     meta ifTrue: [^ methodClass class]
  7202.         ifFalse: [^ methodClass]!
  7203. methodSelector
  7204.     type == #method ifFalse: [^ nil].
  7205.     ^ Parser new parseSelector: self string!
  7206. string 
  7207.     | string |
  7208.     file openReadOnly.
  7209.     file position: position.
  7210.     string _ file nextChunk.
  7211.     file close.
  7212.     ^ string!
  7213. type
  7214.     ^ type! !
  7215.  
  7216. !ChangeRecord methodsFor: 'initialization'!
  7217. file: f position: p type: t
  7218.     file _ f.
  7219.     position _ p.
  7220.     type _ t!
  7221. file: f position: p type: t class: c category: cat meta: m
  7222.     self file: f position: p type: t.
  7223.     class _ c.
  7224.     category _ cat.
  7225.     meta _ m! !Object subclass: #ChangeSet
  7226.     instanceVariableNames: 'classChanges methodChanges classRemoves name '
  7227.     classVariableNames: ''
  7228.     poolDictionaries: ''
  7229.     category: 'Kernel-Support'!
  7230. ChangeSet comment:
  7231. 'My instances keep track of the changes made to a system, so the user can make an incremental fileOut. The order in which changes are made is not remembered.'!
  7232.  
  7233. !ChangeSet methodsFor: 'initialize-release'!
  7234. initialize 
  7235.     "Reset the receiver to be empty."
  7236.  
  7237.     self wither.  "Avoid duplicate entries in AllChangeSets if initialize gets called twice"
  7238.     classChanges _ Dictionary new.
  7239.     methodChanges _ Dictionary new.
  7240.     classRemoves _ Set new.
  7241.     name _ ChangeSet defaultName!
  7242. isMoribund
  7243.     "Answer whether the receiver is obsolete and about to die; part of an effort to get such guys cleared out from the change sorter.  2/7/96 sw"
  7244.  
  7245.     ^ name == nil !
  7246. wither
  7247.     "The receiver is to be clobbered.  Clear it out.  2/7/96 sw"
  7248.  
  7249.     classChanges _ nil.
  7250.     methodChanges _ nil.
  7251.     classRemoves _ nil.
  7252.     name _ nil! !
  7253.  
  7254. !ChangeSet methodsFor: 'testing'!
  7255. classChangeAt: className
  7256.     "Return what we know about class changes to this class."
  7257.     ^ classChanges at: className ifAbsent: [Set new].!
  7258. classRemoves
  7259.     ^ classRemoves!
  7260. isEmpty
  7261.     "Answer whether the receiver contains any elements."
  7262.  
  7263.     ^(methodChanges isEmpty and: [classChanges isEmpty]) and: [classRemoves isEmpty]!
  7264. methodChangesAtClass: className
  7265.     "Return what we know about method changes to this class."
  7266.     ^ methodChanges at: className ifAbsent: [Dictionary new].!
  7267. name
  7268.     "The name of this changeSet.
  7269.      2/7/96 sw: If name is nil, we've got garbage.  Help to identify."
  7270.  
  7271.     ^ name == nil
  7272.         ifTrue:
  7273.             ['<no name -- garbage?>']
  7274.         ifFalse:
  7275.             [name]! !
  7276.  
  7277. !ChangeSet methodsFor: 'converting'!
  7278. asSortedCollection
  7279.     "Answer a SortedCollection whose elements are the elements of the 
  7280.     receiver. The sort order is the default less than or equal ordering."
  7281.     | result |
  7282.     result _ SortedCollection new.
  7283.     classChanges associationsDo: 
  7284.         [:clAssoc | 
  7285.         clAssoc value do: 
  7286.             [:changeType | result add: clAssoc key, ' - ', changeType]].
  7287.     methodChanges associationsDo: 
  7288.         [:clAssoc | 
  7289.         clAssoc value associationsDo: 
  7290.             [:mAssoc | result add: clAssoc key, ' ', mAssoc key, ' - ', mAssoc value]].
  7291.     classRemoves do:
  7292.         [:cName | result add: cName  , ' - ', 'remove'].
  7293.     ^ result! !
  7294.  
  7295. !ChangeSet methodsFor: 'change management'!
  7296. absorbChangesInChangeSetsNamed: nameList
  7297.     "Absorb into the receiver all the changes found in  change sets of the given names.  *** classes renamed in aChangeSet may have have problems
  7298. 1/22/96 sw"
  7299.  
  7300.     | aChangeSet |
  7301.     nameList do:
  7302.         [:aName | (aChangeSet _ ChangeSorter changeSetNamed: aName) ~~ nil
  7303.             ifTrue:
  7304.                 [self assimilateAllChangesFoundIn: aChangeSet]]!
  7305. addClass: class 
  7306.     "Include indication that a new class was created."
  7307.  
  7308.     self atClass: class add: #add!
  7309. assimilateAllChangesFoundIn: aChangeSet
  7310.     "Make all changes in aChangeSet take effect on self as it they happened later.  *** classes renamed in aChangeSet may have have problems"
  7311.  
  7312.     | cls info |
  7313.     aChangeSet changedClassNames do: [:className |
  7314.         (cls _ Smalltalk classNamed: className) notNil ifTrue:
  7315.         [info _ aChangeSet classChangeAt: className.
  7316.         info do: [:each | self atClass: cls add: each].
  7317.  
  7318.         info _ aChangeSet methodChanges at: className 
  7319.             ifAbsent: [Dictionary new].
  7320.         info associationsDo: [:assoc |
  7321.             assoc value == #remove ifTrue:
  7322.                     [self removeSelector: assoc key class: cls]
  7323.                 ifFalse: 
  7324.                     [self atSelector: assoc key class: cls put: assoc value]]]].
  7325.     self flag: #developmentNote.  "the following cannot work, since the class will not exist; SW comments this out 8/91 because it thwarts integration!!"
  7326. "aChangeSet classRemoves do:
  7327.         [:removed | self removeClass: (Smalltalk classNamed: removed)] "
  7328. !
  7329. changeClass: class 
  7330.     "Include indication that a class definition has been changed. 
  7331.      6/10/96 sw: don't accumulate this information for classes that don't want logging
  7332.      7/12/96 sw: use wantsChangeSetLogging flag"
  7333.  
  7334.     class wantsChangeSetLogging
  7335.         ifTrue:
  7336.             [self atClass: class add: #change]!
  7337. changedClasses
  7338.     "Answer a OrderedCollection of changed or edited classes.  Not including removed classes.  Sort alphabetically by name."
  7339.  
  7340.     "Much faster to sort names first, then convert back to classes.  Because metaclasses reconstruct their name at every comparison in the sorted collection.
  7341.     8/91 sw chgd to filter out non-existent classes (triggered by problems with class-renames"
  7342.     classChanges == nil ifTrue: [^ OrderedCollection new].
  7343.     ^ self changedClassNames collect: 
  7344.         [:className | Smalltalk classNamed: className]
  7345.             thenSelect:
  7346.                 [:aClass | aClass notNil]!
  7347. changedClassNames
  7348.     "Answer a OrderedCollection of the names of changed or edited classes.  Not including removed classes.  Sort alphabetically."
  7349.  
  7350.     | classes |
  7351.     classes _ SortedCollection new: (methodChanges size + classChanges size) *2.
  7352.     methodChanges keys do: [:className | classes add: className].
  7353.     classChanges keys do: [:className | 
  7354.         (methodChanges includesKey: className) ifFalse: [
  7355.             "avoid duplicates"
  7356.             classes add: className]].
  7357.     ^ classes asOrderedCollection!
  7358. commentClass: class 
  7359.     "Include indication that a class comment has been changed."
  7360.  
  7361.     self atClass: class add: #comment!
  7362. convertClassAddsToClassChanges
  7363.     "1/22/96 sw: as part of a general policy of not storing 'new class' ever, but always having it as a changed class, in order to preserve the specific messages that get changed within this change set, we need to morph existing changesets so that class-adds become class-changes.  This has no method senders, but rather is for invocation from a doit.
  7364.     Note that this adds all the selectors for each added class to the changed method list"
  7365.  
  7366.     | chg aClass |
  7367.     self flag: #scottPrivate.
  7368.     self changedClassNames do:
  7369.         [:aClassName |
  7370.             chg _ self classChangeAt: aClassName.
  7371.             (chg includes: #add) ifTrue:
  7372.                 [chg remove: #add.
  7373.                 chg add: #change.
  7374.                 aClass _ Smalltalk at: aClassName.
  7375.                 aClass selectorsDo:
  7376.                     [:aSelector | self addSelector: aSelector class: aClass].
  7377.                 aClass class selectorsDo:
  7378.                     [:aSelector | self addSelector: aSelector class: aClass class]]]!
  7379. flushClassRemoves
  7380.     classRemoves _ Set new!
  7381. forgetAllChangesFoundIn: aChangeSet
  7382.     "Remove from the receiver all method changes found in aChangeSet. The intention is facilitate the process of factoring a large set of changes into disjoint change sets.  3/13/96 sw.  Note that class-(re)-definition changes are not subtracted out, yet."
  7383.  
  7384.     | cls itsMethodChanges |
  7385.  
  7386.     aChangeSet == self ifTrue: [^ self].
  7387.  
  7388.     aChangeSet changedClassNames do:
  7389.         [:className | (cls _ Smalltalk classNamed: className) ~~ nil
  7390.             ifTrue:
  7391.                 [itsMethodChanges _ aChangeSet methodChanges at: className  ifAbsent: [Dictionary new].
  7392.                 itsMethodChanges associationsDo:
  7393.                     [:assoc | self removeSelectorChanges:  assoc key class: cls]]]!
  7394. removeClass: class 
  7395.     "Include indication that a class has been forgotten."
  7396.     | cName |
  7397.     (self isNew: class) ifTrue:
  7398.         [^ self removeClassChanges: class].     "only remember old classes"
  7399.     cName _ (self atClass: class includes: #rename)     "remember as old name"
  7400.         ifTrue: [self oldNameFor: class]
  7401.         ifFalse: [class name].
  7402.     self removeClassChanges: class.
  7403.     classRemoves add: cName!
  7404. removeClassAndMetaClassChanges: class
  7405.     "Remove all memory of changes associated with this class and its metaclass.  7/18/96 sw"
  7406.  
  7407.     classChanges removeKey: class name ifAbsent: [].
  7408.     methodChanges removeKey: class name ifAbsent: [].
  7409.     classChanges removeKey: class class name ifAbsent: [].
  7410.     methodChanges removeKey: class class name ifAbsent: [].
  7411.     classRemoves remove: class name ifAbsent: [].!
  7412. removeClassChanges: class
  7413.     "Remove all memory of changes associated with this class"
  7414.  
  7415.     classChanges removeKey: class name ifAbsent: [].
  7416.     methodChanges removeKey: class name ifAbsent: [].
  7417.     classRemoves remove: class name ifAbsent: [].!
  7418. removeNamedClassChanges: className
  7419.     "Remove all memory of changes associated with this class name.
  7420.     This is here as removeClassChanges: will not work if the class
  7421.     has been removed."
  7422.  
  7423.     classChanges removeKey: className ifAbsent: [].
  7424.     methodChanges removeKey: className ifAbsent: [].
  7425.     classRemoves remove: className ifAbsent: [].!
  7426. renameClass: class as: newName 
  7427.     "Include indication that a class has been renamed."
  7428.  
  7429.     | value |
  7430.     (self atClass: class includes: #rename) ifFalse:
  7431.         [self atClass: class add: 'oldName: ', class name.     "only original name matters"
  7432.         self atClass: class add: #rename].
  7433.      "copy changes using new name (metaclass too)"
  7434.     (Array with: classChanges with: methodChanges) do:
  7435.         [:changes |
  7436.         (value _ changes at: class name ifAbsent: [nil]) == nil ifFalse:
  7437.             [changes at: newName put: value.
  7438.             changes removeKey: class name].
  7439.         (value _ changes at: class class name ifAbsent: [nil]) == nil ifFalse:
  7440.             [changes at: (newName, ' class') put: value.
  7441.             changes removeKey: class class name]]!
  7442. reorganizeClass: class 
  7443.     "Include indication that a class was reorganized."
  7444.  
  7445.     self atClass: class add: #reorganize! !
  7446.  
  7447. !ChangeSet methodsFor: 'method changes'!
  7448. addSelector: selector class: class 
  7449.     "Include indication that a method has been added.
  7450.      5/16/96 sw: tell Utilities of the change so it can put up an in-order browser on recent submissions."
  7451.  
  7452.     Utilities noteMethodSubmission: selector forClass: class name.
  7453.     self atSelector: selector class: class put: #add!
  7454. allMessagesForAddedClasses
  7455.     | messageList  mAssoc |
  7456.     "Smalltalk changes allMessagesForAddedClasses"
  7457.     messageList _ SortedCollection new.
  7458.     classChanges associationsDo:
  7459.         [:clAssoc |
  7460.         (clAssoc value includes: #add)
  7461.             ifTrue:
  7462.                 [(Smalltalk at: clAssoc key) selectorsDo:
  7463.                     [:aSelector | 
  7464.                         messageList add: clAssoc key asString, ' ' , aSelector].
  7465.                 (Smalltalk at: clAssoc key) class selectorsDo:
  7466.                     [:aSelector | 
  7467.                         messageList add: clAssoc key asString, ' class ' , aSelector]]].
  7468.     ^ messageList asArray!
  7469. browseMessagesWithPriorVersions
  7470.     "Open a message list browser on the new and changed methods in the receiver which have at least one prior version.  6/28/96 sw"
  7471.  
  7472.     | aList aSelector aClass |
  7473.  
  7474.     aList _ self changedMessageListAugmented select:
  7475.         [:msg |  Utilities setClassAndSelectorFrom: msg in: 
  7476.                 [:cl :sl | aClass _ cl.  aSelector _ sl].
  7477.             (ChangeList versionCountForSelector: aSelector class: aClass) > 1].
  7478.     aList size > 0 ifFalse: [self inform: 'None!!'.  ^ nil].
  7479.     Smalltalk browseMessageList: aList name: (self name, ' methods that have prior versions')!
  7480. changedMessageList
  7481.     "Used by a message set browser to access the list view information."
  7482.  
  7483.     | messageList |
  7484.     messageList _ SortedCollection new.
  7485.     methodChanges associationsDo: 
  7486.         [:clAssoc | 
  7487.         clAssoc value associationsDo: 
  7488.             [:mAssoc |
  7489.             mAssoc value = #remove ifFalse:
  7490.                 [messageList add: clAssoc key asString, ' ' , mAssoc key]]].
  7491.     ^messageList asArray!
  7492. changedMessageListAugmented
  7493.     "In addition to changedMessageList, put all messages for all added classes in the ChangeSet."
  7494.     ^ self changedMessageList asArray, self allMessagesForAddedClasses!
  7495. changeSelector: selector class: class 
  7496.     "Include indication that a method has been edited. 
  7497.      5/16/96 sw: tell Utilities of the change so it can put up an in-order browser on recent submissions."
  7498.  
  7499.     Utilities noteMethodSubmission: selector forClass: class name.
  7500.     (self atSelector: selector class: class) = #add 
  7501.         ifFalse: [self atSelector: selector class: class put: #change]
  7502.             "Don't forget a method is new just because it's been changed"!
  7503. removeSelector: selector class: class 
  7504.     "Include indication that a method has been forgotten."
  7505.  
  7506.     (self atSelector: selector class: class) = #add
  7507.         ifTrue: [self removeSelectorChanges: selector 
  7508.                     class: class]                    "Forgot a new method, no-op"
  7509.         ifFalse: [self atSelector: selector
  7510.                     class: class
  7511.                     put: #remove]!
  7512. removeSelectorChanges: selector class: class 
  7513.     "Remove all memory of changes associated with the argument, selector, in 
  7514.     this class."
  7515.  
  7516.     | dictionary |
  7517.     dictionary _ methodChanges at: class name ifAbsent: [^self].
  7518.     dictionary removeKey: selector ifAbsent: [].
  7519.     dictionary isEmpty ifTrue: [methodChanges removeKey: class name]!
  7520. selectorsInClass: aClass
  7521.     "Used by a ChangeSorter to access the list methods."
  7522.     "later include class changes"
  7523.     ^ (methodChanges at: aClass ifAbsent: [^#()]) keys! !
  7524.  
  7525. !ChangeSet methodsFor: 'fileIn/Out'!
  7526. fileOut
  7527.     "File out the receiver, to a file whose name is a function of the change-set name and of the date and the time.  1/18/96 sw
  7528.  2/4/96 sw: show write cursor
  7529.     5/30/96 sw: put a dot before the date/time stamp"
  7530.  
  7531.     | file |
  7532.     Cursor write showWhile:
  7533.         [file _ FileStream newFileNamed: ((self name, '.', Utilities dateTimeSuffix, '.cs') truncateTo: 27).
  7534.         file header; timeStamp.
  7535.         self fileOutOn: file.
  7536.         file trailer; close]!
  7537. fileOutChangesFor: class on: stream 
  7538.     "Write out all the changes the receiver knows about this class.
  7539.      5/15/96 sw: altered to call fileOutClassModifications:on: rather than fileOutClassChanges:on:, so that class headers won't go out as part of this process (they no go out at the beginning of the fileout"
  7540.  
  7541.     | changes |
  7542.                     "first file out class changes"
  7543.     self fileOutClassModifications: class on: stream.
  7544.                     "next file out changed methods"
  7545.     changes _ OrderedCollection new.
  7546.     (methodChanges at: class name ifAbsent: [^ self]) associationsDo: 
  7547.         [:mAssoc | 
  7548.         mAssoc value = #remove
  7549.             ifFalse: [changes add: mAssoc key]].
  7550.     changes isEmpty ifFalse: 
  7551.         [class fileOutChangedMessages: changes on: stream.
  7552.         stream cr]!
  7553. fileOutOn: stream 
  7554.     "Write out all the changes the receiver knows about.
  7555.      5/15/96 sw: changed such that class headers for all changed classes go out at the beginning of the file."
  7556.  
  7557.     | classList |
  7558.     self isEmpty ifTrue: [self notify: 'Warning: no changes to file out'].
  7559.     classList _ ChangeSet superclassOrder: self changedClasses asOrderedCollection.
  7560.     classList do:
  7561.         [:aClass |  "if class defn changed, put it onto the file now"
  7562.             self fileOutClassDefinition: aClass on: stream].
  7563.     classList do:
  7564.         [:aClass |  "nb: he following no longer puts out class headers"
  7565.             self fileOutChangesFor: aClass on: stream].
  7566.     stream cr.
  7567.     classList do:
  7568.         [:aClass |
  7569.         self fileOutPSFor: aClass on: stream].
  7570.     classRemoves do:
  7571.         [:aClassName |
  7572.         stream nextChunkPut: aClassName, ' removeFromSystem'; cr].!
  7573. fileOutPSFor: class on: stream 
  7574.     "Write out removals and initialization for this class."
  7575.  
  7576.     (methodChanges at: class name ifAbsent: [^self]) associationsDo: 
  7577.         [:mAssoc | 
  7578.         mAssoc value = #remove
  7579.             ifTrue: [stream nextChunkPut:
  7580.                 class name, ' removeSelector: ', mAssoc key storeString; cr]
  7581.             ifFalse: [(mAssoc key = #initialize and: [class isMeta])
  7582.                     ifTrue: [stream nextChunkPut: class soleInstance name, ' initialize'; cr]]]! !
  7583.  
  7584. !ChangeSet methodsFor: 'private'!
  7585. atClass: class add: changeType
  7586.  
  7587.     (self isNew: class) ifFalse:     "new classes don't matter"
  7588.         [(classChanges at: class name
  7589.                 ifAbsent: [^classChanges at: class name put:
  7590.                     (Set with: changeType)])
  7591.             add: changeType]!
  7592. atClass: class includes: changeType
  7593.  
  7594.     ^(classChanges at: class name ifAbsent: [^false])
  7595.         includes: changeType!
  7596. atSelector: selector class: class
  7597.  
  7598.     ^(methodChanges at: class name ifAbsent: [^#none])
  7599.         at: selector ifAbsent: [#none]!
  7600. atSelector: selector class: class put: changeType
  7601.     | dict |
  7602.     (self isNew: class) ifTrue: [^self].     "Don't keep method changes for new classes"
  7603.     (selector==#DoIt) | (selector==#DoItIn:) ifTrue: [^self].
  7604.     (methodChanges at: class name
  7605.         ifAbsent: 
  7606.             [dict _ IdentityDictionary new.
  7607.             methodChanges at: class name put: dict.
  7608.             dict])
  7609.         at: selector put: changeType !
  7610. fileOutClassChanges: class on: stream 
  7611.     "Write out class changes, i.e. new class, definition, comment, renaming."
  7612.  
  7613.     (self atClass: class includes: #add) ifTrue:
  7614.         [stream cr.
  7615.         class fileOutOn: stream.
  7616.         stream cr].
  7617.  
  7618.     (self atClass: class includes: #rename) ifTrue:
  7619.         [stream nextChunkPut: (self oldNameFor: class), ' rename: #', class name; cr].
  7620.  
  7621.     (self atClass: class includes: #change) ifTrue:
  7622.         [stream emphasis: 5; nextChunkPut: class definition; cr; emphasis: 1].
  7623.  
  7624.     (self atClass: class includes: #comment) ifTrue:
  7625.         [class organization putCommentOnFile: stream
  7626.             numbered: nil moveSource: false.
  7627.         stream cr].
  7628.  
  7629.     (self atClass: class includes: #reorganize) ifTrue:
  7630.         [class fileOutOrganizationOn: stream.
  7631.         stream cr]!
  7632. fileOutClassDefinition: class on: stream 
  7633.     "Write out class definition for the given class on the given stream, if the class definition was added or changed.  5/15/96 sw"
  7634.  
  7635.     ((self atClass: class includes: #add) or: [self atClass: class includes: #change])
  7636.         ifTrue:
  7637.             [stream emphasis: 5; nextChunkPut: class definition; cr; emphasis: 1]!
  7638. fileOutClassModifications: class on: stream 
  7639.     "Write out class mod-- rename, comment, reorg, remove, on the given stream.  Differs from the superseded fileOutClassChanges:on: in that it does not deal with class definitions, and does not file out entire added classes.  5/15/96 sw"
  7640.  
  7641.     (self atClass: class includes: #rename) ifTrue:
  7642.         [stream nextChunkPut: (self oldNameFor: class), ' rename: #', class name; cr].
  7643.  
  7644.     (self atClass: class includes: #comment) ifTrue:
  7645.         [class organization putCommentOnFile: stream
  7646.             numbered: nil moveSource: false.
  7647.         stream cr].
  7648.  
  7649.     (self atClass: class includes: #reorganize) ifTrue:
  7650.         [class fileOutOrganizationOn: stream.
  7651.         stream cr]!
  7652. inspectMethodChanges
  7653.     methodChanges inspect!
  7654. isNew: class
  7655.     "Answer whether this class was added since the ChangeSet was cleared."
  7656.  
  7657.     (class isKindOf: Metaclass)
  7658.         ifTrue: [^self atClass: class soleInstance includes: #add "check class"]
  7659.         ifFalse: [^self atClass: class includes: #add]!
  7660. oldNameFor: class
  7661.     | cName |
  7662.     cName _ (classChanges at: class name) asOrderedCollection
  7663.                 detect: [:x | 'oldName: *' match: x].
  7664.     ^ (Scanner new scanTokens: cName) last! !
  7665.  
  7666. !ChangeSet methodsFor: 'accessing'!
  7667. methodChanges
  7668.     ^methodChanges!
  7669. name: anObject
  7670.     name _ anObject!
  7671. printOn: aStream
  7672.     "2/7/96 sw: provide the receiver's name in the printout"
  7673.     super printOn: aStream.
  7674.     aStream nextPutAll: ' named ', self name! !
  7675. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  7676.  
  7677. ChangeSet class
  7678.     instanceVariableNames: ''!
  7679.  
  7680. !ChangeSet class methodsFor: 'instance creation'! !
  7681.  
  7682. !ChangeSet class methodsFor: 'fileIn/Out'!
  7683. superclassOrder: classes 
  7684.     "Arrange the classes in the collection, classes, in superclass order so the 
  7685.     classes can be properly filed in."
  7686.  
  7687.     | all list i aClass superClass |
  7688.     list _ classes copy.             "list is indexable"
  7689.     all _ OrderedCollection new: list size.
  7690.     [list size > 0]
  7691.         whileTrue: 
  7692.             [aClass _ list first.
  7693.             superClass _ aClass superclass.
  7694.             "Make sure it doesn't have an as yet uncollected superclass"
  7695.             [superClass == nil or: [list includes: superClass]]
  7696.                 whileFalse: [superClass _ superClass superclass].
  7697.             i _ 1.
  7698.             [superClass == nil]
  7699.                 whileFalse: 
  7700.                     [i _ i + 1.
  7701.                     aClass _ list at: i.
  7702.                     superClass _ aClass superclass.
  7703.                     "check as yet uncollected superclass"
  7704.                     [superClass == nil or: [list includes: superClass]]
  7705.                         whileFalse: [superClass _ superClass superclass]].
  7706.             all addLast: aClass.
  7707.             list _ list copyWithout: aClass].
  7708.     ^all! !
  7709.  
  7710. !ChangeSet class methodsFor: 'defaults'!
  7711. defaultName
  7712.     | namesInUse try |
  7713.     namesInUse _ ChangeSorter gatherChangeSets
  7714.                     collect: [:each | each name].
  7715.     1 to: 999999 do:
  7716.         [:i | try _ 'Unnamed' , i printString.
  7717.         (namesInUse includes: try) ifFalse: [^ try]]! !StringHolder subclass: #ChangeSorter
  7718.     instanceVariableNames: 'parent myChangeSet classList messageList buttonView '
  7719.     classVariableNames: 'AllChangeSets CngSetSelectors MsgListMenu SingleCngSetMenu CngSetMenu MsgListSelectors ClassSelectors ClassMenu '
  7720.     poolDictionaries: ''
  7721.     category: 'Interface-Changes'!
  7722.  
  7723. !ChangeSorter methodsFor: 'creation'!
  7724. aReadThis
  7725.     "This class presents a view of a single change set.  A DualChangeSorter owns two of me.  The name pane across the top has a menu of things to do to the ChangeSet I am currently showing.  
  7726.     Renames of classes are not shown properly.  'Copy to other side' overwrites what was there if the other change set had the same method or class change.
  7727.  
  7728.     ChangeSorter new open.
  7729.     ChangeSorter allInstances inspect
  7730.     "!
  7731. defaultBackgroundColor
  7732.     ^ #lightBlue!
  7733. initialize
  7734.     myChangeSet _ Smalltalk changes.        "default"
  7735.     classList _ CngsClassList new.
  7736.     classList parent: self.
  7737.     messageList _ CngsMsgList new.
  7738.     messageList parent: self.
  7739.     MsgListMenu == nil ifTrue: [self class initialize].
  7740.     classList list: #().
  7741.     messageList list: #().
  7742. !
  7743. open
  7744.     | topView |
  7745.     self initialize.
  7746.  
  7747.     topView _ StandardSystemView new.
  7748.     topView model: self.
  7749.     topView label: self label.
  7750.     topView minimumSize: 360@360.
  7751.     self openView: topView.
  7752.     topView controller open        "Let the show begin"!
  7753. openView: topView
  7754.     "Create change sorter on one changeSet only.  Two of these in a DualChangeSorter."
  7755.     | classView messageView codeView |
  7756.  
  7757.     buttonView _ SwitchView new.
  7758.     buttonView model: self controller: TriggerController new.
  7759.     buttonView borderWidthLeft: 2 right: 2 top: 2 bottom: 0.
  7760.     buttonView selector: #whatPolarity.
  7761.     buttonView controller selector: #cngSetActivity.
  7762.     buttonView window: (0 @ 0 extent: 360 @ 20).
  7763.     buttonView label: myChangeSet name asParagraph.
  7764.  
  7765.     classView _ GeneralListView new.
  7766.     classView controllerClass: GeneralListController.
  7767.     classView model: classList.
  7768.     classView window: (0 @ 0 extent: 180 @ 160).
  7769.     classView borderWidthLeft: 2 right: 0 top: 2 bottom: 2.
  7770.     classView controller yellowButtonMenu: ClassMenu 
  7771.         yellowButtonMessages: ClassSelectors.
  7772.     classList controller: classView controller.
  7773.  
  7774.  
  7775.     messageView _ GeneralListView new.
  7776.     messageView controllerClass: GeneralListController.
  7777.     messageView model: messageList.
  7778.     messageView window: (0 @ 0 extent: 180 @ 160).
  7779.     messageView borderWidthLeft: 2 right: 2 top: 2 bottom: 2.
  7780.     messageView controller yellowButtonMenu: MsgListMenu 
  7781.         yellowButtonMessages: MsgListSelectors.
  7782.     messageList controller: messageView controller.
  7783.  
  7784.     codeView _ BrowserCodeView new.
  7785.     codeView model: self.
  7786.     codeView window: (0 @ 0 extent: 360 @ 180).
  7787.     codeView borderWidthLeft: 2 right: 2 top: 0 bottom: 2.
  7788.     "codeView editString: aString."
  7789.  
  7790.     topView addSubView: buttonView.
  7791.     topView addSubView: classView.
  7792.     topView addSubView: messageView.
  7793.     topView addSubView: codeView.
  7794.  
  7795.     classView 
  7796.         align: classView viewport topLeft     
  7797.         with: buttonView viewport bottomLeft.
  7798.     messageView 
  7799.         align: messageView viewport topLeft     
  7800.         with: classView viewport topRight.
  7801.     codeView 
  7802.         align: codeView viewport topLeft     
  7803.         with: classView viewport bottomLeft.
  7804. ! !
  7805.  
  7806. !ChangeSorter methodsFor: 'startUp'!
  7807. changed: what
  7808.     "Respond to an external change.  By tck, mid-1991.
  7809.      3/1/96 sw: present message lists in sorted order"
  7810.  
  7811.     | cls |
  7812.     what == #set ifTrue: [^ self launch].
  7813.     what == #class ifTrue:
  7814.         [self verifyLabel.
  7815.         (cls _ classList selectedClassOrMetaClass) == nil
  7816.             ifFalse: [messageList list:
  7817.                     ((myChangeSet selectorsInClass: cls name) collect: 
  7818.                         [:each | each printString]) asSortedCollection]
  7819.             ifTrue: [messageList list: #()].
  7820.         ^ self].
  7821.  
  7822.     what == #message ifTrue:
  7823.         [self setContents.
  7824.         ^ super changed: #editMessage].
  7825.     super changed: what!
  7826. label
  7827.     ^ 'Changes go to "', (Smalltalk changes name), '"'!
  7828. launch
  7829.     "recompute what to show in all panes"
  7830.     | cls msg |
  7831.     buttonView label: myChangeSet name asParagraph.  "in case it changed"
  7832.     buttonView display.
  7833.     cls _ classList selection.        "save current selection"
  7834.     msg _ messageList selection.
  7835.     Cursor wait showWhile: [
  7836.         classList list: (myChangeSet changedClasses collect: 
  7837.                 [:each | each printString]) asOrderedCollection].
  7838.     classList selection: cls.        "try to reselect old selection, if there"
  7839.     messageList selection: msg.
  7840.     self setContents.!
  7841. parent
  7842.     ^parent!
  7843. parent: anObject
  7844.     parent _ anObject!
  7845. verifyLabel
  7846.     "May have changed since we last were in this window"
  7847.     buttonView == nil ifTrue: [^ self].
  7848.     buttonView topView label asString = self label 
  7849.         ifFalse: [buttonView topView relabel: self label].
  7850. ! !
  7851.  
  7852. !ChangeSorter methodsFor: 'change set menu'!
  7853. browseChangeSet
  7854.     "Open a message list browser on the new and changed methods in the current change set.  2/2/96 sw"
  7855.  
  7856.     Smalltalk browseMessageList: myChangeSet changedMessageListAugmented name: 'Methods in Change Set ', myChangeSet name!
  7857. browseMessagesWithPriorVersions
  7858.     "Open a message list browser on the new and changed methods in the current change set which have at least one prior version.  Potentially a menu command, though its use is perhaps somewhat obscure, so for the moment I'm only getting at this feature via direct calls to the ChangeSet method, through explicit doIts.  6/28/96 sw"
  7859.  
  7860.     myChangeSet browseMessagesWithPriorVersions!
  7861. changeSet
  7862.     ^ myChangeSet!
  7863. chooseCngSet
  7864.     "Put up a list of them"
  7865.     | index |
  7866.     ChangeSet instanceCount > AllChangeSets size ifTrue: [self gather].
  7867.     index _ (PopUpMenu labels: 
  7868.         (AllChangeSets collect: [:each | each name]) asStringWithCr) startUp.
  7869.     index = 0 ifFalse: [
  7870.         myChangeSet _ AllChangeSets at: index.
  7871.         buttonView label: myChangeSet name asParagraph.
  7872.         buttonView display.
  7873.         self changed: #set].!
  7874. cngSetActivity
  7875.     "Put up a menu and do what the user says.  1991 tck;
  7876.     5/9/96 sw: highlight button while mouse down
  7877.     5/29/96 sw: use different menu for single-change-sorter case"
  7878.  
  7879.     | index reply |
  7880.  
  7881.     buttonView displayComplemented.
  7882.     parent == nil "Single change sorter"
  7883.         ifTrue:
  7884.             [reply _ SingleCngSetMenu startUp.
  7885.             reply == nil ifFalse:
  7886.                 [self perform: reply]]
  7887.         ifFalse:
  7888.             [index _ CngSetMenu startUp.
  7889.             index == 0 ifFalse:
  7890.                 [self perform: (CngSetSelectors at: index)]].
  7891.     buttonView displayNormal!
  7892. copyToOther
  7893.     "Copy this entire change set into the one on the other side"
  7894.  
  7895.     "controller controlTerminate."
  7896.     | other |
  7897.     other _ (parent other: self) changeSet.
  7898.  
  7899.     other assimilateAllChangesFoundIn: myChangeSet.
  7900.     (parent other: self) launch.
  7901.     "controller controlInitialize"!
  7902. fileIntoNewChangeSet
  7903.     "Obtain a file designation from the user, and file its contents into a new change set whose name is a function of the filename; in the end, leave the current change-set unaltered.  5/30/96 sw."
  7904.  
  7905.     | aFileName  aNewChangeSet |
  7906.  
  7907.     aFileName _ FillInTheBlank request: 'Name of file to be imported: '.
  7908.     aFileName size == 0 ifTrue: [^ self].
  7909.     (FileDirectory default includesKey: aFileName) ifFalse:
  7910.         [self inform: 'Sorry -- cannot find that file'.
  7911.         ^ self].
  7912.  
  7913.     aNewChangeSet _ self class newChangesFromFile: aFileName.
  7914.     aNewChangeSet ~~ nil ifTrue:
  7915.         [myChangeSet _ aNewChangeSet.
  7916.         buttonView label: aNewChangeSet name asParagraph.
  7917.         buttonView display.
  7918.         self changed: #set]!
  7919. fileOut
  7920.     "File out the current change set.  1/18/96 sw"
  7921.  
  7922.     myChangeSet fileOut!
  7923. gather
  7924.     "Make sure the class variable AllChangeSets is up to date.  1/22/96 sw"
  7925.  
  7926.     self class gatherChangeSets!
  7927. newCurrent
  7928.     "make my change set be the current one that changes go into"
  7929.     Smalltalk newChanges: myChangeSet.
  7930.     buttonView topView relabel: self label.!
  7931. newSet
  7932.     "Create a new changeSet and show it.  For splitting an existing one that is showing in the other pane..  1991-tck.
  7933.      3/9/96 sw: make the new guy the current one, corresponding to 99.5% of normal use.  Also, reject name if already in use."
  7934.  
  7935.     | newName |
  7936.     newName _ FillInTheBlank request: 'A name for the new change set'
  7937.             initialAnswer: ChangeSet defaultName.
  7938.  
  7939.     newName isEmpty ifTrue: [^ self].
  7940.     (self class changeSetNamed: newName) ~~ nil
  7941.         ifTrue:
  7942.             [self inform: 'Sorry that name is already used'.
  7943.             ^ self].
  7944.  
  7945.     myChangeSet _ ChangeSet new initialize.
  7946.     myChangeSet name: newName.
  7947.     AllChangeSets add: myChangeSet.
  7948.     buttonView label: myChangeSet name asParagraph.
  7949.     buttonView display.
  7950.     self newCurrent.
  7951.     self changed: #set!
  7952. remove
  7953.     "Completely destroy my change set.  Check if it's OK first.  tck 1991
  7954.      1/22/96 sw MacPal -> Utilities.  2/7/96 sw: changed the order of the various checks; don't put up confirmer if the change set is empty"
  7955.  
  7956.     | message |
  7957.  
  7958.     myChangeSet == Smalltalk changes ifTrue:
  7959.         [self inform: 'Cannot remove the 
  7960. current change set.'.
  7961.         ^ self].
  7962.  
  7963.     Project allInstances do: [:each |
  7964.         each projectChangeSet == myChangeSet ifTrue:
  7965.             [Utilities inform: 'This change set belongs to a 
  7966. project and cannot be removed.'.
  7967.             ^ self]].
  7968.  
  7969.     myChangeSet isEmpty ifFalse:
  7970.         [message _ 'Are you certain that you want to 
  7971. forget all the changes in this set?'.
  7972.         (self confirm: message) ifFalse: [^ self]].
  7973.  
  7974.     "Go ahead and remove the change set"
  7975.     AllChangeSets remove: myChangeSet.
  7976.     myChangeSet wither.        "clear out its contents"
  7977.     "Show the current change set"
  7978.     myChangeSet _ Smalltalk changes.
  7979.     buttonView label: myChangeSet name asParagraph.
  7980.     buttonView display.
  7981.     self changed: #set!
  7982. rename
  7983.     "Store a new name string into the selected ChangeSet.  1991-tck.
  7984.      3/9/96 sw: several fixes:  reject duplicate name; allow user to back out"
  7985.  
  7986.     | newName |
  7987.     newName _ FillInTheBlank request: 'A name for this change set'
  7988.                         initialAnswer: myChangeSet name.
  7989.     (newName = myChangeSet name or:
  7990.         [newName size == 0]) ifTrue:
  7991.             [^ self inform: 'No change made'].
  7992.  
  7993.     (self class changeSetNamed: newName) ~~ nil
  7994.         ifTrue:
  7995.             [Utilities inform: 'Sorry that name is already used'.
  7996.             ^ self].
  7997.  
  7998.     myChangeSet name: newName.
  7999.     buttonView label: newName asParagraph.
  8000.     buttonView display.
  8001.     myChangeSet == Smalltalk changes ifTrue:
  8002.         [buttonView topView relabel: self label]!
  8003. subtractOtherSide
  8004.     "Subtract the changes found on the other side from the requesting side.  3/13/96 sw"
  8005.  
  8006.     | other |
  8007.     other _ (parent other: self) changeSet.
  8008.     myChangeSet forgetAllChangesFoundIn: other.
  8009.     self launch!
  8010. whatPolarity
  8011.     "button at top is white (off), not black"
  8012.     ^ false! !
  8013.  
  8014. !ChangeSorter methodsFor: 'class list'!
  8015. selectedClass
  8016.     ^ classList selectedClass!
  8017. selectedClassOrMetaClass
  8018.     ^ classList selectedClassOrMetaClass! !
  8019.  
  8020. !ChangeSorter methodsFor: 'message list'!
  8021. messageListIndex
  8022.     ^ messageList listIndex!
  8023. selectedMessage
  8024.     ^ self selectedClassOrMetaClass sourceMethodAt: self selectedMessageName!
  8025. selectedMessageName
  8026.     | sel |
  8027.     ^ (sel _ messageList selection) == nil ifFalse: [sel asSymbol]
  8028.         ifTrue: [nil]! !
  8029.  
  8030. !ChangeSorter methodsFor: 'code pane'!
  8031. contents: aString notifying: aController 
  8032.     "Compile the code in aString. Notify aController of any syntax errors. 
  8033.     Create an error if the category of the selected message is unknown. 
  8034.     Answer false if the compilation fails. Otherwise, if the compilation 
  8035.     created a new method, deselect the current selection. Then answer true."
  8036.     | category selector class oldSelector notice |
  8037.     messageList listIndex = 0 ifTrue: [^ false].
  8038.     class _ self selectedClassOrMetaClass.
  8039.     oldSelector _ self selectedMessageName.
  8040.     category _ class organization categoryOfElement: oldSelector.
  8041.     selector _ class
  8042.                 compile: aString
  8043.                 classified: category
  8044.                 notifying: aController.
  8045.     selector == nil ifTrue: [^false].
  8046.     selector == oldSelector ifFalse: [self changed: #message].
  8047.     notice _ class checkForPerform: selector in: aController.
  8048.     notice size = 0 ifFalse: ["insert the notice"
  8049.             aController notify: notice
  8050.                 at: contents size + 1
  8051.                 in: nil.
  8052.             self lock  "code is dirty"].
  8053.     ^true!
  8054. editSelection
  8055.     ^ #editMessage!
  8056. setContents
  8057.     "return the source code that shows in the bottom pane"
  8058.     | sel class strm what |
  8059.     self unlock.
  8060.     (classList selection) == nil ifTrue: [^ contents _ ''].
  8061.     class _ classList selectedClassOrMetaClass.
  8062.     (sel _ messageList selection) == nil
  8063.         ifFalse: [
  8064.             what _ (myChangeSet atSelector: (sel _ sel asSymbol) class: class).
  8065.             what == #remove ifFalse: [
  8066.                 (class includesSelector: sel) ifFalse: [
  8067.                     ^ contents _ 'was added, but it''s gone!! ******'].
  8068.                 ^ contents _ (class sourceMethodAt: sel) copy]
  8069.               ifTrue: [^ contents _ 'remove the method ******']]
  8070.         ifTrue: [strm _ WriteStream on: (String new: 100).
  8071.             (myChangeSet classChangeAt: class name) do: [:each |
  8072.                 each = #remove ifTrue: [strm nextPutAll: '**** entire class was removed ****'; cr].
  8073.                 each = #add ifTrue: [strm nextPutAll: '**** entire class was added ****'; cr].
  8074.                 each = #change ifTrue: [strm nextPutAll: '**** class definition was changed ****'; cr].
  8075.                 each = #comment ifTrue: [strm nextPutAll: '**** new class comment ****'; cr]].
  8076.             ^ contents _ strm contents].!
  8077. spawn: aString 
  8078.     "Create and schedule a message browser for the receiver in which the 
  8079.     argument, aString, contains characters to be edited in the text view."
  8080.  
  8081.     messageList listIndex = 0 ifTrue: [^ self].
  8082.     ^ BrowserView
  8083.         openMessageBrowserForClass: self selectedClassOrMetaClass
  8084.         selector: self selectedMessageName
  8085.         editString: aString! !
  8086.  
  8087. !ChangeSorter methodsFor: 'accessing'!
  8088. messageList
  8089.     ^messageList! !
  8090. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  8091.  
  8092. ChangeSorter class
  8093.     instanceVariableNames: ''!
  8094.  
  8095. !ChangeSorter class methodsFor: 'as yet unclassified'!
  8096. changeSetNamed: aName
  8097.     "Return the change set of the given name, or nil if none found.  1/22/96 sw"
  8098.  
  8099.     self gatherChangeSets.
  8100.     AllChangeSets do:
  8101.         [:aChangeSet | aChangeSet name = aName ifTrue:
  8102.             [^ aChangeSet]].
  8103.     ^ nil!
  8104. gatherChangeSets
  8105.     "Collect any change sets created in other projects  1/22/96 sw
  8106.      2/7/96 sw: filter out moribund guys"
  8107.  
  8108.     ChangeSet allInstancesDo: [:each |
  8109.         (AllChangeSets includes: each) ifFalse:
  8110.             [AllChangeSets add: each]].
  8111.     ^ AllChangeSets _ AllChangeSets select:
  8112.         [:each | each isMoribund not]
  8113.  
  8114.     "ChangeSorter gatherChangeSets"!
  8115. initialize
  8116.     "Initialize the class.  1991-tck
  8117.     Modified 1/12/96 sw: added a bunch of new items, not all of them implemented yet.  2/2/96 sw: added browse change set.  Also made it such that if AllChangeSets already exists, this won't clobber the existing order.  2/5/96 sw: changed wording of some items
  8118.     5/8/96 sw: added subtractOtherSide
  8119.     5/29/96 sw: added SingleCngSetMenu, for single change sorter
  8120.     5/30/96 sw: added fileIntoNewChangeSet
  8121.     7/23/96 di: removed SingleCngSetMenu, since not used"
  8122.  
  8123.     AllChangeSets == nil ifTrue:
  8124.         [AllChangeSets _ OrderedCollection new].
  8125.     self gatherChangeSets.
  8126.  
  8127.     CngSetMenu _ PopUpMenu labels: 
  8128. 'make changes go to me
  8129. new...
  8130. file into new...
  8131. show...
  8132. fileOut
  8133. browse
  8134. rename
  8135. copy all to other side
  8136. subtract other side
  8137. remove'    lines: #(1 3 7 9).
  8138.     CngSetSelectors  _ 
  8139.         #(newCurrent newSet fileIntoNewChangeSet chooseCngSet fileOut browseChangeSet rename copyToOther subtractOtherSide remove).
  8140.  
  8141.     ClassMenu _ PopUpMenu labels: 
  8142. 'browse class
  8143. browse full
  8144. inst var refs
  8145. class vars
  8146. copy to other side
  8147. forget' 
  8148.             lines: #().
  8149.     ClassSelectors _ 
  8150.         #(browse browseFull instVarRefs classVariables copyToOther forget).
  8151.  
  8152.     MsgListMenu _ PopUpMenu labels: 
  8153. 'fileOut
  8154. senders
  8155. implementors
  8156. senders of...
  8157. implementors of...
  8158. implementors of sent msgs
  8159. versions
  8160. copy to other side
  8161. forget' 
  8162.             lines: #(1 6 7).
  8163.     MsgListSelectors _ 
  8164.         #(fileOut senders implementors browseSendersOfMessages messages
  8165.         allImplementorsOf versions copyToOther forget).
  8166.     false ifTrue: [
  8167.         "Just so senders will find it here!!!!!!  Never executed."
  8168.         (CngsMsgList new) fileOut; senders; implementors; messages;  
  8169.             versions; copyToOther; forget.
  8170.         (MessageListController new) browseSendersOfMessages; 
  8171.             allImplementorsOf].
  8172.  
  8173.     "
  8174.     ChangeSorter initialize.
  8175.     GeneralListController allInstancesDo:
  8176.         [:each  | each model parent class == ChangeSorter ifTrue: [
  8177.             each yellowButtonMenu: ClassMenu 
  8178.                 yellowButtonMessages: ClassSelectors.
  8179.             each yellowButtonMenu: MsgListMenu 
  8180.                 yellowButtonMessages: MsgListSelectors]].
  8181.     "!
  8182. makeCurrent: aChangeSet
  8183.     "Make aChangeSet be the one that changes will accumulate into.  5/30/96 sw"
  8184.  
  8185.     Smalltalk newChanges: aChangeSet!
  8186. newChangesFromFile: aFileName
  8187.     "File in the code from the file of the given name, into a new change set whose name is derived from that of the filename.  Leave the 'current change set' unchanged.   Returns the new change set; Returns nil on failure.  5/30/96 sw"
  8188.  
  8189.     |  newName aNewChangeSet existingChanges |
  8190.  
  8191.     existingChanges _ Smalltalk changes.
  8192.     newName _ aFileName sansPeriodSuffix.
  8193.     (self changeSetNamed: newName) ~~ nil
  8194.         ifTrue:
  8195.             [self inform: 'Sorry -- "', newName, '" is already used as a change-set name'.
  8196.             ^ nil].
  8197.  
  8198.     aNewChangeSet _ ChangeSet new initialize.
  8199.     aNewChangeSet name: newName.
  8200.     AllChangeSets add: aNewChangeSet.
  8201.     self makeCurrent: aNewChangeSet.
  8202.     (FileStream oldFileNamed: aFileName) fileIn.
  8203.     Transcript cr; show: 'File ', aFileName, ' successfully filed in to change set ', newName.
  8204.     self makeCurrent: existingChanges.
  8205.     ^ aNewChangeSet!
  8206. newChangesFromFileStream: aFileStream
  8207.     "File in the code from the file, into a new change set whose name is derived from the filename.  Leave the 'current change set' unchanged.   Returns the new change set;  Returns nil on failure.  7/12/96 sw"
  8208.  
  8209.     |  newName aNewChangeSet existingChanges aFileName |
  8210.  
  8211.     existingChanges _ Smalltalk changes.
  8212.     aFileName _ aFileStream localName.
  8213.     newName _ aFileName sansPeriodSuffix.
  8214.     (self changeSetNamed: newName) ~~ nil
  8215.         ifTrue:
  8216.             [self inform: 'Sorry -- "', newName, '" is already used as a change-set name'.
  8217.             aFileStream close.
  8218.             ^ nil].
  8219.  
  8220.     aNewChangeSet _ ChangeSet new initialize.
  8221.     aNewChangeSet name: newName.
  8222.     AllChangeSets add: aNewChangeSet.
  8223.     self makeCurrent: aNewChangeSet.
  8224.     aFileStream fileIn.
  8225.     Transcript cr; show: 'File ', aFileName, ' successfully filed in to change set ', newName.
  8226.     self makeCurrent: existingChanges.
  8227.     ^ aNewChangeSet! !
  8228.  
  8229. ChangeSorter initialize!
  8230. Magnitude subclass: #Character
  8231.     instanceVariableNames: 'value '
  8232.     classVariableNames: 'CharacterTable '
  8233.     poolDictionaries: ''
  8234.     category: 'Collections-Text'!
  8235. Character comment:
  8236. 'I represent a character by storing its associated ASCII code (extended to 256 codes). My instances are created uniquely, so that all instances of a character ($R, for example) are identical.'!
  8237.  
  8238. !Character methodsFor: 'accessing'!
  8239. asciiValue
  8240.     "Answer the value of the receiver that represents its ascii encoding."
  8241.  
  8242.     ^value!
  8243. digitValue
  8244.     "Answer 0-9 if the receiver is $0-$9, 10-35 if it is $A-$Z or $a-$z, and < 0 
  8245.     otherwise. This is used to parse literal numbers of radix 2-36."
  8246.  
  8247.     value <= $9 asciiValue 
  8248.         ifTrue: [^value - $0 asciiValue].
  8249.     value >= $A asciiValue 
  8250.         ifTrue: [value <= $Z asciiValue ifTrue: [^value - $A asciiValue + 10]].
  8251.     value >= $a asciiValue 
  8252.         ifTrue: [value <= $z asciiValue ifTrue: [^value - $a asciiValue + 10]].
  8253.     ^-1! !
  8254.  
  8255. !Character methodsFor: 'comparing'!
  8256. < aCharacter 
  8257.     "Answer true if the receiver's value < aCharacter's value."
  8258.  
  8259.     ^self asciiValue < aCharacter asciiValue!
  8260. = aCharacter 
  8261.     "Primitive. Answer true if the receiver and the argument are the same
  8262.     object (have the same object pointer) and false otherwise. Optional. See
  8263.     Object documentation whatIsAPrimitive."
  8264.  
  8265.     <primitive: 110>
  8266.     ^self == aCharacter!
  8267. > aCharacter 
  8268.     "Answer true if the receiver's value > aCharacter's value."
  8269.  
  8270.     ^self asciiValue > aCharacter asciiValue!
  8271. hash
  8272.     "Hash is reimplemented because = is implemented."
  8273.  
  8274.     ^value! !
  8275.  
  8276. !Character methodsFor: 'testing'!
  8277. isAlphaNumeric
  8278.     "Answer whether the receiver is a letter or a digit."
  8279.  
  8280.     ^self isLetter or: [self isDigit]!
  8281. isDigit
  8282.     "Answer whether the receiver is a digit."
  8283.  
  8284.     ^value >= 48 and: [value <= 57]!
  8285. isLetter
  8286.     "Answer whether the receiver is a letter."
  8287.  
  8288.     ^(8r141 <= value and: [value <= 8r172])
  8289.         or: [8r101 <= value and: [value <= 8r132]]!
  8290. isLowercase
  8291.     "Answer whether the receiver is a lowercase letter.
  8292.     (The old implementation answered whether the receiver is not an uppercase letter.)"
  8293.  
  8294.     ^8r141 <= value and: [value <= 8r172]!
  8295. isSeparator
  8296.     "Answer whether the receiver is one of the separator characters--space, 
  8297.     cr, tab, line feed, or form feed."
  8298.  
  8299.     value = 32 ifTrue: [^true].    "space"
  8300.     value = 13 ifTrue: [^true].    "cr"
  8301.     value = 9 ifTrue: [^true].    "tab"
  8302.     value = 10 ifTrue: [^true].    "line feed"
  8303.     value = 12 ifTrue: [^true].    "form feed"
  8304.     ^false!
  8305. isSpecial
  8306.     "Answer whether the receiver is one of the special characters"
  8307.  
  8308.     ^'+/\*~<>=@%|&?!!' includes: self!
  8309. isUppercase
  8310.     "Answer whether the receiver is an uppercase letter.
  8311.     (The old implementation answered whether the receiver is not a lowercase letter.)"
  8312.  
  8313.     ^8r101 <= value and: [value <= 8r132]!
  8314. isVowel
  8315.     "Answer whether the receiver is one of the vowels, AEIOU, in upper or 
  8316.     lower case."
  8317.  
  8318.     ^'AEIOU' includes: self asUppercase!
  8319. tokenish
  8320.     "Answer whether the receiver is a valid token-character--letter, digit, or 
  8321.     colon."
  8322.  
  8323.     ^self isLetter or: [self isDigit or: [self = $:]]! !
  8324.  
  8325. !Character methodsFor: 'copying'!
  8326. copy
  8327.     "Answer with the receiver because Characters are unique."!
  8328. deepCopy
  8329.     "Answer with the receiver because Characters are unique."! !
  8330.  
  8331. !Character methodsFor: 'printing'!
  8332. hex
  8333.     ^ String with: ('0123456789ABCDEF' at: value//16+1)
  8334.             with:  ('0123456789ABCDEF' at: value\\16+1)!
  8335. isLiteral
  8336.  
  8337.     ^true!
  8338. printOn: aStream
  8339.  
  8340.     aStream nextPut: $$.
  8341.     aStream nextPut: self!
  8342. storeOn: aStream
  8343.     "Character literals are preceded by '$'."
  8344.  
  8345.     aStream nextPut: $$; nextPut: self! !
  8346.  
  8347. !Character methodsFor: 'converting'!
  8348. asCharacter
  8349.     "Answer the receiver itself."
  8350.  
  8351.     ^self!
  8352. asInteger
  8353.     "Answer the value of the receiver."
  8354.  
  8355.     ^value!
  8356. asLowercase
  8357.     "If the receiver is uppercase, answer its matching lowercase Character."
  8358.     
  8359.     self isUppercase ifTrue: [^Character value: value+8r40]!
  8360. asString
  8361.     | cString |
  8362.     cString _ String new: 1.
  8363.     cString at: 1 put: self.
  8364.     ^ cString!
  8365. asSymbol 
  8366.     "Answer a Symbol consisting of the receiver as the only element."
  8367.  
  8368.     ^Symbol internCharacter: self!
  8369. asUppercase
  8370.     "If the receiver is lowercase, answer its matching uppercase Character."
  8371.     
  8372.     (8r141 <= value and: [value <= 8r172])  "self isLowercase"
  8373.         ifTrue: [^ Character value: value - 8r40]
  8374.         ifFalse: [^ self]!
  8375. to: other
  8376.     "Answer with a collection in ascii order -- $a to: $z"
  8377.     ^ (self asciiValue to: other asciiValue) collect:
  8378.                 [:ascii | Character value: ascii]! !
  8379. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  8380.  
  8381. Character class
  8382.     instanceVariableNames: ''!
  8383.  
  8384. !Character class methodsFor: 'class initialization'!
  8385. initialize
  8386.     "Create the table of unique Characters. This code is not shown so that the
  8387.     user can not destroy the system by trying to recreate the table."! !
  8388.  
  8389. !Character class methodsFor: 'instance creation'!
  8390. digitValue: x 
  8391.     "Answer the Character whose digit value is x. For example, answer $9 for 
  8392.     x=9, $0 for x=0, $A for x=10, $Z for x=35."
  8393.  
  8394.     | index |
  8395.     index _ x asInteger.
  8396.     ^CharacterTable at: 
  8397.         (index < 10
  8398.             ifTrue: [48 + index]
  8399.             ifFalse: [55 + index])
  8400.         + 1!
  8401. new
  8402.     "Creating new characters is not allowed."
  8403.  
  8404.     self error: 'cannot create new characters'!
  8405. separators
  8406.     ^ #(32 "space"
  8407.         13 "cr"
  8408.         9 "tab"
  8409.         10 "line feed"
  8410.         12 "form feed")
  8411.         collect: [:v | Character value: v]
  8412.  
  8413.     
  8414. !
  8415. value: anInteger 
  8416.     "Answer the Character whose value is anInteger."
  8417.  
  8418.     ^CharacterTable at: anInteger + 1! !
  8419.  
  8420. !Character class methodsFor: 'accessing untypeable characters'!
  8421. apple
  8422.     "Answer the Character representing an Apple."
  8423.  
  8424.     ^self value: 20!
  8425. backspace
  8426.     "Answer the Character representing a backspace."
  8427.  
  8428.     ^self value: 8!
  8429. cr
  8430.     "Answer the Character representing a carriage return."
  8431.  
  8432.     ^self value: 13!
  8433. enter
  8434.     "Answer the Character representing enter."
  8435.  
  8436.     ^self value: 3!
  8437. esc
  8438.     "Answer the Character representing an escape."
  8439.  
  8440.     ^self value: 160!
  8441. newPage
  8442.     "Answer the Character representing a form feed."
  8443.  
  8444.     ^self value: 12!
  8445. space
  8446.     "Answer the Character representing a space."
  8447.  
  8448.     ^self value: 32!
  8449. tab
  8450.     "Answer the Character representing a tab."
  8451.  
  8452.     ^self value: 9! !
  8453.  
  8454. !Character class methodsFor: 'constants'!
  8455. alphabet
  8456.     "In case someone needs it"
  8457.     ^'abcdefghijklmnopqrstuvwxyz'!
  8458. characterTable
  8459.     "Answer the class variable in which unique Characters are stored."
  8460.  
  8461.     ^CharacterTable! !
  8462.  
  8463. Character initialize!
  8464. Rectangle subclass: #CharacterBlock
  8465.     instanceVariableNames: 'stringIndex character '
  8466.     classVariableNames: ''
  8467.     poolDictionaries: 'TextConstants '
  8468.     category: 'Graphics-Support'!
  8469. CharacterBlock comment:
  8470. 'My instances contain information about displayed characters. They are used to return the results of methods:
  8471.     Paragraph characterBlockAtPoint: aPoint and
  8472.     Paragraph characterBlockForIndex: stringIndex.
  8473. Any recomposition or movement of a Paragraph can make the instance obsolete.'!
  8474.  
  8475. !CharacterBlock methodsFor: 'accessing'!
  8476. character
  8477.     "Answer the character in the receiver."
  8478.  
  8479.     ^character!
  8480. stringIndex
  8481.     "Answer the position of the receiver in the string it indexes."
  8482.  
  8483.     ^stringIndex! !
  8484.  
  8485. !CharacterBlock methodsFor: 'comparing'!
  8486. < aCharacterBlock 
  8487.     "Answer whether the string index of the receiver precedes that of 
  8488.     aCharacterBlock."
  8489.  
  8490.     ^stringIndex < aCharacterBlock stringIndex!
  8491. <= aCharacterBlock 
  8492.     "Answer whether the string index of the receiver does not come after that 
  8493.     of aCharacterBlock."
  8494.  
  8495.     ^(self > aCharacterBlock) not!
  8496. = aCharacterBlock
  8497.  
  8498.     self species = aCharacterBlock species
  8499.         ifTrue: [^stringIndex = aCharacterBlock stringIndex]
  8500.         ifFalse: [^false]!
  8501. > aCharacterBlock 
  8502.     "Answer whether the string index of the receiver comes after that of 
  8503.     aCharacterBlock."
  8504.  
  8505.     ^aCharacterBlock < self!
  8506. >= aCharacterBlock 
  8507.     "Answer whether the string index of the receiver does not precede that of 
  8508.     aCharacterBlock."
  8509.  
  8510.     ^(self < aCharacterBlock) not! !
  8511.  
  8512. !CharacterBlock methodsFor: 'copying'!
  8513. copy
  8514.  
  8515.     ^self deepCopy! !
  8516.  
  8517. !CharacterBlock methodsFor: 'printing'!
  8518. printOn: aStream
  8519.  
  8520.     aStream nextPutAll: 'a CharacterBlock with index '.
  8521.     stringIndex printOn: aStream.
  8522.     aStream nextPutAll: ' and character '.
  8523.     character printOn: aStream.
  8524.     aStream nextPutAll: ' and rectangle '.
  8525.     super printOn: aStream! !
  8526.  
  8527. !CharacterBlock methodsFor: 'private'!
  8528. newStringIndex: anInteger Character: aCharacter BoundingRectangle: aRectangle
  8529.  
  8530.     stringIndex _ anInteger.
  8531.     character _ aCharacter.
  8532.     super origin: aRectangle topLeft.
  8533.     super corner: aRectangle corner!
  8534. newStringIndex: anInteger Character: aCharacter TopLeft: originPoint Extent: extentPoint
  8535.  
  8536.     stringIndex _ anInteger.
  8537.     character _ aCharacter.
  8538.     super origin: originPoint.
  8539.     super extent: extentPoint! !
  8540. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  8541.  
  8542. CharacterBlock class
  8543.     instanceVariableNames: ''!
  8544.  
  8545. !CharacterBlock class methodsFor: 'instance creation'!
  8546. stringIndex: anInteger character: aCharacter boundingRectangle: aRectangle 
  8547.     "Answer an instance of me with values set to the arguments."
  8548.  
  8549.     ^self new
  8550.         newStringIndex: anInteger
  8551.         Character: aCharacter
  8552.         BoundingRectangle: aRectangle!
  8553. stringIndex: anInteger character: aCharacter topLeft: originPoint extent: extentPoint 
  8554.     "Answer an instance of me with values set to the arguments."
  8555.  
  8556.     ^self new
  8557.         newStringIndex: anInteger
  8558.         Character: aCharacter
  8559.         TopLeft: originPoint
  8560.         Extent: extentPoint! !CharacterScanner subclass: #CharacterBlockScanner
  8561.     instanceVariableNames: 'characterPoint characterIndex lastCharacter lastCharacterExtent lastSpaceOrTabExtent nextLeftMargin '
  8562.     classVariableNames: ''
  8563.     poolDictionaries: 'TextConstants '
  8564.     category: 'Graphics-Support'!
  8565. CharacterBlockScanner comment:
  8566. 'My instances are used to scan text to compute the CharacterBlock for a character specified by its index in the text or its proximity to the cursor location.'!
  8567.  
  8568. !CharacterBlockScanner methodsFor: 'scanning'!
  8569. characterBlockAtPoint: aPoint in: aParagraph
  8570.     "Answer a CharacterBlock for character in aParagraph at point aPoint. It 
  8571.     is assumed that aPoint has been transformed into coordinates appropriate 
  8572.     to the text's destination form rectangle and the composition rectangle."
  8573.  
  8574.     super initializeFromParagraph: aParagraph clippedBy: aParagraph clippingRectangle.
  8575.     characterPoint _ aPoint.
  8576.     ^self buildCharacterBlockIn: aParagraph!
  8577. characterBlockForIndex: targetIndex in: aParagraph 
  8578.     "Answer a CharacterBlock for character in aParagraph at targetIndex. The 
  8579.     coordinates in the CharacterBlock will be appropriate to the intersection 
  8580.     of the destination form rectangle and the composition rectangle."
  8581.  
  8582.     super 
  8583.         initializeFromParagraph: aParagraph 
  8584.         clippedBy: aParagraph clippingRectangle.
  8585.     characterIndex _ targetIndex.
  8586.     characterPoint _ 
  8587.         aParagraph rightMarginForDisplay @ 
  8588.             (aParagraph topAtLineIndex: 
  8589.                 (aParagraph lineIndexOfCharacterIndex: characterIndex)).
  8590.     ^self buildCharacterBlockIn: aParagraph!
  8591. characterNotInFont
  8592.     "This does not handle character selection nicely, i.e., illegal characters are a 
  8593.     little tricky to select.  Since the end of a run or line is subverted here by actually
  8594.     having the scanner scan a different string in order to manage the illegal 
  8595.     character, things are not in an absolutely correct state for the character 
  8596.     location code.  If this becomes too odious in use, logic will be added to accurately 
  8597.     manage the situation."
  8598.  
  8599.     lastCharacterExtent _ 
  8600.         (font widthOf: (font maxAscii + 1) asCharacter) @ textStyle lineGrid.
  8601.     ^super characterNotInFont! !
  8602.  
  8603. !CharacterBlockScanner methodsFor: 'stop conditions'!
  8604. cr
  8605.     "Answer a CharacterBlock that specifies the current location of the mouse 
  8606.     relative to a carriage return stop condition that has just been 
  8607.     encountered. The ParagraphEditor convention is to denote selections by 
  8608.     CharacterBlocks, sometimes including the carriage return (cursor is at 
  8609.     the end) and sometimes not (cursor is in the middle of the text)."
  8610.  
  8611.     ((characterIndex ~= nil
  8612.         and: [characterIndex > text size])
  8613.             or: [(line last = text size)
  8614.                 and: [(destY + textStyle lineGrid) < characterPoint y]])
  8615.         ifTrue:    ["When off end of string, give data for next character"
  8616.                 destY _ destY +  textStyle lineGrid.
  8617.                 lastCharacter _ nil.
  8618.                 characterPoint _ 
  8619.                     Point
  8620.                         x: ((text at: lastIndex) = CR
  8621.                                 ifTrue: [leftMargin]
  8622.                                 ifFalse: [nextLeftMargin])
  8623.                         y: destY.
  8624.                 lastIndex _ lastIndex + 1.
  8625.                 lastCharacterExtent x: 0.
  8626.                 ^ true].
  8627.         lastCharacter _ CR.
  8628.         characterPoint _ destX @ destY.
  8629.         lastCharacterExtent x: rightMargin - destX.
  8630.         ^true!
  8631. crossedX
  8632.     "Text display has wrapping. The scanner just found a character past the x 
  8633.     location of the cursor. We know that the cursor is pointing at a character 
  8634.     or before one."
  8635.  
  8636.     | leadingTab currentX |
  8637.     ((characterPoint x <= (destX + ((lastCharacterExtent x) // 2)))
  8638.         or: [line last = lastIndex])
  8639.         ifTrue:    [lastCharacter _ (text at: lastIndex).
  8640.                 characterPoint _ destX @ destY.
  8641.                 ^true].
  8642.     "Pointing past middle of a character, return the next character."
  8643.     lastIndex _ lastIndex + 1.
  8644.     lastCharacter _ text at: lastIndex.
  8645.     currentX _ destX + lastCharacterExtent x.
  8646.     lastCharacterExtent x: (font widthOf: lastCharacter).
  8647.     characterPoint _ currentX @ destY.
  8648.  
  8649.     "Yukky if next character is space or tab."
  8650.     (lastCharacter = Space and: [textStyle alignment = Justified])
  8651.         ifTrue:    [lastCharacterExtent x:
  8652.                     (lastCharacterExtent x +     (line justifiedPadFor: (spaceCount + 1))).
  8653.                 ^true].
  8654.     lastCharacter = Space
  8655.         ifTrue:
  8656.             ["See tabForDisplay for illumination on the following awfulness."
  8657.             leadingTab _ true.
  8658.             (line first to: lastIndex - 1) do:
  8659.             [:index |
  8660.             (text at: index) ~= Tab
  8661.                 ifTrue: [leadingTab _ false]].
  8662.             (textStyle alignment ~= Justified or: [leadingTab])
  8663.                 ifTrue:    [lastCharacterExtent x: (textStyle nextTabXFrom: currentX
  8664.                             leftMargin: leftMargin rightMargin: rightMargin) -
  8665.                                 currentX]
  8666.                 ifFalse:    [lastCharacterExtent x:  (((currentX + (textStyle tabWidth -
  8667.                                 (line justifiedTabDeltaFor: spaceCount))) -
  8668.                                     currentX) max: 0)]].
  8669.     ^ true
  8670. !
  8671. endOfRun
  8672.     "Before arriving at the cursor location, the selection has encountered an 
  8673.     end of run. Answer false if the selection continues, true otherwise. Set 
  8674.     up indexes for building the appropriate CharacterBlock."
  8675.  
  8676.     | runLength lineStop |
  8677.     ((characterIndex ~~ nil and:
  8678.         [runStopIndex < characterIndex and: [runStopIndex < text size]])
  8679.             or:    [characterIndex == nil and: [lastIndex < line last]])
  8680.         ifTrue:    ["We're really at the end of a real run."
  8681.                 runLength _ (text runLengthFor: (lastIndex _ lastIndex + 1)).
  8682.                 characterIndex ~~ nil
  8683.                     ifTrue:    [lineStop _ characterIndex    "scanning for index"]
  8684.                     ifFalse:    [lineStop _ line last            "scanning for point"].
  8685.                 (runStopIndex _ lastIndex + (runLength - 1)) > lineStop
  8686.                     ifTrue:     [runStopIndex _ lineStop].
  8687.                 self setStopConditions.
  8688.                 ^false].
  8689.  
  8690.     lastCharacter _ text at: lastIndex.
  8691.     characterPoint _ destX @ destY.
  8692.     ((lastCharacter = Space and: [textStyle alignment = Justified])
  8693.         or: [lastCharacter = Tab and: [lastSpaceOrTabExtent notNil]])
  8694.         ifTrue: [lastCharacterExtent _ lastSpaceOrTabExtent].
  8695.     characterIndex ~~ nil
  8696.         ifTrue:    ["If scanning for an index and we've stopped on that index,
  8697.                 then we back destX off by the width of the character stopped on
  8698.                 (it will be pointing at the right side of the character) and return"
  8699.                 runStopIndex = characterIndex
  8700.                     ifTrue:    [characterPoint x: destX - lastCharacterExtent x.
  8701.                             ^true].
  8702.                 "Otherwise the requested index was greater than the length of the
  8703.                 string.  Return string size + 1 as index, indicate further that off the
  8704.                 string by setting character to nil and the extent to 0."
  8705.                 lastIndex _  lastIndex + 1.
  8706.                 lastCharacter _ nil.
  8707.                 lastCharacterExtent x: 0.
  8708.                 ^true].
  8709.  
  8710.     "Scanning for a point and either off the end of the line or off the end of the string."
  8711.     runStopIndex = text size
  8712.         ifTrue:    ["off end of string"
  8713.                 lastIndex _  lastIndex + 1.
  8714.                 lastCharacter _ nil.
  8715.                 lastCharacterExtent x: 0.
  8716.                 ^true].
  8717.     "just off end of line without crossing x"
  8718.     lastIndex _ lastIndex + 1.
  8719.     ^true!
  8720. paddedSpace
  8721.     "When the line is justified, the spaces will not be the same as the font's 
  8722.     space character. A padding of extra space must be considered in trying 
  8723.     to find which character the cursor is pointing at. Answer whether the 
  8724.     scanning has crossed the cursor."
  8725.  
  8726.     | pad |
  8727.     pad _ 0.
  8728.     spaceCount _ spaceCount + 1.
  8729.     pad _ line justifiedPadFor: spaceCount.
  8730.     lastSpaceOrTabExtent _ lastCharacterExtent copy.
  8731.     lastSpaceOrTabExtent x:  spaceWidth + pad.
  8732.     (destX + lastSpaceOrTabExtent x)  >= characterPoint x
  8733.         ifTrue: [lastCharacterExtent _ lastSpaceOrTabExtent copy.
  8734.                 ^self crossedX].
  8735.     lastIndex _ lastIndex + 1.
  8736.     destX _ destX + lastSpaceOrTabExtent x.
  8737.     ^ false
  8738. !
  8739. setStopConditions
  8740.     "Set the font and the stop conditions for the current run."
  8741.     
  8742.     self setFont.
  8743.     stopConditions at: (Space asciiValue + 1) put:
  8744.         (textStyle alignment = Justified ifTrue: [#paddedSpace] ifFalse: [nil])!
  8745. tab
  8746.     | currentX |
  8747.     currentX _ (textStyle alignment == Justified and: [self leadingTab not])
  8748.         ifTrue:        "imbedded tabs in justified text are weird"
  8749.             [destX + (textStyle tabWidth - (line justifiedTabDeltaFor: spaceCount)) max: destX]
  8750.         ifFalse:
  8751.             [textStyle
  8752.                 nextTabXFrom: destX
  8753.                 leftMargin: leftMargin
  8754.                 rightMargin: rightMargin].
  8755.     lastSpaceOrTabExtent _ lastCharacterExtent copy.
  8756.     lastSpaceOrTabExtent x: (currentX - destX max: 0).
  8757.     currentX >= characterPoint x
  8758.         ifTrue: 
  8759.             [lastCharacterExtent _ lastSpaceOrTabExtent copy.
  8760.             ^self crossedX].
  8761.     destX _ currentX.
  8762.     lastIndex _ lastIndex + 1.
  8763.     ^false! !
  8764.  
  8765. !CharacterBlockScanner methodsFor: 'private'!
  8766. buildCharacterBlockIn: aText
  8767.  
  8768.     | lineIndex runLength lineStop done stopCondition |
  8769.     "handle nullText"
  8770.     (aText numberOfLines = 0 or: [text size = 0])
  8771.         ifTrue:    [^CharacterBlock
  8772.                     stringIndex: 1    "like being off end of string"
  8773.                     character: nil
  8774.                     topLeft: ((aText leftMarginForDisplayForLine: 1) @
  8775.                                 (aText compositionRectangle) top)
  8776.                     extent: (0 @ textStyle lineGrid)].
  8777.  
  8778.     "find the line"
  8779.     lineIndex _ aText lineIndexOfTop: characterPoint y.
  8780.     destY _ (aText topAtLineIndex: lineIndex).
  8781.     line _ aText lines at: lineIndex.
  8782.     rightMargin _ aText rightMarginForDisplay.
  8783.  
  8784.     (lineIndex = aText numberOfLines and:
  8785.         [(destY + textStyle lineGrid) < characterPoint y])
  8786.             ifTrue:    ["if beyond lastLine, force search to last character"
  8787.                     characterPoint x: rightMargin]
  8788.             ifFalse:    [characterPoint y < (aText compositionRectangle) top
  8789.                         ifTrue: ["force search to first line"
  8790.                                 characterPoint _
  8791.                                 (aText compositionRectangle) topLeft].
  8792.                     characterPoint x > rightMargin
  8793.                         ifTrue:    [characterPoint x: rightMargin]].
  8794.     destX _ leftMargin _ aText leftMarginForDisplayForLine: lineIndex.
  8795.     nextLeftMargin_ aText leftMarginForDisplayForLine: lineIndex+1.
  8796.     lastIndex _ line first.
  8797.  
  8798.     self setStopConditions.        "also sets font"
  8799.     runLength _ (text runLengthFor: line first).
  8800.     characterIndex ~~ nil
  8801.         ifTrue:    [lineStop _ characterIndex    "scanning for index"]
  8802.         ifFalse:    [lineStop _ line last].
  8803.     (runStopIndex _ lastIndex + (runLength - 1)) > lineStop
  8804.         ifTrue:    [runStopIndex _ lineStop].
  8805.     lastCharacterExtent _ 0 @ textStyle lineGrid.
  8806.     spaceCount _ 0. done  _ false.
  8807.  
  8808.     [done]
  8809.     whileFalse:
  8810.     [stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex
  8811.             in: text string rightX: characterPoint x
  8812.             stopConditions: stopConditions displaying: false.
  8813.  
  8814.     "see setStopConditions for stopping conditions for character block     operations."
  8815.     lastCharacterExtent x: (font widthOf: (text at: lastIndex)).
  8816.     (self perform: stopCondition)
  8817.         ifTrue:    [^CharacterBlock
  8818.                     stringIndex: lastIndex
  8819.                     character: lastCharacter
  8820.                     topLeft: characterPoint
  8821.                     extent: lastCharacterExtent]]! !BitBlt subclass: #CharacterScanner
  8822.     instanceVariableNames: 'lastIndex xTable stopConditions text textStyle leftMargin rightMargin font line runStopIndex spaceCount spaceWidth '
  8823.     classVariableNames: ''
  8824.     poolDictionaries: 'TextConstants '
  8825.     category: 'Graphics-Support'!
  8826. CharacterScanner comment:
  8827. 'My instances hold the state associated with scanning text. My subclasses scan characters for specified purposes, such as computing a CharacterBlock or placing characters into Forms.'!
  8828.  
  8829. !CharacterScanner methodsFor: 'scanning'!
  8830. characterNotInFont
  8831.     "All fonts have an illegal character to be used when a character is not 
  8832.     within the font's legal range. When characters out of ranged are 
  8833.     encountered in scanning text, then this special character indicates the 
  8834.     appropriate behavior. The character is usually treated as a unary 
  8835.     message understood by a subclass of CharacterScanner."
  8836.  
  8837.     | illegalAsciiString saveIndex stopCondition | 
  8838.     saveIndex _ lastIndex.
  8839.     illegalAsciiString _ String with: (font maxAscii + 1) asCharacter.
  8840.     stopCondition _ 
  8841.         self scanCharactersFrom: 1 to: 1
  8842.             in: illegalAsciiString
  8843.             rightX: rightMargin stopConditions: stopConditions
  8844.             displaying: self doesDisplaying.
  8845.     lastIndex _ saveIndex + 1.
  8846.     stopCondition ~= (stopConditions at: EndOfRun)
  8847.         ifTrue:    [^self perform: stopCondition]
  8848.         ifFalse: [lastIndex = runStopIndex
  8849.                     ifTrue:    [^self perform: (stopConditions at: EndOfRun)].
  8850.                 ^false]
  8851. !
  8852. leadingTab
  8853.     "return true if only tabs lie to the left"
  8854.     line first to: lastIndex do:
  8855.         [:i | (text at: i) == Tab ifFalse: [^ false]].
  8856.     ^ true!
  8857. scanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops displaying: display 
  8858.     "Primitive. This is the inner loop of text display--but see 
  8859.     scanCharactersFrom: to:rightX: which would get the string, 
  8860.     stopConditions and displaying from the instance. March through source 
  8861.     String from startIndex to stopIndex. If any character is flagged with a 
  8862.     non-nil entry in stops, then return the corresponding value. Determine 
  8863.     width of each character from xTable. If dextX would exceed rightX, then 
  8864.     return stops at: 258. If displaying is true, then display the character. 
  8865.     Advance destX by the width of the character. If stopIndex has been 
  8866.     reached, then return stops at: 257. Fail under the same conditions that 
  8867.     the Smalltalk code below would cause an error. Optional. See Object 
  8868.     documentation whatIsAPrimitive."
  8869.     | ascii nextDestX |
  8870.     <primitive: 103>
  8871.     lastIndex _ startIndex.
  8872.     [lastIndex <= stopIndex]
  8873.         whileTrue: 
  8874.             [ascii _ (sourceString at: lastIndex) asciiValue.
  8875.             (stopConditions at: ascii + 1) == nil
  8876.                 ifFalse: [^stops at: ascii + 1].
  8877.             sourceX _ xTable at: ascii + 1.
  8878.             nextDestX _ destX + (width _ (xTable at: ascii + 2) - sourceX).
  8879.             nextDestX > rightX ifTrue: [^stops at: CrossedX].
  8880.             display ifTrue: [self copyBits].
  8881.             destX _ nextDestX.
  8882.             lastIndex _ lastIndex + 1].
  8883.     lastIndex _ stopIndex.
  8884.     ^stops at: EndOfRun! !
  8885.  
  8886. !CharacterScanner methodsFor: 'private'!
  8887. doesDisplaying
  8888.  
  8889.     ^false!
  8890. initializeFromParagraph: aParagraph clippedBy: clippingRectangle
  8891.  
  8892.     text _ aParagraph text.
  8893.     textStyle _ aParagraph textStyle. 
  8894.     destForm _ aParagraph destinationForm.
  8895.     self fillColor: aParagraph fillColor.    "sets halftoneForm"
  8896.     self combinationRule: aParagraph rule.
  8897.     self clipRect: clippingRectangle.
  8898.     sourceY _ 0!
  8899. setFont 
  8900.     "Set the font and the stop conditions for the font."
  8901.     | newFont |
  8902.     newFont _ textStyle fontAt: (text emphasisAt: lastIndex).
  8903.     font == newFont ifTrue: [^ self].  "no need to reinitialize"
  8904.     font _ newFont.
  8905.     spaceWidth _ font widthOf: Space. 
  8906.     sourceForm _ font glyphs.
  8907.     xTable _ font xTable.
  8908.     height _ font height.
  8909.     stopConditions _ font stopConditions.
  8910.     stopConditions at: Space asciiValue + 1 put: #space.
  8911.     stopConditions at: Tab asciiValue + 1 put: #tab.
  8912.     stopConditions at: CR asciiValue + 1 put: #cr.
  8913.     stopConditions at: EndOfRun put: #endOfRun.
  8914.     stopConditions at: CrossedX put: #crossedX! !Object subclass: #CharRecog
  8915.     instanceVariableNames: 'mp p sts pts bmin bmax op cPat in dirs ftrs prevFeatures '
  8916.     classVariableNames: 'CharacterDictionary '
  8917.     poolDictionaries: 'TextConstants '
  8918.     category: 'System-Support'!
  8919. CharRecog comment:
  8920. 'Alan Kay''s "one-page" character recognizer.  Currently hooked up to text panes, such that you can get it started by hitting cmd-r in any pane.  
  8921.  
  8922. To reinitialize the recognition dictionary, evaluate
  8923.  
  8924.     CharRecog reinitializeCharacterDictionary
  8925.  
  8926.  '!
  8927.  
  8928. !CharRecog methodsFor: 'recognizer'!
  8929. directionFrom: p1 to: p2 | ex |
  8930.  
  8931. "This does 8 directions and is not used in current recognizer"
  8932. "get the bounding box"        ex _ p2 - p1. "unlike bmax-bmin, this can have negatives"
  8933.  
  8934. "Look for degenerate forms first: . - |"
  8935. "look for a dot"                ex abs < (3@3) ifTrue: [^' dot... '].
  8936. "look for hori line"            ((ex y = 0) or: [(ex x/ex y) abs > 2]) ifTrue:
  8937.     "look for w-e"                    [ex x > 0 ifTrue:[^' we-- ']
  8938.     "it's an e-w"                        ifFalse:[^' ew-- ']].
  8939. "look for vertical line"        ((ex x = 0) or: [(ex y/ex x) abs > 2]) ifTrue:
  8940.     "look for n-s"                [(ex y > 0) ifTrue:[ ^' ns||']
  8941.     "it's a s-n"                        ifFalse:[^' sn|| ']].
  8942. "look for a diagonal"            (ex x/ex y) abs <= 2 ifTrue:
  8943.     "se or ne"                    [ex x > 0 ifTrue:[ex y > 0 ifTrue:[^' se// ']. ^' ne// '].
  8944.     "sw or nw"                                    ex y > 0 ifTrue:[^' sw// ']. ^' nw// '].
  8945. !
  8946. extractFeatures | xl xr yl yh reg px py |
  8947. "get extent bounding box"    in _ bmax - bmin. 
  8948.  
  8949. "Look for degenerate forms first: . - |"
  8950. "look for a dot"                in < (3@3) ifTrue: [^' dot... '].
  8951.  
  8952. "Feature 5: turns (these are already in ftrs)"
  8953.  
  8954. "Feature 4: absolute size"    in < (10@10) ifTrue: [ftrs _  'SML ', ftrs] ifFalse:
  8955.                             [in <=  (70@70) ifTrue: [ftrs _ 'REG ', ftrs] ifFalse:
  8956.                             [in > (70@70) ifTrue: [ftrs _ 'LRG ', ftrs]]].
  8957.  
  8958. "Feature 3: aspect ratio"
  8959.     "horizontal shape"        ((in y = 0) or: [(in x/in y) abs > 3]) ifTrue:
  8960.                                 [ftrs _ 'HOR ', ftrs] ifFalse:
  8961.     "vertical shape"            [((in x = 0) or: [(in y/in x) abs >= 3]) ifTrue:
  8962.                                 [ftrs _ 'VER ', ftrs] ifFalse:
  8963.     "boxy shape"            [((in x/in y) abs <= 3) ifTrue:
  8964.                                 [ftrs _ 'BOX ', ftrs.
  8965. "Now only for boxes"
  8966. "Feature 2: endstroke reg"    ftrs _ (self regionOf: (pts last)), ftrs.
  8967.                             
  8968. "Feature 1: startstroke reg"    ftrs _ (self regionOf: (pts contents at: 1)), ftrs.]]].
  8969.  
  8970. ^ftrs
  8971.  
  8972.  
  8973.  
  8974. !
  8975. fourDirsFrom:  p1 to: p2 | ex |
  8976.  
  8977. "get the bounding box"        ex _ p2 - p1. "unlike bmax-bmin, this can have negatives"
  8978.  
  8979. "Look for degenerate forms first: . - |"
  8980. "look for a dot"                ex abs < (3@3) ifTrue: [^' dot... '].
  8981. "look for hori line"            ((ex y = 0) or: [(ex x/ex y) abs > 1]) ifTrue:
  8982.     "look for w-e"                    [ex x > 0 ifTrue:[^'WE ']
  8983.     "it's an e-w"                        ifFalse:[^'EW ']].
  8984. "look for vertical line"        ((ex x = 0) or: [(ex y/ex x) abs >= 1]) ifTrue:
  8985.     "look for n-s"                [(ex y > 0) ifTrue:[ ^'NS ']
  8986.     "it's a s-n"                        ifFalse:[^'SN ']].
  8987.  
  8988. "look for a diagonal            (ex x/ex y) abs <= 2 ifTrue:"
  8989.     "se or ne                    [ex x > 0 ifTrue:[ex y > 0 ifTrue:[^' se// ']. ^' ne// ']."
  8990.     "sw or nw                                    ex y > 0 ifTrue:[^' sw// ']. ^' nw// ']."
  8991. !
  8992. learnPrev
  8993.     "The character recognized before this one was wrong.  (Got here via the gesture for 'wrong'.)  Bring up a dialog box on that char.  8/21/96 tk"
  8994.  
  8995.                         | old result |
  8996.     old _ CharacterDictionary at: prevFeatures ifAbsent: [^ ''].
  8997. "get right char from user"    result _ FillInTheBlank request:
  8998.                         ('Redefine the gesture we thought was "', old asString, '".', '
  8999. (Letter or:  tab  cr  wrong  bs  select  caret)
  9000. ', prevFeatures) initialAnswer: '' avoiding: (bmin rounded corner: bmax rounded).
  9001.  
  9002. "ignore or..."                (result = '~' | result = '') ifTrue: ['']
  9003. "...enter new char"            ifFalse: [
  9004.                                 CharacterDictionary at: prevFeatures 
  9005.                                     put: result].
  9006.                     "caller erases bad char"
  9007. "good char"            ^ result!
  9008. recognize | prv cdir result features char r s t dir |
  9009.  
  9010. "Alan Kay's recognizer as of 1/31/96.  This version preserved for historical purposes, and also because it's still called by the not-yet-deployed method recogPar.  Within the current image, the recognizer is now called via #recognizeAndDispatch:until:"
  9011.  
  9012.  
  9013. "Inits"                (p _ Pen new) defaultNib: 1; down.
  9014.     "for points"        pts _ ReadWriteStream on: #().
  9015.  
  9016. "Event Loop"    
  9017.                     [(Sensor mousePoint x) < 50] whileFalse:
  9018.  
  9019. "First-Time"            [pts reset.        
  9020. "will hold features"        ftrs _ ''.
  9021.  
  9022.                       (Sensor anyButtonPressed) ifTrue:
  9023.                         [pts nextPut: (bmin _ bmax _ t _ s _ sts _ Sensor mousePoint).
  9024.                         p place: sts. cdir _ nil.
  9025.  
  9026. "Each-Time"        [Sensor anyButtonPressed] whileTrue:
  9027.                         [
  9028. "ink raw input"            p goto: (r _ Sensor mousePoint).
  9029. "smooth it"                s _ (0.5*s) + (0.5*r).
  9030. "thin the stream"        ((s x - t x) abs > 3 or:[(s y - t y) abs > 3]) ifTrue:
  9031.                             [ pts nextPut: t. 
  9032. "bounding box"            bmin _ bmin min: s. bmax _ bmax max: s.
  9033. "get current dir"                dir _ (self fourDirsFrom: t to: s). t _ s.
  9034.                             dir ~= ' dot... ' ifTrue: [
  9035. "store new dirs"                    cdir ~= dir ifTrue: [ftrs _ ftrs, (cdir _ dir)]].
  9036. "for inked t's"             p place: t; go: 1; place: r.
  9037.                             ].
  9038.  "End Each-Time Loop"    ].
  9039.  
  9040. "Last-Time"    
  9041.  
  9042. "save last points"        pts nextPut: t; nextPut: r.
  9043. "find rest of features"    features _ self extractFeatures.
  9044. "find char..."            char _ CharacterDictionary at: features ifAbsent:
  9045. "...or get from user"            [ result _ FillInTheBlank request:
  9046.                              'Not recognized. type char, or type ~: ', features.
  9047. "ignore or..."                result = '~' ifTrue: ['']
  9048. "...enter new char"            ifFalse: [CharacterDictionary at: features put: result. result]].
  9049.  
  9050. "control the editor"        (char = 'cr' ifTrue: [Transcript cr] ifFalse:
  9051.                         [char = 'bs' ifTrue: [Transcript bs] ifFalse:
  9052.                         [char = 'tab' ifTrue:[Transcript tab] ifFalse:
  9053.                         [Transcript show: char]]]). 
  9054.  
  9055. "End First-Time Loop"    ]. 
  9056.  
  9057. "End Event-Loop" ]. 
  9058.  
  9059.                
  9060.  !
  9061. recognizeAndDispatch: charDispatchBlock ifUnrecognized: unrecognizedFeaturesBlock until: terminationBlock
  9062.     "Recognize characters, and dispatch each one found by evaluating charDispatchBlock; proceed until terminationBlock is true.  This method derives directly from Alan's 1/96 #recognize method, but factors out the character dispatch and the termination condition from the main body of the method.  2/2/96 sw.   2/5/96 sw: switch to using a class variable for the character dictionary, and don't put vacuous entries in the dictionary if the user gives an empty response to the prompt, and don't send empty characters onward, and use a variant of the FillInTheBlank that keeps the prompt clear of the working window.  8/17/96 tk: Turn cr, tab, bs into strings so they work.
  9063.      9/18/96 sw: in this variant, the block for handling unrecognized features is handed in as an argument, so that in some circumstances we can avoid putting up a prompt.  unrecognizedFeaturesBlock should be a one-argument block, which is handed in the features and which is expected to return a string which indicates the determined translation -- empty if none."
  9064.  
  9065.     | prv cdir features char r s t dir |
  9066.  
  9067. "Inits"                (p _ Pen new) defaultNib: 1; down.
  9068.     "for points"        pts _ ReadWriteStream on: #().
  9069.  
  9070. "Event Loop"    
  9071.                     [terminationBlock value] whileFalse:
  9072.  
  9073. "First-Time"            [pts reset.        
  9074. "will hold features"        ftrs _ ''.
  9075.  
  9076.                       (Sensor anyButtonPressed) ifTrue:
  9077.                         [pts nextPut: (bmin _ bmax _ t _ s _ sts _ Sensor mousePoint).
  9078.                         p place: sts. cdir _ nil.
  9079.  
  9080. "Each-Time"        [Sensor anyButtonPressed] whileTrue:
  9081. "ink raw input"            [p goto: (r _ Sensor mousePoint).
  9082. "smooth it"                s _ (0.5*s) + (0.5*r).
  9083. "thin the stream"        ((s x - t x) abs > 3 or:[(s y - t y) abs > 3]) ifTrue:
  9084.                             [pts nextPut: t. 
  9085. "bounding box"                bmin _ bmin min: s. bmax _ bmax max: s.
  9086. "get current dir"                dir _ (self fourDirsFrom: t to: s). t _ s.
  9087.                             dir ~= ' dot... ' ifTrue:
  9088. "store new dirs"                    [cdir ~= dir ifTrue: [ftrs _ ftrs, (cdir _ dir)]].
  9089. "for inked t's"                 p place: t; go: 1; place: r]].
  9090.  "End Each-Time Loop"
  9091.  
  9092. "Last-Time"    
  9093. "save last points"        pts nextPut: t; nextPut: r.
  9094. "find rest of features"    features _ self extractFeatures.
  9095. "find char..."            char _ CharacterDictionary at: features ifAbsent:
  9096.                             [unrecognizedFeaturesBlock value: features].
  9097.  
  9098. "special chars"        char size > 0 ifTrue:
  9099.                         [char = 'tab' ifTrue: [char _ Tab].
  9100.                         char = 'cr' ifTrue:    [char _ CR].
  9101. "must be a string"        char class == Character ifTrue: 
  9102.                             [char _ String with: char].
  9103.                         char = 'bs' ifTrue:    [char _ BS].
  9104. "control the editor"        charDispatchBlock value: char]]]
  9105.  !
  9106. recognizeAndDispatch: charDispatchBlock until: terminationBlock
  9107.     "Recognize characters, and dispatch each one found by evaluating charDispatchBlock; proceed until terminationBlock is true. 9/18/96 sw"
  9108.  
  9109.     ^ self recognizeAndDispatch: charDispatchBlock
  9110.         ifUnrecognized: 
  9111.             [:features | self stringForUnrecognizedFeatures: features]
  9112.         until: terminationBlock
  9113.  !
  9114. recognizeAndPutInTranscript
  9115.     "Call Alan's recognizer repeatedly until the mouse is near the left edge of the screen, and dispatch keystrokes inferred to the Trancript.  2/2/96 sw"
  9116.  
  9117.     ^ self recognizeAndDispatch:
  9118.  
  9119.         [:char | (char = 'cr') ifTrue: [Transcript cr] ifFalse:
  9120.                         [char = 'bs' ifTrue: [Transcript bs] ifFalse:
  9121.                         [char = 'tab' ifTrue:[Transcript tab] ifFalse:
  9122.                         [Transcript show: char]]]]
  9123.  
  9124.         until:
  9125.             [Sensor mousePoint x < 50]
  9126.  
  9127. "CharRecog new recognizeAndPutInTranscript"!
  9128. recogPar | prv cdir result features char r s t dir |
  9129.  
  9130. "Inits"                (p _ Pen new) defaultNib: 1; down.
  9131.     "for points"        pts _ ReadWriteStream on: #().
  9132.  
  9133. "Event Loop"    
  9134.         [Sensor anyButtonPressed] whileFalse: [(Sensor mousePoint x < 50) ifTrue: [^''].].
  9135.  
  9136. "First-Time"            pts reset.        
  9137. "will hold features"        ftrs _ ''.
  9138.  
  9139.                       (Sensor anyButtonPressed) ifTrue:
  9140.                         [pts nextPut: (bmin _ bmax _ t _ s _ sts _ Sensor mousePoint).
  9141.                         p place: sts. cdir _ nil.
  9142.  
  9143. "Each-Time"        [Sensor anyButtonPressed] whileTrue:
  9144.                         [
  9145. "ink raw input"            p goto: (r _ Sensor mousePoint).
  9146. "smooth it"                s _ (0.5*s) + (0.5*r).
  9147. "thin the stream"        ((s x - t x) abs > 3 or:[(s y - t y) abs > 3]) ifTrue:
  9148.                             [ pts nextPut: t. 
  9149. "bounding box"            bmin _ bmin min: s. bmax _ bmax max: s.
  9150. "get current dir"                dir _ (self fourDirsFrom: t to: s). t _ s.
  9151.                             dir ~= ' dot... ' ifTrue: [
  9152. "store new dirs"                    cdir ~= dir ifTrue: [ftrs _ ftrs, (cdir _ dir)]].
  9153. "for inked t's"             p place: t; go: 1; place: r.
  9154.                             ].
  9155.  "End Each-Time Loop"    ].
  9156.  
  9157. "Last-Time"    
  9158. "start a new recog for next point"    [CharRecog new recognize] fork.
  9159.  
  9160. "save last points"        pts nextPut: t; nextPut: r.
  9161. "find rest of features"    features _ self extractFeatures.
  9162. "find char..."            char _ CharacterDictionary at: features ifAbsent:
  9163. "...or get from user"            [ result _ FillInTheBlank request:
  9164.                              'Not recognized. type char, or type ~: ', features.
  9165. "ignore or..."                result = '~' ifTrue: ['']
  9166. "...enter new char"            ifFalse: [CharacterDictionary at: features put: result. result]].
  9167.  
  9168. "control the editor"        (char = 'cr' ifTrue: [Transcript cr] ifFalse:
  9169.                         [char = 'bs' ifTrue: [Transcript bs] ifFalse:
  9170.                         [char = 'tab' ifTrue:[Transcript tab] ifFalse:
  9171.                         [Transcript show: char]]]). 
  9172.  
  9173. "End First-Time Loop"    ]. 
  9174.  
  9175.  
  9176.  
  9177.                
  9178.  !
  9179. regionOf: pt 
  9180.  
  9181. | px py reg xl yl yh xr rg |
  9182. "it's some other character"    rg _ in/3.     xl _ bmin x + rg x. xr _ bmax x - rg x.
  9183. "divide box into 9 regions"                yl _ bmin y + rg y. yh _ bmax y - rg y.
  9184.  
  9185.                     px _ pt x. py _ pt y.
  9186.                     reg _ (px < xl ifTrue: [py < yl ifTrue: ['NW ']
  9187.                                         "py >= yl"    ifFalse:[ py < yh ifTrue:['W ']
  9188.                                                                     ifFalse: ['SW ']]]
  9189.                     ifFalse: [px < xr ifTrue: [py < yl ifTrue: ['N ']
  9190.                                                     ifFalse: [py < yh ifTrue: ['C ']
  9191.                                                                     ifFalse: ['S ']]]
  9192.                     ifFalse: [py < yl ifTrue: ['NE ']
  9193.                                     ifFalse: [py < yh ifTrue: ['E ']
  9194.                                                     ifFalse: ['SE ']]]]).
  9195. ^reg.
  9196.                     !
  9197. stringForUnrecognizedFeatures: features
  9198.     "Prompt the user for what string the current features represent, and return the result.  9/18/96 sw"
  9199.  
  9200.     | result |
  9201.     result _ FillInTheBlank request:
  9202. ('Not recognized. type char, or "tab", "cr" or "bs",
  9203. or hit return to ignore 
  9204. ', features) initialAnswer: '' avoiding: (bmin rounded corner: bmax rounded).
  9205.  
  9206.     ^ (result = '~' | result = '')
  9207.         ifTrue:
  9208.             ['']
  9209.         ifFalse:
  9210.             [CharacterDictionary at: features put: result. result]! !
  9211. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  9212.  
  9213. CharRecog class
  9214.     instanceVariableNames: ''!
  9215.  
  9216. !CharRecog class methodsFor: 'initialization'!
  9217. initialize
  9218.     "Iniitialize the character dictionary if it doesn't exist yet.  2/5/96 sw"
  9219.  
  9220.     CharacterDictionary == nil ifTrue:
  9221.         [CharacterDictionary _ Dictionary new]!
  9222. reinitializeCharacterDictionary
  9223.     "Reset the character dictionary to be empty, ready for a fresh start.  2/5/96 sw"
  9224.  
  9225.     CharacterDictionary _ Dictionary new
  9226.  
  9227. "CharRecog reinitializeCharacterDictionary" ! !
  9228.  
  9229. !CharRecog class methodsFor: 'saving dictionary'!
  9230. readRecognizerDictionaryFrom: aFileName
  9231.     "Read a fresh version of the Recognizer dictionary in from a file of the given name.  7/26/96 sw"
  9232.     "CharRecog readRecognizerDictionaryFrom: 'RecogDictionary.2 fixed'"
  9233.  
  9234.    | aReferenceStream |
  9235.    aReferenceStream _ ReferenceStream fileNamed: aFileName.
  9236.    CharacterDictionary _ aReferenceStream next.
  9237.    aReferenceStream close.
  9238. !
  9239. saveRecognizerDictionaryTo: aFileName
  9240.     "Save the current state of the Recognizer dictionary to disk.  7/26/96 sw"
  9241.  
  9242.    | aReferenceStream |
  9243. aReferenceStream _ ReferenceStream fileNamed: aFileName.
  9244.    aReferenceStream nextPut: CharacterDictionary.
  9245.    aReferenceStream close! !
  9246.  
  9247. CharRecog initialize!
  9248. Arc subclass: #Circle
  9249.     instanceVariableNames: ''
  9250.     classVariableNames: ''
  9251.     poolDictionaries: ''
  9252.     category: 'Graphics-Paths'!
  9253. Circle comment:
  9254. 'I represent a full circle. I am made from four Arcs.'!
  9255.  
  9256. !Circle methodsFor: 'displaying'!
  9257. displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
  9258.  
  9259.     1 to: 4 do:
  9260.         [:i |
  9261.         super quadrant: i.
  9262.         super displayOn: aDisplayMedium
  9263.             at: aPoint
  9264.             clippingBox: clipRect
  9265.             rule: anInteger
  9266.             fillColor: aForm]!
  9267. displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
  9268.  
  9269.     1 to: 4 do:
  9270.         [:i |
  9271.         super quadrant: i.
  9272.         super displayOn: aDisplayMedium
  9273.             transformation: aTransformation
  9274.             clippingBox: clipRect
  9275.             rule: anInteger
  9276.             fillColor: aForm]! !
  9277.  
  9278. !Circle methodsFor: 'display box access'!
  9279. computeBoundingBox
  9280.  
  9281.     ^center - radius + form offset extent: form extent + (radius * 2) asPoint! !
  9282. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  9283.  
  9284. Circle class
  9285.     instanceVariableNames: ''!
  9286.  
  9287. !Circle class methodsFor: 'examples'!
  9288. exampleOne 
  9289.     "Click any button somewhere on the screen. The point will be the center
  9290.     of the circcle of radius 150."
  9291.  
  9292.     | aCircle aForm |
  9293.     aForm _ Form extent: 1@30.
  9294.     aForm fillBlack.
  9295.     aCircle _ Circle new.
  9296.     aCircle form: aForm.
  9297.     aCircle radius: 150.
  9298.     aCircle center: Sensor waitButton.
  9299.     aCircle displayOn: Display
  9300.     
  9301.     "Circle exampleOne"!
  9302. exampleTwo
  9303.     "Designate a rectangular area that should be used as the brush for
  9304.     displaying the circle. Click any button at a point on the screen which
  9305.     will be the center location for the circle. The curve will be displayed
  9306.     with a long black form."
  9307.  
  9308.     | aCircle aForm |
  9309.     aForm _ Form fromUser.
  9310.     aCircle _ Circle new.
  9311.     aCircle form: aForm.
  9312.     aCircle radius: 150.
  9313.     aCircle center: Sensor waitButton.
  9314.     aCircle displayOn: Display at: 0 @ 0 rule: Form reverse
  9315.  
  9316.      "Circle exampleTwo"! !ClassDescription subclass: #Class
  9317.     instanceVariableNames: 'name classPool sharedPools '
  9318.     classVariableNames: ''
  9319.     poolDictionaries: ''
  9320.     category: 'Kernel-Classes'!
  9321. Class comment:
  9322. 'My instances describe the representation and behavior of objects. I add more comprehensive programming support facilities to the basic attributes of Behavior and the descriptive facilities of ClassDescription. An example is accessing shared (pool) variables.'!
  9323.  
  9324. !Class methodsFor: 'initialize-release'!
  9325. declare: varString 
  9326.     "Declare class variables common to all instances. Answer whether 
  9327.     recompilation is advisable."
  9328.  
  9329.     | newVars conflicts assoc class |
  9330.     newVars _ 
  9331.         (Scanner new scanFieldNames: varString)
  9332.             collect: [:x | x asSymbol].
  9333.     newVars do:
  9334.         [:var | var first isLowercase
  9335.             ifTrue: [self error: var, ' class variable name should be capitalized; proceed to include anyway.']].
  9336.     conflicts _ false.
  9337.     classPool == nil 
  9338.         ifFalse: [(classPool keys reject: [:x | newVars includes: x]) do: 
  9339.                     [:var | self removeClassVarName: var]].
  9340.     (newVars reject: [:var | self classPool includesKey: var])
  9341.         do: [:var | "adding"
  9342.             "check if new vars defined elsewhere"
  9343.             (self scopeHas: var ifTrue: [:ignored | ignored])
  9344.                 ifTrue: 
  9345.                     [self error: var , ' is defined elsewhere'.
  9346.                     conflicts _ true]].
  9347.     newVars size > 0
  9348.         ifTrue: 
  9349.             [classPool _ self classPool.
  9350.             "in case it was nil"
  9351.             newVars do: [:var | classPool declare: var from: Undeclared]].
  9352.     ^conflicts!
  9353. obsolete
  9354.     "Change the receiver to an obsolete class by changing its name to have
  9355.     the prefix -AnObsolete-."
  9356.  
  9357.     name _ 'AnObsolete' , name.
  9358.     classPool _ Dictionary new.
  9359.     self class obsolete.
  9360.     super obsolete!
  9361. removeFromSystem
  9362.     "Forget the receiver from the Smalltalk global dictionary. Any existing 
  9363.     instances will refer to an obsolete version of the receiver."
  9364.  
  9365.     Smalltalk removeClassFromSystem: self.
  9366.     self obsolete!
  9367. sharing: poolString 
  9368.     "Set up sharedPools. Answer whether recompilation is advisable."
  9369.     | oldPools poolName pool found |
  9370.     oldPools _ self sharedPools.
  9371.     sharedPools _ OrderedCollection new.
  9372.     (Scanner new scanFieldNames: poolString) do: 
  9373.         [:poolName | 
  9374.         sharedPools add: (Smalltalk at: poolName asSymbol)].
  9375.     sharedPools isEmpty ifTrue: [sharedPools _ nil].
  9376.     oldPools do: [:pool | found _ false.
  9377.                 self sharedPools do: [:p | p == pool ifTrue: [found _ true]].
  9378.                 found ifFalse: [^ true "A pool got deleted"]].
  9379.     ^ false!
  9380. superclass: sup methodDict: md format: ft name: nm organization: org instVarNames: nilOrArray classPool: pool sharedPools: poolSet 
  9381.     "Answer an instance of me, a new class, using the arguments of the 
  9382.     message as the needed information."
  9383.  
  9384.     superclass _ sup.
  9385.     methodDict _ md.
  9386.     format _ ft.
  9387.     name _ nm.
  9388.     organization _ org.
  9389.     instanceVariables _ nilOrArray.
  9390.     classPool _ pool.
  9391.     sharedPools _ poolSet!
  9392. validateFrom: oldClass in: environ instanceVariableNames: invalidFields methods: invalidMethods 
  9393.     "Recompile the receiver and redefine its subclasses if necessary."
  9394.  
  9395.     super
  9396.         validateFrom: oldClass
  9397.         in: environ
  9398.         instanceVariableNames: invalidFields
  9399.         methods: invalidMethods.
  9400.     self ~~ oldClass
  9401.         ifTrue: 
  9402.             [environ at: name put: self.
  9403.             oldClass obsolete]! !
  9404.  
  9405. !Class methodsFor: 'accessing'!
  9406. classPool
  9407.     "Answer the dictionary of class variables."
  9408.  
  9409.     classPool == nil
  9410.         ifTrue: [^Dictionary new]
  9411.         ifFalse: [^classPool]!
  9412. name
  9413.     "Answer the name of the receiver."
  9414.  
  9415.     name == nil
  9416.         ifTrue: [^super name]
  9417.         ifFalse: [^name]! !
  9418.  
  9419. !Class methodsFor: 'testing'!
  9420. hasMethods
  9421.     "Answer a Boolean according to whether any methods are defined for the 
  9422.     receiver (includes whether there are methods defined in the receiver's 
  9423.     metaclass)."
  9424.  
  9425.     ^super hasMethods or: [self class hasMethods]! !
  9426.  
  9427. !Class methodsFor: 'copying'!
  9428. copy
  9429.     | newClass |
  9430.     newClass _ self class copy new
  9431.         superclass: superclass
  9432.         methodDict: methodDict copy
  9433.         format: format
  9434.         name: name
  9435.         organization: organization copy
  9436.         instVarNames: instanceVariables copy
  9437.         classPool: classPool copy
  9438.         sharedPools: sharedPools.
  9439.     Class instSize+1 to: self class instSize do:
  9440.         [:offset | newClass instVarAt: offset put: (self instVarAt: offset)].
  9441.     ^ newClass!
  9442. copyForValidation
  9443.     "Make a copy of the receiver (a class) but do not install the created class 
  9444.     as a new class in the system. This is used for creating a new version of 
  9445.     the receiver in which the installation is deferred until all changes are 
  9446.     successfully completed."
  9447.     | newClass |
  9448.     newClass _ self class copy new
  9449.         superclass: superclass
  9450.         methodDict: methodDict copy
  9451.         format: format
  9452.         name: name
  9453.         organization: organization
  9454.         instVarNames: instanceVariables copy
  9455.         classPool: classPool
  9456.         sharedPools: sharedPools.
  9457.     Class instSize+1 to: self class instSize do:
  9458.         [:offset | newClass instVarAt: offset put: (self instVarAt: offset)].
  9459.     ^ newClass! !
  9460.  
  9461. !Class methodsFor: 'class name'!
  9462. rename: aString 
  9463.     "The new name of the receiver is the argument, aString."
  9464.  
  9465.     | newName |
  9466.     newName _ aString asSymbol.
  9467.     (Smalltalk includesKey: newName)
  9468.         ifTrue: [^self error: newName , ' already exists'].
  9469.     (Undeclared includesKey: newName)
  9470.         ifTrue: [^ PopUpMenu notify: 'There are references to, ' , aString printString , '
  9471. from Undeclared. Check them after this change.'].
  9472.     Smalltalk renameClass: self as: newName.
  9473.     name _ newName.
  9474.     self comment: self comment.
  9475.     self class comment: self class comment! !
  9476.  
  9477. !Class methodsFor: 'instance variables'!
  9478. addInstVarName: aString
  9479.     "Add the argument, aString, as one of the receiver's instance variables."
  9480.  
  9481.     superclass class
  9482.         name: self name
  9483.         inEnvironment: Smalltalk
  9484.         subclassOf: superclass
  9485.         instanceVariableNames: self instanceVariablesString , aString
  9486.         variable: self isVariable
  9487.         words: self isWords
  9488.         pointers: self isPointers
  9489.         classVariableNames: self classVariablesString
  9490.         poolDictionaries: self sharedPoolsString
  9491.         category: self category
  9492.         comment: nil
  9493.         changed: false!
  9494. removeInstVarName: aString 
  9495.     "Remove the argument, aString, as one of the receiver's instance variables."
  9496.  
  9497.     | newInstVarString |
  9498.     (self instVarNames includes: aString)
  9499.         ifFalse: [self error: aString , ' is not one of my instance variables'].
  9500.     newInstVarString _ ''.
  9501.     (self instVarNames copyWithout: aString) do: 
  9502.         [:varName | newInstVarString _ newInstVarString , ' ' , varName].
  9503.     superclass class
  9504.         name: self name
  9505.         inEnvironment: Smalltalk
  9506.         subclassOf: superclass
  9507.         instanceVariableNames: newInstVarString
  9508.         variable: self isVariable
  9509.         words: self isWords
  9510.         pointers: self isPointers
  9511.         classVariableNames: self classVariablesString
  9512.         poolDictionaries: self sharedPoolsString
  9513.         category: self category
  9514.         comment: nil
  9515.         changed: false! !
  9516.  
  9517. !Class methodsFor: 'class variables'!
  9518. addClassVarName: aString 
  9519.     "Add the argument, aString, as a class variable of the receiver.
  9520.     Signal an error if the first character of aString is not capitalized,
  9521.     or if it is already a variable named in the class."
  9522.     | symbol index |
  9523.     aString first isLowercase
  9524.         ifTrue: [^self error: aString, ' class variable name should be capitalized; proceed to include anyway.'].
  9525.     symbol _ aString asSymbol.
  9526.     self withAllSubclasses do: 
  9527.         [:subclass | 
  9528.         subclass scopeHas: symbol
  9529.             ifTrue: [:temp | 
  9530.                     ^ self error: aString 
  9531.                         , ' is already used as a variable name in class ' 
  9532.                         , subclass name]].
  9533.     classPool == nil ifTrue: [classPool _ Dictionary new].
  9534.     (classPool includesKey: symbol) ifFalse: 
  9535.         ["Pick up any refs in Undeclared"
  9536.         classPool declare: symbol from: Undeclared.
  9537.         Smalltalk changes changeClass: self]!
  9538. allClassVarNames
  9539.     "Answer a Set of the names of the receiver's class variables, including those
  9540.     defined in the superclasses of the receiver."
  9541.  
  9542.     | aSet |
  9543.     superclass == nil
  9544.         ifTrue: 
  9545.             [^self classVarNames]  "This is the keys so it is a new Set."
  9546.         ifFalse: 
  9547.             [aSet _ superclass allClassVarNames.
  9548.             aSet addAll: self classVarNames.
  9549.             ^aSet]!
  9550. classVarNames
  9551.     "Answer a Set of the names of the class variables defined in the receiver."
  9552.  
  9553.     ^self classPool keys!
  9554. initialize
  9555.     "Typically used for the initialization of class variables and metaclass 
  9556.     instance variables. Does nothing, but may be overridden in Metaclasses."
  9557.  
  9558.     ^self!
  9559. removeClassVarName: aString 
  9560.     "Remove the class variable whose name is the argument, aString, from 
  9561.     the names defined in the receiver, a class. Create an error notification if 
  9562.     aString is not a class variable or if it is still being used in the code of 
  9563.     the class."
  9564.  
  9565.     | anAssoc aSymbol |
  9566.     aSymbol _ aString asSymbol.
  9567.     (classPool includesKey: aSymbol)
  9568.         ifFalse: [^self error: aString, ' is not a class variable'].
  9569.     anAssoc _ classPool associationAt: aSymbol.
  9570.     self withAllSubclasses do:
  9571.         [:subclass |
  9572.         (Array with: subclass with: subclass class) do:
  9573.             [:classOrMeta |
  9574.             (classOrMeta whichSelectorsReferTo: (classPool associationAt: aSymbol))
  9575.                 isEmpty
  9576.                     ifFalse: [^self error: aString
  9577.                                 , ' is still used in code of class '
  9578.                                 , classOrMeta name]]].
  9579.     classPool removeKey: aSymbol! !
  9580.  
  9581. !Class methodsFor: 'pool variables'!
  9582. addSharedPool: aDictionary 
  9583.     "Add the argument, aDictionary, as one of the receiver's pool dictionaries. 
  9584.     Create an error if the dictionary is already one of the pools."
  9585.  
  9586.     (self sharedPools includes: aDictionary)
  9587.         ifTrue: [^self error: 'The dictionary is already in my pool'].
  9588.     sharedPools == nil
  9589.         ifTrue: [sharedPools _ OrderedCollection with: aDictionary]
  9590.         ifFalse: [sharedPools add: aDictionary]!
  9591. allSharedPools
  9592.     "Answer a Set of the pools the receiver shares, including those defined 
  9593.     in the superclasses of the receiver."
  9594.  
  9595.     | aSet |
  9596.     superclass == nil
  9597.         ifTrue:
  9598.             [^self sharedPools copy]
  9599.         ifFalse: 
  9600.             [aSet _ superclass allSharedPools.
  9601.             aSet addAll: self sharedPools.
  9602.             ^aSet]!
  9603. removeSharedPool: aDictionary 
  9604.     "Remove the pool dictionary, aDictionary, as one of the receiver's pool 
  9605.     dictionaries. Create an error notification if the dictionary is not one of 
  9606.     the pools.
  9607.     9/12/96 tk: Note that it removes the wrong one if there are two empty Dictionaries in the list."
  9608.  
  9609.     | satisfiedSet workingSet aSubclass|
  9610.     (self sharedPools includes: aDictionary)
  9611.         ifFalse: [^self error: 'the dictionary is not in my pool'].
  9612.  
  9613.     "first see if it is declared in a superclass in which case we can remove it."
  9614.     (self selectSuperclasses: [:class | class sharedPools includes: aDictionary]) isEmpty
  9615.         ifFalse: [sharedPools remove: aDictionary.
  9616.                 sharedPools isEmpty ifTrue: [sharedPools _ nil].
  9617.                 ^self]. 
  9618.  
  9619.     "second get all the subclasses that reference aDictionary through me rather than a 
  9620.     superclass that is one of my subclasses."
  9621.  
  9622.     workingSet _ self subclasses asOrderedCollection.
  9623.     satisfiedSet _ Set new.
  9624.     [workingSet isEmpty] whileFalse:
  9625.         [aSubclass _ workingSet removeFirst.
  9626.         (aSubclass sharedPools includes: aDictionary)
  9627.             ifFalse: 
  9628.                 [satisfiedSet add: aSubclass.
  9629.                 workingSet addAll: aSubclass subclasses]].
  9630.  
  9631.     "for each of these, see if they refer to any of the variables in aDictionary because 
  9632.     if they do, we can not remove the dictionary."
  9633.     satisfiedSet add: self.
  9634.     satisfiedSet do: 
  9635.         [:aSubclass | 
  9636.         aDictionary associationsDo: 
  9637.             [:aGlobal | 
  9638.             (aSubclass whichSelectorsReferTo: aGlobal) isEmpty 
  9639.                 ifFalse: [^self error: aGlobal key 
  9640.                                 , ' is still used in code of class '
  9641.                                 , aSubclass name]]].
  9642.     sharedPools remove: aDictionary.
  9643.     sharedPools isEmpty ifTrue: [sharedPools _ nil]!
  9644. sharedPools
  9645.     "Answer a Set of the pool dictionaries declared in the receiver."
  9646.  
  9647.     sharedPools == nil
  9648.         ifTrue: [^OrderedCollection new]
  9649.         ifFalse: [^sharedPools]! !
  9650.  
  9651. !Class methodsFor: 'compiling'!
  9652. compileAllFrom: oldClass
  9653.     "Recompile all the methods in the receiver's method dictionary (not the
  9654.     subclasses). Also recompile the methods in the metaclass."
  9655.  
  9656.     super compileAllFrom: oldClass.
  9657.     self class compileAllFrom: oldClass class!
  9658. possibleVariablesFor: misspelled continuedFrom: oldResults
  9659.  
  9660.     | results |
  9661.     results _ misspelled correctAgainstDictionary: self classPool continuedFrom: oldResults.
  9662.     self sharedPools do: [:pool | 
  9663.         results _ misspelled correctAgainstDictionary: pool continuedFrom: results ].
  9664.     superclass == nil
  9665.         ifTrue: 
  9666.             [ ^ misspelled correctAgainstDictionary: Smalltalk continuedFrom: results ]
  9667.         ifFalse:
  9668.             [ ^ superclass possibleVariablesFor: misspelled continuedFrom: results ]!
  9669. scopeHas: varName ifTrue: assocBlock 
  9670.     "Look up the first argument, varName, in the context of the receiver. If it is there,
  9671.     pass the association to the second argument, assocBlock, and answer true.
  9672.     Else answer false.
  9673.     9/11/96 tk: Allow key in shared pools to be a string for HyperSqueak"
  9674.  
  9675.     | assoc pool |
  9676.     assoc _ self classPool associationAt: varName ifAbsent: [].
  9677.     assoc == nil
  9678.         ifFalse: 
  9679.             [assocBlock value: assoc.
  9680.             ^true].
  9681.     self sharedPools do: 
  9682.         [:pool | 
  9683.         varName = #Textual ifTrue: [self halt].
  9684.         assoc _ pool associationAt: varName ifAbsent: [
  9685.             pool associationAt: varName asString ifAbsent: []].
  9686.         assoc == nil
  9687.             ifFalse: 
  9688.                 [assocBlock value: assoc.
  9689.                 ^true]].
  9690.     superclass == nil
  9691.         ifTrue: 
  9692.             [assoc _ Smalltalk associationAt: varName ifAbsent: [].
  9693.             assoc == nil
  9694.                 ifFalse: 
  9695.                     [assocBlock value: assoc.
  9696.                     ^true].
  9697.             ^false].
  9698.     ^superclass scopeHas: varName ifTrue: assocBlock! !
  9699.  
  9700. !Class methodsFor: 'subclass creation'!
  9701. subclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat 
  9702.     "This is the standard initialization message for creating a new class as a 
  9703.     subclass of an existing class (the receiver)."
  9704.  
  9705.     self isVariable
  9706.         ifTrue: 
  9707.             [self isPointers 
  9708.                 ifTrue: [^self
  9709.                             variableSubclass: t
  9710.                             instanceVariableNames: f
  9711.                             classVariableNames: d
  9712.                             poolDictionaries: s
  9713.                             category: cat].
  9714.             self isBytes 
  9715.                 ifTrue: [^self
  9716.                             variableByteSubclass: t
  9717.                             instanceVariableNames: f
  9718.                             classVariableNames: d
  9719.                             poolDictionaries: s
  9720.                             category: cat].
  9721.             ^self
  9722.                 variableWordSubclass: t
  9723.                 instanceVariableNames: f
  9724.                 classVariableNames: d
  9725.                 poolDictionaries: s
  9726.                 category: cat].
  9727.     ^self class
  9728.         name: t
  9729.         inEnvironment: Smalltalk
  9730.         subclassOf: self
  9731.         instanceVariableNames: f
  9732.         variable: false
  9733.         words: true
  9734.         pointers: true
  9735.         classVariableNames: d
  9736.         poolDictionaries: s
  9737.         category: cat
  9738.         comment: nil
  9739.         changed: false!
  9740. variableByteSubclass: t instanceVariableNames: f 
  9741.     classVariableNames: d poolDictionaries: s category: cat
  9742.     "This is the standard initialization message for creating a new class as a 
  9743.     subclass of an existing class (the receiver) in which the subclass is to 
  9744.     have indexable byte-sized nonpointer variables."
  9745.  
  9746.     self instSize > 0 
  9747.         ifTrue: [^self error: 'cannot make a byte subclass of a class with named fields'].
  9748.     (self isVariable and: [self isWords])
  9749.         ifTrue: [^self error: 'cannot make a byte subclass of a class with word fields'].
  9750.     (self isVariable and: [self isPointers])
  9751.         ifTrue: [^self error: 
  9752.                     'cannot make a byte subclass of a class with pointer fields'].
  9753.     ^self class name: t 
  9754.         inEnvironment: Smalltalk
  9755.         subclassOf: self 
  9756.         instanceVariableNames: f
  9757.         variable: true 
  9758.         words: false 
  9759.         pointers: false
  9760.         classVariableNames: d 
  9761.         poolDictionaries: s 
  9762.         category: cat 
  9763.         comment: nil
  9764.         changed: false!
  9765. variableSubclass: t instanceVariableNames: f 
  9766.     classVariableNames: d poolDictionaries: s category: cat
  9767.     "This is the standard initialization message for creating a new class as a 
  9768.     subclass of an existing class (the receiver) in which the subclass is to 
  9769.     have indexable pointer variables."
  9770.  
  9771.     self isBits 
  9772.         ifTrue: 
  9773.             [^self error: 
  9774.                 'cannot make a pointer subclass of a class with non-pointer fields'].
  9775.     ^self class name: t 
  9776.         inEnvironment: Smalltalk
  9777.         subclassOf: self 
  9778.         instanceVariableNames: f
  9779.         variable: true 
  9780.         words: true 
  9781.         pointers: true
  9782.         classVariableNames: d 
  9783.         poolDictionaries: s 
  9784.         category: cat 
  9785.         comment: nil
  9786.         changed: false!
  9787. variableWordSubclass: t instanceVariableNames: f 
  9788.     classVariableNames: d poolDictionaries: s category: cat
  9789.     "This is the standard initialization message for creating a new class as a 
  9790.     subclass of an existing class (the receiver) in which the subclass is to 
  9791.     have indexable word-sized nonpointer variables."
  9792.  
  9793.     self instSize > 0 
  9794.         ifTrue: [^self error: 
  9795.                     'cannot make a word subclass of a class with named fields'].
  9796.     self isBytes
  9797.         ifTrue: [^self error: 'cannot make a word subclass of a class with byte fields'].
  9798.     (self isVariable and: [self isPointers])
  9799.         ifTrue: [^self error: 
  9800.                     'cannot make a word subclass of a class with pointer fields'].
  9801.     ^self class name: t 
  9802.         inEnvironment: Smalltalk
  9803.         subclassOf: self 
  9804.         instanceVariableNames: f
  9805.         variable: true 
  9806.         words: true 
  9807.         pointers: false
  9808.         classVariableNames: d 
  9809.         poolDictionaries: s 
  9810.         category: cat 
  9811.         comment: nil
  9812.         changed: false! !
  9813.  
  9814. !Class methodsFor: 'fileIn/Out'!
  9815. fileOut
  9816.     "Create a file whose name is the name of the receiver with '.st' as the 
  9817.     extension, and file a description of the receiver onto it."
  9818.     | fileStream |
  9819.     fileStream _ FileStream newFileNamed: self name , '.st'.
  9820.     fileStream header; timeStamp.
  9821.     self sharedPools size > 0 ifTrue:
  9822.         [self shouldFileOutPools
  9823.             ifTrue: [self fileOutSharedPoolsOn: fileStream]].
  9824.     self fileOutOn: fileStream
  9825.         moveSource: false
  9826.         toFile: 0.
  9827.     fileStream trailer; close!
  9828. fileOutMethod: selector
  9829.     "Write source code of a single method on a file.  Make up a name for the file."
  9830.     | fileStream |
  9831.     (self includesSelector: selector) ifFalse: [^ self].
  9832.     fileStream _ FileStream newFileNamed: 
  9833.         (self name , '-' , (selector copyReplaceAll: ':' with: '')) , '.st'.
  9834.     fileStream header; timeStamp.
  9835.     self printCategoryChunk: (self whichCategoryIncludesSelector: selector)
  9836.         on: fileStream.
  9837.     self printMethodChunk: selector
  9838.         on: fileStream
  9839.         moveSource: false
  9840.         toFile: 0.
  9841.     fileStream nextChunkPut: ' '; trailer; close!
  9842. fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex 
  9843.     "File a description of the receiver on aFileStream. If the boolean argument,
  9844.     moveSource, is true, then set the trailing bytes to the position of aFileStream and
  9845.     to fileIndex in order to indicate where to find the source code."
  9846.  
  9847.     Transcript cr; show: name.
  9848.     super
  9849.         fileOutOn: aFileStream
  9850.         moveSource: moveSource
  9851.         toFile: fileIndex.
  9852.     self class nonTrivial
  9853.         ifTrue:
  9854.             [aFileStream cr; nextPutAll: '"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!!'; cr; cr.
  9855.             self class
  9856.                 fileOutOn: aFileStream
  9857.                 moveSource: moveSource
  9858.                 toFile: fileIndex]!
  9859. fileOutPool: aPool onFileStream: aFileStream 
  9860.     | aPoolName |
  9861.     aPoolName _ Smalltalk keyAtValue: aPool.
  9862.     Transcript cr; show: aPoolName.
  9863.     aFileStream nextPutAll: 'Transcript show: ''' , aPoolName , '''; cr!!'; cr.
  9864.     aFileStream nextPutAll: 'Smalltalk at: #' , aPoolName , ' put: Dictionary new!!'; cr.
  9865.     aPool asSortedCollection do: [ :anItem | 
  9866.         aFileStream nextPutAll: aPoolName , ' at: #' , anItem key asString , ' put:  '.
  9867.         (anItem value isKindOf: Number)
  9868.             ifTrue: [anItem value printOn: aFileStream]
  9869.             ifFalse: [aFileStream nextPutAll: '('.
  9870.                     anItem value printOn: aFileStream.
  9871.                     aFileStream nextPutAll: ')'].
  9872.         aFileStream nextPutAll: '!!'; cr].
  9873.     aFileStream cr!
  9874. fileOutSharedPoolsOn: aFileStream
  9875.     "file out the shared pools of this class after prompting the user about each pool"
  9876.     | poolsToFileOut |
  9877.     poolsToFileOut _ self sharedPools select: 
  9878.         [:aPool | (self shouldFileOutPool: (Smalltalk keyAtValue: aPool))].
  9879.     poolsToFileOut do: [:aPool | self fileOutPool: aPool onFileStream: aFileStream].
  9880.     !
  9881. reformatAll 
  9882.     "Reformat all methods in this class.
  9883.     Leaves old code accessible to version browsing"
  9884.     super reformatAll.        "me..."
  9885.     self class reformatAll    "...and my metaclass"!
  9886. removeFromChanges
  9887.     "References to the receiver, a class, and its metaclass should no longer be included in the system ChangeSet.
  9888.     7/18/96 sw: call removeClassAndMetaClassChanges:"
  9889.  
  9890.     Smalltalk changes removeClassAndMetaClassChanges: self!
  9891. shouldFileOutPool: aPoolName
  9892.     "respond with true if the user wants to file out aPoolName"
  9893.     ^self confirm: ('FileOut the sharedPool ', aPoolName, '?')!
  9894. shouldFileOutPools
  9895.     "respond with true if the user wants to file out the shared pools"
  9896.     ^self confirm: 'FileOut selected sharedPools?'! !
  9897. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  9898.  
  9899. Class class
  9900.     instanceVariableNames: ''!
  9901.  
  9902. !Class class methodsFor: 'instance creation'!
  9903. template: category 
  9904.     "Answer an expression that can be edited and evaluated in order to 
  9905.     define a new class."
  9906.  
  9907.     ^'Object subclass: #NameOfClass
  9908.     instanceVariableNames: ''instVarName1 instVarName2''
  9909.     classVariableNames: ''ClassVarName1 ClassVarName2''
  9910.     poolDictionaries: ''''
  9911.     category: ''' , category , ''''! !
  9912.  
  9913. !Class class methodsFor: 'fileIn/Out'!
  9914. fileOutPool: aString
  9915.     "file out the global pool named aString"
  9916.     | f |
  9917.     f _ FileStream newFileNamed: aString, '.st'.
  9918.     self new fileOutPool: (Smalltalk at: aString asSymbol) onFileStream: f.     f close.
  9919.     ! !Object subclass: #ClassCategoryReader
  9920.     instanceVariableNames: 'class category '
  9921.     classVariableNames: ''
  9922.     poolDictionaries: ''
  9923.     category: 'Kernel-Support'!
  9924. ClassCategoryReader comment:
  9925. 'I represent a mechanism for retrieving class descriptions stored on a file.'!
  9926.  
  9927. !ClassCategoryReader methodsFor: 'fileIn/Out'!
  9928. scanFrom: aStream 
  9929.     "File in methods from the stream, aStream. Print the name and category of 
  9930.     the methods in the transcript view."
  9931.  
  9932.     | string |
  9933.     [string _ aStream nextChunk.
  9934.     string size > 0]                        "done when double terminators"
  9935.         whileTrue: [class compile: string classified: category].
  9936.     Transcript show: class name , '<' , category , '
  9937. '! !
  9938.  
  9939. !ClassCategoryReader methodsFor: 'private'!
  9940. setClass: aClass category: aCategory
  9941.  
  9942.     class _ aClass.
  9943.     category _ aCategory! !
  9944. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  9945.  
  9946. ClassCategoryReader class
  9947.     instanceVariableNames: ''!
  9948.  
  9949. !ClassCategoryReader class methodsFor: 'instance creation'!
  9950. class: aClass category: aCategory 
  9951.     "Answer an instance of me for the category, aCategory, of the class, 
  9952.     aClass."
  9953.  
  9954.     ^self new setClass: aClass category: aCategory! !ClassCategoryReader subclass: #ClassCompiledCategoryReader
  9955.     instanceVariableNames: ''
  9956.     classVariableNames: 'NewMethods '
  9957.     poolDictionaries: ''
  9958.     category: 'Kernel-Support'!
  9959. ClassCompiledCategoryReader comment:
  9960. 'A ClassCompiledCategoryReader reads a series of compiled methods stored in the following format and terminated by an extra $!!.
  9961.     <header word>!!<byte codes in hex>!!
  9962.     <literal storeStrings each terminated by a space>
  9963.     !!<method selector>!!<source code>!!
  9964. See Behavior<storeLiteral:on: to explain ##<global name> and ###< class name>.
  9965.  
  9966. When the file name ends with .f.st, this format is produced by the method ClassDescriptio<printMethodChunk:on:moveSource:toFile:.  Also see ClassDescription<printCategoryChunk:on:.
  9967.  
  9968. CompiledMethods are not installed when read.  Instead, they are added to a collection NewMethods (a class variable) whose elements are arrays of the form
  9969. {class. category. selector. compiledMethod}.  Later in the file (after all classes and methods have been defined, but before calls on initialize methods have been made), there should be a call on:
  9970.             ClassCompiledCategoryReader installNewMethods.
  9971. This call is produced by the methods ChangeSet<fileOutOn: and ReadWriteStream<fileOutChangesFor: when the file name ends with .f.st'!
  9972.  
  9973. !ClassCompiledCategoryReader methodsFor: 'fileIn/Out'!
  9974. scanFrom: aStream 
  9975.     "File in compiled methods from the stream, aStream. Much faster than
  9976.      superclass method.  To save even more time, do not print the name and
  9977.      category of the methods in the transcript view."
  9978.     | file string header byteCodes method mStrm scanner selector remoteString |
  9979.     file _ SourceFiles at: 2.
  9980.     file isNil ifFalse:
  9981.         [file setToEnd. class printCategoryChunk: category on: file. file cr].
  9982.     [string _ aStream nextChunk.
  9983.      string size > 0]                        "done when double terminators"
  9984.         whileTrue:
  9985.             [header _ string asNumber.
  9986.             byteCodes _ ByteArray fromHex: aStream nextChunk.
  9987.             method _ CompiledMethod
  9988.                         newMethod: byteCodes size+3
  9989.                         header: header.
  9990.             mStrm _ ReadWriteStream with: method.
  9991.             mStrm position: method initialPC - 1.
  9992.             mStrm nextPutAll: byteCodes.
  9993.             scanner _ Scanner new scan: (ReadStream on: aStream nextChunk).
  9994.             1 to: method numLiterals do:
  9995.                 [:i |
  9996.                  method literalAt: i put:
  9997.                     (class literalScannedAs: scanner nextLiteral notifying: nil)].
  9998.             selector _ aStream nextChunk asSymbol.
  9999.             file isNil ifFalse:
  10000.                 [remoteString _ RemoteString new
  10001.                     fromFile: aStream
  10002.                     onFileNumber: 2
  10003.                     toFile: file.
  10004.                  method setSourcePosition: remoteString position inFile: 2].
  10005.             NewMethods add:
  10006.                 (Array with: class with: category with: selector with: method)].
  10007.     file isNil ifFalse: [file nextChunkPut: ' '; flush]! !
  10008. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  10009.  
  10010. ClassCompiledCategoryReader class
  10011.     instanceVariableNames: ''!
  10012.  
  10013. !ClassCompiledCategoryReader class methodsFor: 'class initialization'!
  10014. initialize
  10015.  
  10016.     NewMethods _ OrderedCollection new: 100
  10017.  
  10018. "ClassCompiledCategoryReader initialize"! !
  10019.  
  10020. !ClassCompiledCategoryReader class methodsFor: 'fileIn/Out'!
  10021. installNewMethods
  10022.  
  10023.     | clsCatSelMth class category selector method |
  10024.     NewMethods do: 
  10025.         [:clsCatSelMth |
  10026.         class _ clsCatSelMth at: 1.
  10027.         category _ clsCatSelMth at: 2.
  10028.         selector _ clsCatSelMth at: 3.
  10029.         method _ clsCatSelMth at: 4.
  10030.         (methodDict includesKey: selector)
  10031.             ifTrue: [Smalltalk changes changeSelector: selector class: class]
  10032.             ifFalse: [Smalltalk changes addSelector: selector class: class].
  10033.         class organization classify: selector under: category.
  10034.         class addSelector: selector withMethod: method].
  10035.     self initialize! !
  10036.  
  10037. ClassCompiledCategoryReader initialize!
  10038. Behavior subclass: #ClassDescription
  10039.     instanceVariableNames: 'instanceVariables organization '
  10040.     classVariableNames: ''
  10041.     poolDictionaries: ''
  10042.     category: 'Kernel-Classes'!
  10043. ClassDescription comment:
  10044. 'I add a number of facilities to basic Behavior:
  10045.     Named instance variables
  10046.     Category organization for methods
  10047.     The notion of a name of this class (implemented as subclass responsibility)
  10048.     The maintenance of a ChangeSet, and logging changes on a file
  10049.     Most of the mechanism for fileOut.
  10050.     
  10051. I am an abstract class, in particular, my facilities are intended for inheritance by two subclasses, Class and Metaclass.'!
  10052.  
  10053. !ClassDescription methodsFor: 'initialize-release'!
  10054. obsolete
  10055.     "Make the receiver obsolete."
  10056.  
  10057.     organization _ nil.
  10058.     super obsolete!
  10059. subclassOf: newSuper oldClass: oldClass instanceVariableNames: newInstVarString variable: v words: w pointers: p ifBad: badBlock 
  10060.     "Basic initialization message for creating classes using the information 
  10061.     provided as arguments. Answer whether old instances will be 
  10062.     invalidated."
  10063.  
  10064.     | oldNames newNames usedNames invalid oldSuperMeta newInstVarArray oldSpec |
  10065.     oldNames _ self allInstVarNames.
  10066.     usedNames _ #(self super thisContext true false nil ) asSet.
  10067.     newInstVarArray _ Scanner new scanFieldNames: newInstVarString.
  10068.     newNames _ newSuper allInstVarNames , newInstVarArray.
  10069.     newNames size > 62
  10070.         ifTrue: [self error: 'A class cannot have more than 62 instance variables'.
  10071.                 ^ badBlock value].
  10072.     newNames do: 
  10073.         [:fieldName | 
  10074.         (usedNames includes: fieldName)
  10075.             ifTrue: 
  10076.                 [self error: fieldName , ' is reserved (maybe in a superclass)'.
  10077.                 ^ badBlock value].
  10078.         usedNames add: fieldName].
  10079.     (invalid _ superclass ~~ newSuper)
  10080.         ifTrue: 
  10081.             ["superclass changed"
  10082.             oldSuperMeta _ superclass class.
  10083.             superclass removeSubclass: self.
  10084.             superclass _ newSuper.
  10085.             superclass addSubclass: self.
  10086.             self class superclass == oldSuperMeta 
  10087.                 ifTrue: ["Only false when self is a metaclass"
  10088.                         self class superclass: newSuper class]].
  10089.     instanceVariables _ newInstVarArray size = 0 ifFalse: [newInstVarArray].
  10090.     invalid _ invalid |   "field names changed"
  10091.             (newNames size < oldNames size or:
  10092.                 [(newNames copyFrom: 1 to: oldNames size) ~= oldNames]).
  10093.     oldSpec _ self instSpec.
  10094.     self
  10095.         format: newNames size
  10096.         variable: v
  10097.         words: w
  10098.         pointers: p.
  10099.     invalid _ invalid | (self instSpec ~= oldSpec).  "format changed"
  10100.     ^invalid!
  10101. updateInstancesFrom: oldClass 
  10102.     "Recreate any existing instances of the argument, oldClass, as instances of 
  10103.     the receiver, which is a newly changed class. Permute variables as 
  10104.     necessary."
  10105.  
  10106.     | oldInstVarNames map variable old new instSize offset fieldName oldInstances |
  10107.     oldClass someInstance == nil ifTrue: [^self].
  10108.     "no instances to convert"
  10109.     oldInstVarNames _ oldClass allInstVarNames.
  10110.     map _ 
  10111.         self allInstVarNames 
  10112.             collect: [:instVarName | oldInstVarNames indexOf: instVarName].
  10113.     variable _ self isVariable.
  10114.     instSize _ self instSize.
  10115.  
  10116.     "Now perform a bulk mutation of old instances into new ones"
  10117.     oldInstances _ oldClass allInstances asArray.
  10118.     oldInstances elementsExchangeIdentityWith:
  10119.         (oldInstances collect: 
  10120.         [:old | 
  10121.         variable
  10122.             ifTrue: [new _ self basicNew: old basicSize]
  10123.             ifFalse: [new _ self basicNew].
  10124.         1 to: instSize do: 
  10125.             [:offset |  (map at: offset) > 0 ifTrue:
  10126.                 [new instVarAt: offset
  10127.                         put: (old instVarAt: (map at: offset))]].
  10128.         variable 
  10129.             ifTrue: [1 to: old basicSize do: 
  10130.                         [:offset |
  10131.                         new basicAt: offset put: (old basicAt: offset)]].
  10132.         new])!
  10133. validateFrom: oldClass in: environ instanceVariableNames: invalidFields methods: invalidMethods 
  10134.     "Recompile the receiver, a class, and redefine its subclasses if necessary.
  10135.     The parameter invalidFields is no longer really used"
  10136.  
  10137.     | sub newSub invalidSubMethods |
  10138.     oldClass becomeUncompact.  "Its about to be abandoned"
  10139.     invalidMethods & self hasMethods
  10140.         ifTrue: 
  10141.             [Transcript show: 'recompiling ' , self name , '...'.
  10142.             self compileAllFrom: oldClass.
  10143.             Transcript show: ' done'; cr].
  10144.     invalidSubMethods _ invalidMethods | (self instSize ~= oldClass instSize).
  10145.     self == oldClass
  10146.         ifTrue: [invalidSubMethods ifFalse: [^self]]
  10147.         ifFalse: [self updateInstancesFrom: oldClass].
  10148.     oldClass subclasses do: 
  10149.         [:sub | 
  10150.         newSub _ sub copyForValidation.
  10151.         newSub
  10152.             subclassOf: self
  10153.             oldClass: sub
  10154.             instanceVariableNames: sub instVarNames
  10155.             variable: sub isVariable
  10156.             words: sub isBytes not
  10157.             pointers: sub isBits not
  10158.             ifBad: [self error: 'terrible problem in recompiling subclasses!!'].
  10159.         newSub
  10160.             validateFrom: sub
  10161.             in: environ
  10162.             instanceVariableNames: invalidFields
  10163.             methods: invalidSubMethods]! !
  10164.  
  10165. !ClassDescription methodsFor: 'accessing'!
  10166. classVersion
  10167.     "Default.  Any class may return a later version to inform readers that use ReferenceStream.  8/17/96 tk"
  10168.     ^ 0!
  10169. comment
  10170.     "Answer the receiver's comment."
  10171.  
  10172.     | aString |
  10173.     aString _ self organization classComment.
  10174.     aString size = 0 ifTrue: [^''].
  10175.     "get string only of classComment, undoubling quotes"
  10176.     ^ String readFromString: aString!
  10177. comment: aString 
  10178.     "Set the receiver's comment to be the argument, aString."
  10179.  
  10180.     | aStream |
  10181.     aString size = 0
  10182.         ifTrue: 
  10183.             [self organization classComment: aString]
  10184.         ifFalse: 
  10185.             ["double internal quotes of the comment string"
  10186.             aStream _ WriteStream on: (String new: aString size).
  10187.             aStream nextPutAll: self name , ' comment:'; cr.
  10188.             aString storeOn: aStream.
  10189.             self organization classComment: aStream contents.
  10190.     Smalltalk changes commentClass: self]!
  10191. commentTemplate
  10192.     "Answer an expression to edit and evaluate in order to produce the 
  10193.     receiver's comment."
  10194.  
  10195.     | aString |
  10196.     aString _ self organization classComment.
  10197.     aString size = 0
  10198.         ifTrue: [ ^ self name , ' comment:
  10199. ''This class has not yet been commented''']
  10200.         ifFalse: [ ^ aString]!
  10201. isMeta
  10202.     ^ false!
  10203. name
  10204.     "Answer a String that is the name of the receiver."
  10205.  
  10206.     self subclassResponsibility!
  10207. theNonMetaClass
  10208.     "Sent to a class or metaclass, always return the class"
  10209.  
  10210.     ^self! !
  10211.  
  10212. !ClassDescription methodsFor: 'copying'!
  10213. copy: sel from: class 
  10214.     "Install the method associated with the first argument, sel, a message 
  10215.     selector, found in the method dictionary of the second argument, class, 
  10216.     as one of the receiver's methods. Classify the message under -As yet not 
  10217.     classified-."
  10218.  
  10219.     self copy: sel
  10220.         from: class
  10221.         classified: nil!
  10222. copy: sel from: class classified: cat 
  10223.     "Install the method associated with the first arugment, sel, a message 
  10224.     selector, found in the method dictionary of the second argument, class, 
  10225.     as one of the receiver's methods. Classify the message under the third 
  10226.     argument, cat."
  10227.  
  10228.     | code category |
  10229.     "Useful when modifying an existing class"
  10230.     code _ class sourceMethodAt: sel.
  10231.     code == nil
  10232.         ifFalse: 
  10233.             [cat == nil
  10234.                 ifTrue: [category _ class organization categoryOfElement: sel]
  10235.                 ifFalse: [category _ cat].
  10236.             (methodDict includesKey: sel)
  10237.                 ifTrue: [code asString = (self sourceMethodAt: sel) asString 
  10238.                             ifFalse: [self error: self name 
  10239.                                         , ' ' 
  10240.                                         , sel 
  10241.                                         , ' will be redefined if you proceed.']].
  10242.             self compile: code classified: category]!
  10243. copyAll: selArray from: class 
  10244.     "Install all the methods found in the method dictionary of the second 
  10245.     argument, class, as the receiver's methods. Classify the messages under 
  10246.     -As yet not classified-."
  10247.  
  10248.     self copyAll: selArray
  10249.         from: class
  10250.         classified: nil!
  10251. copyAll: selArray from: class classified: cat 
  10252.     "Install all the methods found in the method dictionary of the second 
  10253.     argument, class, as the receiver's methods. Classify the messages under 
  10254.     the third argument, cat."
  10255.  
  10256.     selArray do: 
  10257.         [:s | self copy: s
  10258.                 from: class
  10259.                 classified: cat]!
  10260. copyAllCategoriesFrom: aClass 
  10261.     "Specify that the categories of messages for the receiver include all of 
  10262.     those found in the class, aClass. Install each of the messages found in 
  10263.     these categories into the method dictionary of the receiver, classified 
  10264.     under the appropriate categories."
  10265.  
  10266.     aClass organization categories do: [:cat | self copyCategory: cat from: aClass]!
  10267. copyCategory: cat from: class 
  10268.     "Specify that one of the categories of messages for the receiver is cat, as 
  10269.     found in the class, class. Copy each message found in this category."
  10270.  
  10271.     self copyCategory: cat
  10272.         from: class
  10273.         classified: cat!
  10274. copyCategory: cat from: aClass classified: newCat 
  10275.     "Specify that one of the categories of messages for the receiver is the 
  10276.     third argument, newCat. Copy each message found in the category cat in 
  10277.     class aClass into this new category."
  10278.  
  10279.     self copyAll: (aClass organization listAtCategoryNamed: cat)
  10280.         from: aClass
  10281.         classified: newCat! !
  10282.  
  10283. !ClassDescription methodsFor: 'printing'!
  10284. classVariablesString
  10285.     "Answer a string of my class variable names separated by spaces."
  10286.  
  10287.     | aStream |
  10288.     aStream _ WriteStream on: (String new: 100).
  10289.     self classPool keysDo: [:key | aStream nextPutAll: key; space].
  10290.     ^aStream contents!
  10291. instanceVariablesString
  10292.     "Answer a string of my instance variable names separated by spaces."
  10293.  
  10294.     | aStream names |
  10295.     aStream _ WriteStream on: (String new: 100).
  10296.     names _ self instVarNames.
  10297.     1 to: names size do: [:i | aStream nextPutAll: (names at: i); space].
  10298.     ^aStream contents!
  10299. printOn: aStream 
  10300.  
  10301.     aStream nextPutAll: self name!
  10302. sharedPoolsString
  10303.     "Answer a string of my shared pool names separated by spaces."
  10304.  
  10305.     | aStream |
  10306.     aStream _ WriteStream on: (String new: 100).
  10307.     self sharedPools do: [:x | aStream nextPutAll: (Smalltalk keyAtValue: x); space].
  10308.     ^aStream contents!
  10309. storeOn: aStream
  10310.     "Classes and Metaclasses have global names."
  10311.  
  10312.     aStream nextPutAll: self name! !
  10313.  
  10314. !ClassDescription methodsFor: 'instance variables'!
  10315. addInstVarName: aString 
  10316.     "Add the argument, aString, as one of the receiver's instance variables."
  10317.  
  10318.     self subclassResponsibility!
  10319. browseClassVariables
  10320.     "Put up a browser showing the receiver's class variables.  2/1/96 sw"
  10321.  
  10322.     self classPool inspectWithLabel: 'Class Variables in ', self name!
  10323. browseClassVarRefs 
  10324.     "1/17/96 sw: moved here from Browser so that it could be used from a variety of places."
  10325.  
  10326.     | lines labelStream vars allVars index owningClasses |
  10327.  
  10328.     lines _ OrderedCollection new.
  10329.     allVars _ OrderedCollection new.
  10330.     owningClasses _ OrderedCollection new.
  10331.     labelStream _ WriteStream on: (String new: 200).
  10332.     self withAllSuperclasses reverseDo:
  10333.         [:class |
  10334.         vars _ class classVarNames asSortedCollection.
  10335.         vars do:
  10336.             [:var |
  10337.             labelStream nextPutAll: var; cr.
  10338.             allVars add: var.
  10339.             owningClasses add: class].
  10340.         vars isEmpty ifFalse: [lines add: allVars size]].
  10341.     labelStream skip: -1 "cut last CR".
  10342.     index _ (PopUpMenu labels: labelStream contents lines: lines) startUp.
  10343.     index = 0 ifTrue: [^ self].
  10344.     Smalltalk browseAllCallsOn:
  10345.         ((owningClasses at: index) classPool associationAt: (allVars at: index))!
  10346. browseInstVarDefs 
  10347.     "Copied from browseInstVarRefs.  Should be consolidated some day. 7/29/96 di
  10348.     7/30/96 sw: did the consolidation"
  10349.  
  10350.     self chooseInstVarThenDo:    
  10351.         [:aVar | self browseAllStoresInto: aVar]!
  10352. browseInstVarRefs 
  10353.     "1/16/96 sw: moved here from Browser so that it could be used from a variety of places.
  10354.      7/30/96 sw: call chooseInstVarThenDo: to get the inst var choice"
  10355.  
  10356.     self chooseInstVarThenDo: 
  10357.         [:aVar | self browseAllAccessesTo: aVar]!
  10358. chooseInstVarThenDo: aBlock 
  10359.     "Put up a menu of all the instance variables in the receiver, and when the user chooses one, evaluate aBlock with the chosen variable as its parameter.  7/30/96 sw"
  10360.  
  10361.     | lines labelStream vars allVars index |
  10362.  
  10363.     lines _ OrderedCollection new.
  10364.     allVars _ OrderedCollection new.
  10365.     labelStream _ WriteStream on: (String new: 200).
  10366.     self withAllSuperclasses reverseDo:
  10367.         [:class |
  10368.         vars _ class instVarNames.
  10369.         vars do:
  10370.             [:var |
  10371.             labelStream nextPutAll: var; cr.
  10372.             allVars add: var].
  10373.         vars isEmpty ifFalse: [lines add: allVars size]].
  10374.     labelStream isEmpty ifTrue:
  10375.         [^ (PopUpMenu labels: ' OK ')
  10376.             startUpWithCaption: 'There are no
  10377. instance variables.'].
  10378.     labelStream skip: -1 "cut last CR".
  10379.     index _ (PopUpMenu labels: labelStream contents lines: lines) startUp.
  10380.     index = 0 ifTrue: [^ self].
  10381.     aBlock value: (allVars at: index)!
  10382. forceNewFrom: anArray
  10383.     "Create a new instance of the class and fill
  10384.     its instance variables up with the array."
  10385.     | object max |
  10386.  
  10387.     object _ self new.
  10388.     max _ self instSize.
  10389.     anArray doWithIndex: [:each :index |
  10390.         index > max ifFalse:
  10391.             [object instVarAt: index put: each]].
  10392.     ^ object!
  10393. instVarNames
  10394.     "Answer an Array of the receiver's instance variable names."
  10395.  
  10396.     instanceVariables == nil
  10397.         ifTrue: [^#()]
  10398.         ifFalse: [^instanceVariables]!
  10399. removeInstVarName: aString 
  10400.     "Remove the argument, aString, as one of the receiver's instance 
  10401.     variables. Create an error notification if the argument is not found."
  10402.  
  10403.     self subclassResponsibility! !
  10404.  
  10405. !ClassDescription methodsFor: 'method dictionary'!
  10406. removeCategory: aString 
  10407.     "Remove each of the messages categorized under aString in the method 
  10408.     dictionary of the receiver. Then remove the category aString."
  10409.     | categoryName |
  10410.     categoryName _ aString asSymbol.
  10411.     (self organization listAtCategoryNamed: categoryName) do:
  10412.         [:sel | self removeSelector: sel].
  10413.     self organization removeCategory: categoryName!
  10414. removeSelector: aSymbol 
  10415.     "Remove the message whose selector is aSymbol from the method 
  10416.     dictionary of the receiver, if it is there. Answer nil otherwise."
  10417.  
  10418.     (methodDict includesKey: aSymbol) ifFalse: [^nil].
  10419.     super removeSelector: aSymbol.
  10420.     self organization removeElement: aSymbol.
  10421.     Smalltalk changes removeSelector: aSymbol class: self.
  10422.     self acceptsLoggingOfCompilation ifTrue:
  10423.         [Smalltalk logChange: self name , ' removeSelector: #' , aSymbol]! !
  10424.  
  10425. !ClassDescription methodsFor: 'organization'!
  10426. category
  10427.     "Answer the system organization category for the receiver."
  10428.  
  10429.     ^SystemOrganization categoryOfElement: self name!
  10430. category: cat 
  10431.     "Categorize the receiver under the system category, cat, removing it from 
  10432.     any previous categorization."
  10433.  
  10434.     (cat isKindOf: String)
  10435.         ifTrue: [SystemOrganization classify: self name under: cat asSymbol]
  10436.         ifFalse: [self errorCategoryName]!
  10437. organization
  10438.     "Answer the instance of ClassOrganizer that represents the organization 
  10439.     of the messages of the receiver."
  10440.  
  10441.     organization==nil
  10442.         ifTrue: [organization _ 
  10443.                  ClassOrganizer defaultList: 
  10444.                         methodDict keys asSortedCollection asArray].
  10445.     ^organization!
  10446. whichCategoryIncludesSelector: aSelector 
  10447.     "Answer the category of the argument, aSelector, in the organization of 
  10448.     the receiver, or answer nil if the receiver does not inlcude this selector."
  10449.  
  10450.     (self includesSelector: aSelector)
  10451.         ifTrue: [^organization categoryOfElement: aSelector]
  10452.         ifFalse: [^nil]! !
  10453.  
  10454. !ClassDescription methodsFor: 'compiling'!
  10455. acceptsLoggingOfCompilation
  10456.     "weird name is so that it will come lexically before #compile, so that a clean build can make it through.  7/7/96 sw"
  10457.  
  10458.     ^ true!
  10459. checkForPerform: selector in: aController
  10460.     "If this newly accepted method contains a perform:, remind the user to put in fake code with the selectors the perform would use.  So senders of those selectors will find this code.  tck 1991
  10461.     1/22/96 sw: MacPal -> Utilities
  10462.     1/24/96 sw: temporarily, at least, bypassed this guy"
  10463.  
  10464.     | meth hasPerform |
  10465.     self flag: #noteToDan.
  10466.     "Ted put this into our image back in 1991, in an effort to force uses who insist on using #perform to put some fake source into their code so that all the selectors likely to be invoked by the perform will be retrieved when one queries senders.  While agreeing this a promising approach, in practice I found it quite a nuisance and also the found the implementation somewhat flawed, so for the moment (more for my personal convenience than as any kind of formal statement) I've commented it out...  2/5/96 sw"
  10467.  
  10468.     "My approach to this would be to disallow all uses of perform:, and replace them with
  10469.     obj perform: selector from: #(list of selectors).
  10470. This provides in-code documenstation, leverage for senders and inplementersOf.  It gives type inference the clue it needs as well, not to mention the possibility of run-time checks on perform: 4/22/96 di"
  10471.  
  10472.     true ifTrue: [^ ''].
  10473.  
  10474.     selector == nil ifTrue: [^ ''].
  10475.     meth _ self compiledMethodAt: selector.
  10476.     hasPerform _ false.
  10477.     #(perform: perform:with: perform:with:with: perform:with:with:with: perform:withArguments:) do: [:each |
  10478.         (meth pointsTo: "faster than hasLiteral:" each) ifTrue: [
  10479.             hasPerform _ true]].
  10480.     hasPerform ifFalse: [^ self].        "normal case, no perform: here"
  10481.     (meth pointsTo: #doNotListPerformSelectors) ifTrue: [^ ''].
  10482.     Sensor leftShiftDown ifTrue: [^ ''].  
  10483.         "When need to accept a method that has many selectors performed
  10484.         and needs to be fast so don't want to include doNotListPerformSelectors."
  10485.  
  10486.     self inform: 
  10487. 'This method contains a perform:.
  10488. Please list all selectors that will 
  10489. be performed in the Selectors 
  10490. Performed section of this method.'.
  10491.  
  10492.     (meth pointsTo: #listPerformSelectorsHere) ifFalse: [
  10493.         "insert section in the method"
  10494.         ^ '.
  10495.  
  10496.     false ifTrue: ["Selectors Performed"
  10497.         "Please list all selectors that could be args to the 
  10498.         perform: in this method.  Do this so senders will find
  10499.         this method as one of the places the selector is sent from."
  10500.         "Use a temp with the class name as the reciever, like this:
  10501.         aBrowser accept."
  10502.         self listPerformSelectorsHere.        "tells the parser its here"
  10503.         ].']!
  10504. compile: code classified: heading 
  10505.     "Compile the argument, code, as source code in the context of the 
  10506.     receiver and install the result in the receiver's method dictionary under 
  10507.     the classification indicated by the second argument, heading. nil is to be 
  10508.     notified if an error occurs. The argument code is either a string or an 
  10509.     object that converts to a string or a PositionableStream on an object that 
  10510.     converts to a string."
  10511.  
  10512.     ^self
  10513.         compile: code
  10514.         classified: heading
  10515.         notifying: (SyntaxError new category: heading)!
  10516. compile: text classified: category notifying: requestor 
  10517.     | selector dict priorMethod method |
  10518.     method _ self
  10519.         compile: text asString
  10520.         notifying: requestor
  10521.         trailer: #(0 0 0 )
  10522.         ifFail: [^nil]
  10523.         elseSetSelectorAndNode: 
  10524.             [:sel :node | selector _ sel.
  10525.             priorMethod _ methodDict at: selector ifAbsent: [nil]].
  10526.     (SourceFiles isNil or: [(SourceFiles at: 2) == nil])
  10527.         ifFalse: [self acceptsLoggingOfCompilation
  10528.                     ifTrue:
  10529.                         [method
  10530.                         putSource: text asString
  10531.                         class: self category: category
  10532.                         inFile: 2 priorMethod: priorMethod]].
  10533.     self organization classify: selector under: category.
  10534.     ^selector!
  10535. compile: code notifying: requestor 
  10536.     "Refer to the comment in Behavior|compile:notifying:." 
  10537.  
  10538.     ^self compile: code
  10539.          classified: ClassOrganizer default
  10540.          notifying: requestor!
  10541. compile: code notifying: requestor trailer: bytes ifFail: failBlock
  10542.     "For backward compatibility."
  10543.     | selector |
  10544.     self compile: code notifying: requestor trailer: bytes
  10545.         ifFail: failBlock
  10546.         elseSetSelectorAndNode: [:sel :node | selector _ sel].
  10547.     ^ selector!
  10548. compile: code notifying: requestor trailer: bytes
  10549.         ifFail: failBlock
  10550.         elseSetSelectorAndNode: selAndNodeBlock
  10551.     "Intercept this message in order to remember system changes.
  10552.      5/15/96 sw: modified so that if the class does not wish its methods logged in the changes file, then they also won't be accumulated in the current change set.
  10553.     7/12/96 sw: use wantsChangeSetLogging to determine whether to put in change set"
  10554.  
  10555.     | methodNode selector method |
  10556.     methodNode _ self compilerClass new
  10557.                 compile: code
  10558.                 in: self
  10559.                 notifying: requestor
  10560.                 ifFail: failBlock.
  10561.     selector _ methodNode selector.
  10562.     selAndNodeBlock value: selector value: methodNode.
  10563.     self wantsChangeSetLogging ifTrue:
  10564.         [(methodDict includesKey: selector)
  10565.             ifTrue: [Smalltalk changes changeSelector: selector class: self]
  10566.             ifFalse: [Smalltalk changes addSelector: selector class: self]].
  10567.     methodNode encoder requestor: requestor.  "Why was this not preserved?"
  10568.     method _ methodNode generate: bytes.
  10569.     self addSelector: selector withMethod: method.
  10570.     ^ method!
  10571. wantsChangeSetLogging
  10572.     "Answer whether code submitted for the receiver should be remembered by the changeSet mechanism.  7/12/96 sw"
  10573.  
  10574.  
  10575.     ^ true! !
  10576.  
  10577. !ClassDescription methodsFor: 'fileIn/Out'!
  10578. definition
  10579.     "Answer a String that defines the receiver."
  10580.  
  10581.     | aStream |
  10582.     aStream _ WriteStream on: (String new: 300).
  10583.     aStream nextPutAll: 
  10584.         (superclass == nil
  10585.             ifTrue: ['nil']
  10586.             ifFalse: [superclass name])
  10587.         , self kindOfSubclass.
  10588.     self name storeOn: aStream.
  10589.     aStream cr; tab; nextPutAll: 'instanceVariableNames: '.
  10590.     aStream store: self instanceVariablesString.
  10591.     aStream cr; tab; nextPutAll: 'classVariableNames: '.
  10592.     aStream store: self classVariablesString.
  10593.     aStream cr; tab; nextPutAll: 'poolDictionaries: '.
  10594.     aStream store: self sharedPoolsString.
  10595.     aStream cr; tab; nextPutAll: 'category: '.
  10596.     (SystemOrganization categoryOfElement: self name) asString storeOn: aStream.
  10597.     ^aStream contents!
  10598. fileOutCategory: aString 
  10599.     "Create a file whose name is the name of the receiver with -.st- as the 
  10600.     extension, and file a description of the receiver's category aString onto it."
  10601.  
  10602.     | fileName fileStream |
  10603.     fileName _ (self name , '-' , aString , '.st') asFileName.
  10604.     fileStream _ FileStream newFileNamed: fileName.
  10605.     fileStream header; timeStamp.
  10606.     self fileOutCategory: aString
  10607.         on: fileStream
  10608.         moveSource: false
  10609.         toFile: 0.
  10610.     fileStream trailer; close!
  10611. fileOutCategory: aString on: aFileStream moveSource: moveSource toFile: fileIndex 
  10612.     "File a description of the receiver's category, aString, onto aFileStream. If 
  10613.     the boolean argument, moveSource, is true, then set the trailing bytes to 
  10614.     the position of aFileStream and to fileIndex in order to indicate where to 
  10615.     find the source code."
  10616.  
  10617.     aFileStream cr.
  10618.     self printCategoryChunk: aString on: aFileStream.
  10619.     (self organization listAtCategoryNamed: aString)
  10620.         do: [:sel | self
  10621.                 printMethodChunk: sel
  10622.                 on: aFileStream
  10623.                 moveSource: moveSource
  10624.                 toFile: fileIndex].
  10625.     aFileStream nextChunkPut: ' '!
  10626. fileOutChangedMessages: aSet on: aFileStream 
  10627.     "File a description of the messages of the receiver that have been 
  10628.     changed (i.e., are entered into the argument, aSet) onto aFileStream."
  10629.  
  10630.     self fileOutChangedMessages: aSet
  10631.         on: aFileStream
  10632.         moveSource: false
  10633.         toFile: 0!
  10634. fileOutChangedMessages: aSet on: aFileStream moveSource: moveSource toFile: fileIndex 
  10635.     "File a description of the messages of the receiver that have been 
  10636.     changed (i.e., are entered into the argument, aSet) onto aFileStream. If 
  10637.     the boolean argument, moveSource, is true, then set the trailing bytes to 
  10638.     the position of aFileStream and to fileIndex in order to indicate where to 
  10639.     find the source code."
  10640.     | org sels |
  10641.     (org _ self organization) categories do: 
  10642.         [:cat | 
  10643.         sels _ (org listAtCategoryNamed: cat) select: [:sel | aSet includes: sel].
  10644.         sels size > 0
  10645.             ifTrue: 
  10646.                 [self printCategoryChunk: cat on: aFileStream.
  10647.                 sels do: [:sel | 
  10648.                         self printMethodChunk: sel
  10649.                             on: aFileStream
  10650.                             moveSource: moveSource
  10651.                             toFile: fileIndex].
  10652.                 aFileStream nextChunkPut: ' ']]!
  10653. fileOutOn: aFileStream 
  10654.     "File a description of the receiver on aFileStream."
  10655.  
  10656.     self fileOutOn: aFileStream
  10657.         moveSource: false
  10658.         toFile: 0!
  10659. fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex
  10660.     "File a description of the receiver on aFileStream. If the boolean 
  10661.     argument, moveSource, is true, then set the trailing bytes to the position 
  10662.     of aFileStream and to fileIndex in order to indicate where to find the 
  10663.     source code."
  10664.     aFileStream emphasis: 5.
  10665.     aFileStream nextChunkPut: self definition.
  10666.     aFileStream emphasis: 3.
  10667.     self organization
  10668.         putCommentOnFile: aFileStream
  10669.         numbered: fileIndex
  10670.         moveSource: moveSource.
  10671.     self organization categories do: 
  10672.         [:heading |
  10673.         self
  10674.             fileOutCategory: heading
  10675.             on: aFileStream
  10676.             moveSource: moveSource
  10677.             toFile: fileIndex]!
  10678. fileOutOrganizationOn: aFileStream
  10679.     "File a description of the receiver's organization on aFileStream."
  10680.  
  10681.     aFileStream emphasis: 3.
  10682.     aFileStream cr; nextPut: $!!.
  10683.     aFileStream nextChunkPut: self name, ' reorganize'; cr.
  10684.     aFileStream nextChunkPut: self organization printString; cr.
  10685.     aFileStream emphasis: 1!
  10686. kindOfSubclass
  10687.     "Answer a string that describes what kind of subclass the receiver is, i.e.,
  10688.     variable, variable byte, variable word, or not variable."
  10689.  
  10690.     self isVariable
  10691.         ifTrue: [self isBits
  10692.                     ifTrue: [self isBytes
  10693.                                 ifTrue: [^' variableByteSubclass: ']
  10694.                                 ifFalse: [^' variableWordSubclass: ']]
  10695.                     ifFalse: [^' variableSubclass: ']]
  10696.         ifFalse: [^' subclass: ']!
  10697. methods
  10698.     "Answer a ClassCategoryReader for accessing the messages in the method dictionary category, 'as yet unclassified', of the receiver.  Used for filing in fileouts made with Smalltalk/V"
  10699.  
  10700.     ^ClassCategoryReader class: self category: 'imported from V' asSymbol!
  10701. methodsFor: aString 
  10702.     "Answer a ClassCategoryReader for accessing the messages in the method 
  10703.     dictionary category, aString, of the receiver."
  10704.  
  10705.     ^ClassCategoryReader class: self category: aString asSymbol
  10706.  
  10707.     "False methodsFor: 'logical operations' inspect"!
  10708. methodsFor: aString priorSource: sourcePosition inFile: fileIndex
  10709.     "Prior source pointer ignored when filing in."
  10710.     ^ self methodsFor: aString!
  10711. moveChangesTo: newFile 
  10712.     "Used in the process of condensing changes, this message requests that 
  10713.     the source code of all methods of the receiver that have been changed 
  10714.     should be moved to newFile."
  10715.  
  10716.     | changes |
  10717.     self organization moveChangedCommentToFile: newFile numbered: 2.
  10718.     changes _ methodDict keys select: [:sel | (methodDict at: sel) fileIndex > 1].
  10719.     self fileOutChangedMessages: changes
  10720.         on: newFile
  10721.         moveSource: true
  10722.         toFile: 2!
  10723. printCategoryChunk: aString on: aFileStream
  10724.     "Print the message describing that methods for the category aString follow 
  10725.     next on aFileStream."
  10726.  
  10727.     aFileStream command: 'H3'.
  10728.     aFileStream cr; nextPut: $!!.
  10729.     aFileStream nextChunkPut: (self name , ' methodsFor: ''' , aString , '''').
  10730.     aFileStream command: '/H3'.
  10731. !
  10732. printCategoryChunk: category on: aFileStream priorMethod: priorMethod
  10733.     "Print the message indicating that methods for the category follow 
  10734.     next on aFileStream.  If priorMethod is not nil, the message also
  10735.     indicates where to find the prior source code"
  10736.  
  10737.     aFileStream cr; command: 'H3'; nextPut: $!!.
  10738.     aFileStream nextChunkPut: (String streamContents:
  10739.         [:strm |
  10740.         strm nextPutAll: self name;
  10741.             nextPutAll: ' methodsFor: ';
  10742.             print: category asString.
  10743.         priorMethod notNil ifTrue:
  10744.             [strm nextPutAll: ' priorSource: ';
  10745.                 print: priorMethod filePosition;
  10746.                 nextPutAll: ' inFile: ';
  10747.                 print: priorMethod fileIndex]]).
  10748.     aFileStream command: '/H3'.!
  10749. printMethodChunk: aSelector on: aFileStream moveSource: moveSource toFile: fileIndex
  10750.     "Print the source for the method of aSelector on aFileSteam, and move 
  10751.     the source to the source file specified by fileIndex if moveSource is true."
  10752.     | position method fastStream |
  10753.     aFileStream cr.
  10754.     moveSource ifTrue: [position _ aFileStream position].
  10755.     method _ self compiledMethodAt: aSelector.
  10756.     self copySourceCodeAt: aSelector to: aFileStream.
  10757.     moveSource ifTrue: [method setSourcePosition: position inFile: fileIndex]!
  10758. reformatAll 
  10759.     "Reformat all methods in this class.
  10760.     Leaves old code accessible to version browsing"
  10761.     self selectorsDo: [:sel | self reformatMethodAt: sel]!
  10762. reformatMethodAt: selector 
  10763.     | newCodeString method |
  10764.     newCodeString _ (self compilerClass new)
  10765.         format: (self sourceCodeAt: selector)
  10766.         in: self
  10767.         notifying: nil.
  10768.     method _ self compiledMethodAt: selector.
  10769.     method
  10770.         putSource: newCodeString
  10771.         class: self
  10772.         category: (self organization categoryOfElement: selector)
  10773.         inFile: 2 priorMethod: method!
  10774. reorganize
  10775.     "Record that the receiver is being reorganized and answer the receiver's organization."
  10776.  
  10777.     Smalltalk changes reorganizeClass: self.
  10778.     ^self organization! !
  10779.  
  10780. !ClassDescription methodsFor: 'private'!
  10781. errorCategoryName
  10782.     self error: 'Category name must be a String'!
  10783. space
  10784.     "Answer a rough estimate of number of objects in this class and its metaclass"
  10785.     | objs words method metaSpace |
  10786.     objs _ words _ 0.
  10787.     self selectorsDo:
  10788.         [:sel | objs_ objs+1.
  10789.         method _ self compiledMethodAt: sel.
  10790.         words _ words + (method size+1//2) + 2 + 4 "dict and org'n space".
  10791.         method literals do:
  10792.             [:lit | (lit isMemberOf: String) ifTrue:
  10793.                 [words _ words+2+(lit size+1//2).
  10794.                 objs _ objs+1]]].
  10795.     (self isMemberOf: Metaclass) ifFalse:
  10796.         [metaSpace _ self class space.
  10797.         objs _ objs + metaSpace first.
  10798.         words _ words + metaSpace last].
  10799.     ^ Array with: objs with: words! !BrowserListController subclass: #ClassListController
  10800.     instanceVariableNames: ''
  10801.     classVariableNames: 'ClassListYellowButtonMenu ClassListYellowButtonMessages '
  10802.     poolDictionaries: ''
  10803.     category: 'Interface-Browser'!
  10804. ClassListController comment:
  10805. 'I am a kind of LockedListController that creates a yellow button menu so that messages can be sent to the list selection (a Class) to:
  10806.     browse    create a class browser
  10807.     categories    print the message categories
  10808.     comment    print a comment describing the purpose of the class
  10809.     definition    print the expression that defines the class
  10810.     fileOut    print a description of the class on an external file
  10811.     hierarchy    print a description of the superclass hierarchy
  10812.     remove    expunge the class from the system'!
  10813.  
  10814. !ClassListController methodsFor: 'initialize-release'!
  10815. initialize
  10816.  
  10817.     super initialize.
  10818.     self initializeYellowButtonMenu! !
  10819.  
  10820. !ClassListController methodsFor: 'menu messages'!
  10821. browse
  10822.     "Create and schedule a class browser on the selected class."
  10823.  
  10824.     self controlTerminate.
  10825.     model buildClassBrowser.
  10826.     self controlInitialize!
  10827. browseClassRefs
  10828.     "Request a browser of references to the current class."
  10829.  
  10830.     self controlTerminate.
  10831.     model browseClassRefs.
  10832.     self controlInitialize!
  10833. browseClassVarRefs
  10834.     "Request a browser of references to a chosen class variable."
  10835.  
  10836.     self controlTerminate.
  10837.     model browseClassVarRefs.
  10838.     self controlInitialize!
  10839. browseInstVarDefs
  10840.     "Request a browser of methods that access a chosen instance variable."
  10841.  
  10842.     self controlTerminate.
  10843.     model browseInstVarDefs.
  10844.     self controlInitialize!
  10845. browseInstVarRefs
  10846.     "Request a browser of methods that access a chosen instance variable."
  10847.  
  10848.     self controlTerminate.
  10849.     model browseInstVarRefs.
  10850.     self controlInitialize!
  10851. classVariables
  10852.     "Request a dictionary inspector on the chosen class's clas variables.  2/5/96 sw."
  10853.  
  10854.     self controlTerminate.
  10855.     model browseClassVariables.
  10856.     self controlInitialize!
  10857. comment
  10858.     "Request that the receiver's view display the comment of the selected 
  10859.     class so that it can be edited."
  10860.  
  10861.     self controlTerminate.
  10862.     model editComment.
  10863.     self controlInitialize!
  10864. definition
  10865.     "Request that the receiver's view display the definition of the selected 
  10866.     class so that it can be edited."
  10867.  
  10868.     self controlTerminate.
  10869.     model editClass.
  10870.     self controlInitialize!
  10871. fileOut
  10872.     "Print a description of the selected class onto an external file."
  10873.  
  10874.     self controlTerminate.
  10875.     Cursor write showWhile:
  10876.         [model fileOutClass].
  10877.     self controlInitialize!
  10878. findMethod
  10879.     "Pop up a list of the current class's methods, and select the one chosen by the user.
  10880.     5/21/96 sw, based on a suggestion of John Maloney's."
  10881.  
  10882.     | aClass selectors reply cat messageCategoryListIndex messageListIndex |
  10883.     self controlTerminate.
  10884.  
  10885.     model classListIndex = 0 ifTrue: [^ self].
  10886.     model okToChange ifFalse: [^ self].
  10887.     aClass _ model selectedClassOrMetaClass.
  10888.     selectors _ aClass selectors asSortedArray.
  10889.     reply _ (SelectionMenu labelList: selectors selections: selectors) startUp.
  10890.     reply == nil ifTrue: [^ self].
  10891.     cat _ aClass whichCategoryIncludesSelector: reply.
  10892.     messageCategoryListIndex _ model messageCategoryList indexOf: cat.
  10893.     model messageCategoryListIndex: messageCategoryListIndex.
  10894.     messageListIndex _ (model messageList indexOf: reply).
  10895.     model messageListIndex: messageListIndex.
  10896.     self controlInitialize.
  10897. !
  10898. hierarchy
  10899.     "Request that the receiver's view display the class hierarchy (super- and 
  10900.     subclasses) of the selected class so that it can be edited."
  10901.  
  10902.     self controlTerminate.
  10903.     model hierarchy.
  10904.     self controlInitialize!
  10905. printOut
  10906.     "Make a file with the description of the selected mesage category.
  10907.     Defaults to the same file as fileOut, but could be changed in any given
  10908.     implementation to have a prettier format."
  10909.  
  10910.     self fileOut!
  10911. remove
  10912.     "Remove the selected class from the system. A Confirmer is created."
  10913.  
  10914.     self controlTerminate.
  10915.     model removeClass.
  10916.     self controlInitialize!
  10917. rename
  10918.     "Request to rename the currently selected class."
  10919.     self controlTerminate.
  10920.     model renameClass.
  10921.     self controlInitialize! !
  10922.  
  10923. !ClassListController methodsFor: 'private'!
  10924. changeModelSelection: anInteger
  10925.     model toggleClassListIndex: anInteger!
  10926. initializeYellowButtonMenu
  10927.  
  10928.     self yellowButtonMenu: ClassListYellowButtonMenu 
  10929.         yellowButtonMessages: ClassListYellowButtonMessages! !
  10930. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  10931.  
  10932. ClassListController class
  10933.     instanceVariableNames: ''!
  10934.  
  10935. !ClassListController class methodsFor: 'class initialization'!
  10936. initialize
  10937.     "Initialize the yellow button menu information.
  10938.      2/1/96 sw: added class vars
  10939.      7/29/96 sw: added 'find method' feature"
  10940.     
  10941.     ClassListYellowButtonMenu _
  10942.         PopUpMenu 
  10943.                 labels: 
  10944. 'browse class
  10945. printOut
  10946. fileOut
  10947. hierarchy
  10948. definition
  10949. comment
  10950. inst var refs..
  10951. class var refs...
  10952. class vars
  10953. class refs
  10954. rename...
  10955. remove
  10956. find method...' 
  10957.                 lines: #(3 6 10 12).
  10958.     ClassListYellowButtonMessages _ 
  10959.         #(browse printOut fileOut
  10960.         hierarchy definition comment
  10961.         browseInstVarRefs browseClassVarRefs classVariables browseClassRefs
  10962.         rename remove findMethod)
  10963.     "
  10964.     ClassListController initialize.
  10965.     ClassListController allInstancesDo:
  10966.         [:x | x initializeYellowButtonMenu].
  10967.     "! !
  10968.  
  10969. ClassListController initialize!
  10970. BrowserListView subclass: #ClassListView
  10971.     instanceVariableNames: ''
  10972.     classVariableNames: ''
  10973.     poolDictionaries: ''
  10974.     category: 'Interface-Browser'!
  10975. ClassListView comment:
  10976. 'I am a BrowserListView whose items are the class names in the Browser I view. ClassListController is my default controller.'!
  10977.  
  10978. !ClassListView methodsFor: 'updating'!
  10979. getList 
  10980.     "Refer to the comment in BrowserListView|getList."
  10981.  
  10982.     | selectedClassName |
  10983.     singleItemMode
  10984.         ifTrue: 
  10985.             [selectedClassName _ model selectedClassName.
  10986.             selectedClassName == nil ifTrue: [selectedClassName _ '    '].
  10987.             ^Array with: selectedClassName asSymbol]
  10988.         ifFalse: [^model classList]!
  10989. update: aSymbol
  10990.  
  10991.     (aSymbol == #systemCategorySelectionChanged) |
  10992.     (aSymbol == #editSystemCategories) |
  10993.     (aSymbol == #classListChanged)
  10994.         ifTrue:  [self updateClassList. ^self].
  10995.     (aSymbol == #classSelectionChanged)
  10996.         ifTrue: [self updateClassSelection. ^self]! !
  10997.  
  10998. !ClassListView methodsFor: 'controller access'!
  10999. defaultControllerClass
  11000.  
  11001.     ^ClassListController! !
  11002.  
  11003. !ClassListView methodsFor: 'private'!
  11004. updateClassList
  11005.  
  11006.     singleItemMode ifFalse: [self getListAndDisplayView] !
  11007. updateClassSelection
  11008.  
  11009.     singleItemMode 
  11010.         ifTrue: [self getListAndDisplayView]
  11011.         ifFalse: [self moveSelectionBox: model classListIndex]! !Object subclass: #ClassOrganizer
  11012.     instanceVariableNames: 'globalComment categoryArray categoryStops elementArray '
  11013.     classVariableNames: 'NullCategory Default '
  11014.     poolDictionaries: ''
  11015.     category: 'Kernel-Support'!
  11016. ClassOrganizer comment:
  11017. 'I represent method categorization information for classes.'!
  11018.  
  11019. !ClassOrganizer methodsFor: 'accessing'!
  11020. categories
  11021.     "Answer an Array of categories (names)."
  11022.     (categoryArray size = 1 
  11023.         and: [categoryArray first = Default & (elementArray size = 0)])
  11024.         ifTrue: [^Array with: NullCategory].
  11025.     ^categoryArray!
  11026. categories: anArray 
  11027.     "Reorder my categories to be in order of the argument, anArray. If the 
  11028.     resulting organization does not include all elements, then give an error."
  11029.  
  11030.     | newCategories newStops newElements catName list runningTotal | 
  11031.     newCategories _ Array new: anArray size.
  11032.     newStops _ Array new: anArray size.
  11033.     newElements _ Array new: 0.
  11034.     runningTotal _ 0.
  11035.     1 to: anArray size do:
  11036.         [:i |
  11037.         catName _ (anArray at: i) asSymbol.
  11038.         list _ self listAtCategoryNamed: catName.
  11039.                 newElements _ newElements, list.
  11040.                 newCategories at: i put: catName.
  11041.                 newStops at: i put: (runningTotal _ runningTotal + list size)].
  11042.     elementArray do:
  11043.         [:element | "check to be sure all elements are included"
  11044.         (newElements includes: element)
  11045.             ifFalse: [^self error: 'New categories must match old ones']].
  11046.     "Everything is good, now update my three arrays."
  11047.     categoryArray _ newCategories.
  11048.     categoryStops _ newStops.
  11049.     elementArray _ newElements!
  11050. categoryOfElement: element 
  11051.     "Answer the category associated with the argument, element."
  11052.  
  11053.     | index |
  11054.     index _ self numberOfCategoryOfElement: element.
  11055.     index = 0
  11056.         ifTrue: [^nil]
  11057.         ifFalse: [^categoryArray at: index]!
  11058. changeFromString: aString 
  11059.     "Parse the argument, aString, and make this be the receiver's structure."
  11060.  
  11061.     | scanner oldElements newElements newCategories newStops currentStop anArray |
  11062.     scanner _ Scanner new scanTokens: aString.
  11063.     "If nothing was scanned and I had no elements before, then default me"
  11064.     (scanner size = 0 and: [elementArray size = 0])
  11065.         ifTrue: [^self setDefaultList: Array new].
  11066.  
  11067.     oldElements _ elementArray asSet.
  11068.     newCategories _ Array new: scanner size.
  11069.     newStops _ Array new: scanner size.
  11070.     currentStop _ 0.
  11071.     newElements _ WriteStream on: (Array new: 16).
  11072.     1 to: scanner size do: 
  11073.         [:i | 
  11074.         anArray _ scanner at: i.
  11075.         newCategories at: i put: anArray first asSymbol.
  11076.         (anArray copyFrom: 2 to: anArray size) asSortedCollection do:
  11077.             [:elem |
  11078.             (oldElements remove: elem ifAbsent: [nil]) notNil ifTrue:
  11079.                 [newElements nextPut: elem.
  11080.                 currentStop _ currentStop+1]].
  11081.         newStops at: i put: currentStop].
  11082.  
  11083.     "Ignore extra elements but don't lose any existing elements!!"
  11084.     oldElements _ oldElements collect:
  11085.         [:elem | Array with: (self categoryOfElement: elem) with: elem].
  11086.     newElements _ newElements contents.
  11087.     categoryArray _ newCategories.
  11088.     categoryStops _ newStops.
  11089.     elementArray _ newElements.
  11090.     oldElements do: [:pair | self classify: pair last under: pair first].!
  11091. listAtCategoryNamed: categoryName
  11092.     "Answer the array of elements associated with the name, categoryName."
  11093.  
  11094.     | i |
  11095.     i _ categoryArray indexOf: categoryName ifAbsent: [^Array new].
  11096.     ^self listAtCategoryNumber: i!
  11097. listAtCategoryNumber: anInteger 
  11098.     "Answer the array of elements stored at the position indexed by 
  11099.     anInteger."
  11100.  
  11101.     | firstIndex lastIndex |
  11102.     firstIndex _ 
  11103.         (anInteger > 1
  11104.             ifTrue: [categoryStops at: anInteger - 1]
  11105.             ifFalse: [0])
  11106.         + 1.
  11107.     lastIndex _ categoryStops at: anInteger.
  11108.     ^elementArray copyFrom: firstIndex to: lastIndex!
  11109. numberOfCategoryOfElement: element 
  11110.     "Answer the index of the category with which the argument, element, is 
  11111.     associated."
  11112.  
  11113.     | categoryIndex elementIndex |
  11114.     categoryIndex _ 1.
  11115.     elementIndex _ 0.
  11116.     [(elementIndex _ elementIndex + 1) <= elementArray size]
  11117.         whileTrue: 
  11118.             ["point to correct category"
  11119.             [elementIndex > (categoryStops at: categoryIndex)]
  11120.                 whileTrue: [categoryIndex _ categoryIndex + 1].
  11121.             "see if this is element"
  11122.             element = (elementArray at: elementIndex) ifTrue: [^categoryIndex]].
  11123.     ^0!
  11124. removeElement: element 
  11125.     "Remove the selector, element, from all categories."
  11126.     | categoryIndex elementIndex nextStop newElements |
  11127.     categoryIndex _ 1.
  11128.     elementIndex _ 0.
  11129.     nextStop _ 0.
  11130.     "nextStop keeps track of the stops in the new element array"
  11131.     newElements _ WriteStream on: (Array new: elementArray size).
  11132.     [(elementIndex _ elementIndex + 1) <= elementArray size]
  11133.         whileTrue: 
  11134.             [[elementIndex > (categoryStops at: categoryIndex)]
  11135.                 whileTrue: 
  11136.                     [categoryStops at: categoryIndex put: nextStop.
  11137.                     categoryIndex _ categoryIndex + 1].
  11138.             (elementArray at: elementIndex) = element
  11139.                 ifFalse: 
  11140.                     [nextStop _ nextStop + 1.
  11141.                     newElements nextPut: (elementArray at: elementIndex)]].
  11142.     [categoryIndex <= categoryStops size]
  11143.         whileTrue: 
  11144.             [categoryStops at: categoryIndex put: nextStop.
  11145.             categoryIndex _ categoryIndex + 1].
  11146.     elementArray _ newElements contents!
  11147. removeEmptyCategories
  11148.     "Remove empty categories."
  11149.  
  11150.     | categoryIndex currentStop keptCategories keptStops |
  11151.     keptCategories _ WriteStream on: (Array new: 16).
  11152.     keptStops _ WriteStream on: (Array new: 16).
  11153.     currentStop _ categoryIndex _ 0.
  11154.     [(categoryIndex _ categoryIndex + 1) <= categoryArray size]
  11155.         whileTrue: 
  11156.             [(categoryStops at: categoryIndex) > currentStop
  11157.                 ifTrue: 
  11158.                     [keptCategories nextPut: (categoryArray at: categoryIndex).
  11159.                     keptStops nextPut: (currentStop _ categoryStops at: categoryIndex)]].
  11160.     categoryArray _ keptCategories contents.
  11161.     categoryStops _ keptStops contents.
  11162.     categoryArray size = 0
  11163.         ifTrue:
  11164.             [categoryArray _ Array with: Default.
  11165.             categoryStops _ Array with: 0]
  11166.  
  11167.     "ClassOrganizer allInstancesDo: [:co | co removeEmptyCategories]."! !
  11168.  
  11169. !ClassOrganizer methodsFor: 'compiler access'!
  11170. classComment
  11171.     "Answer the comment associated with the object that refers to the 
  11172.     receiver."
  11173.  
  11174.     globalComment == nil ifTrue: [^''].
  11175.     ^globalComment string!
  11176. classComment: aString 
  11177.     "Store the comment, aString, associated with the object that refers to the 
  11178.     receiver."
  11179.  
  11180.     aString size = 0
  11181.         ifTrue: [globalComment _ nil]
  11182.         ifFalse: [globalComment _ RemoteString newString: aString onFileNumber: 2]!
  11183. classify: element under: heading 
  11184.     "Store the argument, element, in the category named heading."
  11185.  
  11186.     | catName catIndex elemIndex realHeading |
  11187.     heading = NullCategory
  11188.         ifTrue: [realHeading _ Default]
  11189.         ifFalse: [realHeading _ heading asSymbol].
  11190.     (catName _ self categoryOfElement: element) = realHeading
  11191.         ifTrue: [^self].  "done if already under that category"
  11192.  
  11193.     catName ~~ nil ifTrue: 
  11194.         [realHeading = Default
  11195.             ifTrue: [^self].    "return if exists and realHeading is default"
  11196.         self removeElement: element].    "remove if in another category"
  11197.  
  11198.     (categoryArray indexOf: realHeading) = 0 ifTrue: [self addCategory: realHeading].
  11199.     "add realHeading if not there already"
  11200.  
  11201.     catIndex _ categoryArray indexOf: realHeading.
  11202.     elemIndex _ 
  11203.         catIndex > 1
  11204.             ifTrue: [categoryStops at: catIndex - 1]
  11205.             ifFalse: [0].
  11206.     [(elemIndex _ elemIndex + 1) <= (categoryStops at: catIndex) 
  11207.         and: [element >= (elementArray at: elemIndex)]] whileTrue.
  11208.  
  11209.     "elemIndex is now the index for inserting the element. Do the insertion before it."
  11210.     elementArray _ 
  11211.         (elementArray copyFrom: 1 to: elemIndex - 1)
  11212.             , (Array with: element) 
  11213.             , (elementArray copyFrom: elemIndex to: elementArray size).    "insertion"
  11214.  
  11215.     "add one to stops for this and later categories"
  11216.     catIndex to: categoryArray size do: 
  11217.         [:i | categoryStops at: i put: (categoryStops at: i) + 1].
  11218.     (self listAtCategoryNamed: Default) size = 0 ifTrue: [self removeCategory: Default]!
  11219. classifyAll: aCollection under: heading
  11220.  
  11221.     aCollection do:
  11222.         [:element | self classify: element under: heading]!
  11223. hasNoComment
  11224.     "Answer whether the class classified by the receiver has a comment."
  11225.  
  11226.     ^globalComment == nil!
  11227. moveChangedCommentToFile: aFileStream numbered: sourceIndex 
  11228.     "This is part of source code compression. Move the comment about the 
  11229.     class classified by the receiver from the file referenced by sourceIndex 
  11230.     and to the stream, aFileStream."
  11231.  
  11232.     (globalComment ~~ nil and: [globalComment sourceFileNumber > 1])
  11233.         ifTrue: 
  11234.             [aFileStream cr; cr.
  11235.             globalComment _ 
  11236.                 RemoteString
  11237.                     newString: globalComment string
  11238.                     onFileNumber: sourceIndex
  11239.                     toFile: aFileStream]!
  11240. putCommentOnFile: aFileStream numbered: sourceIndex moveSource: moveSource 
  11241.     "Store the comment about the class onto file, aFileStream."
  11242.  
  11243.     | newRemoteString |
  11244.     globalComment ~~ nil
  11245.         ifTrue: 
  11246.             [aFileStream cr.
  11247.             newRemoteString _ 
  11248.                 RemoteString
  11249.                         newString: globalComment string
  11250.                         onFileNumber: sourceIndex
  11251.                         toFile: aFileStream.
  11252.             moveSource ifTrue: [globalComment _ newRemoteString]]! !
  11253.  
  11254. !ClassOrganizer methodsFor: 'method dictionary'!
  11255. addCategory: newCategory
  11256.     ^ self addCategory: newCategory before: nil !
  11257. addCategory: catString before: nextCategory
  11258.     "Add a new category named heading.
  11259.     If default category exists and is empty, remove it.
  11260.     If nextCategory is nil, then add the new one at the end,
  11261.     otherwise, insert it before nextCategory."
  11262.     | index newCategory |
  11263.     newCategory _ catString asSymbol.
  11264.     (categoryArray indexOf: newCategory) > 0
  11265.         ifTrue: [^self].    "heading already exists, so done"
  11266.     index _ categoryArray indexOf: nextCategory
  11267.         ifAbsent: [categoryArray size + 1].
  11268.     categoryArray _ categoryArray
  11269.         copyReplaceFrom: index
  11270.         to: index-1
  11271.         with: (Array with: newCategory).
  11272.     categoryStops _ categoryStops
  11273.         copyReplaceFrom: index
  11274.         to: index-1
  11275.         with: (Array with: (index = 1
  11276.                 ifTrue: [0]
  11277.                 ifFalse: [categoryStops at: index-1])).
  11278.     "remove empty default category"
  11279.     (self listAtCategoryNamed: Default) size = 0
  11280.         ifTrue: [self removeCategory: Default]!
  11281. removeCategory: cat 
  11282.     "Remove the category named, cat. Create an error notificiation if the 
  11283.     category has any elements in it."
  11284.  
  11285.     | index lastStop |
  11286.     index _ categoryArray indexOf: cat ifAbsent: [^self].
  11287.     lastStop _ 
  11288.         index = 1
  11289.             ifTrue: [0]
  11290.             ifFalse: [categoryStops at: index - 1].
  11291.     (categoryStops at: index) - lastStop > 0 
  11292.         ifTrue: [^self error: 'cannot remove non-empty category'].
  11293.     categoryArray _ 
  11294.         (categoryArray copyFrom: 1 to: index - 1)
  11295.             , (categoryArray copyFrom: index + 1 to: categoryArray size).
  11296.     categoryStops _ 
  11297.         (categoryStops copyFrom: 1 to: index - 1)
  11298.             , (categoryStops copyFrom: index + 1 to: categoryStops size).
  11299.     categoryArray size = 0
  11300.         ifTrue:
  11301.             [categoryArray _ Array with: Default.
  11302.             categoryStops _ Array with: 0]
  11303. !
  11304. renameCategory: oldCatString toBe: newCatString
  11305.     "Rename a category. No action if new name already exists,
  11306.     or if old name does not exist."
  11307.     | index oldCategory newCategory |
  11308.     oldCategory _ oldCatString asSymbol.
  11309.     newCategory _ newCatString asSymbol.
  11310.     (categoryArray indexOf: newCategory) > 0
  11311.         ifTrue: [^self].    "new name exists, so no action"
  11312.     (index _ categoryArray indexOf: oldCategory) = 0
  11313.         ifTrue: [^self].    "old name not found, so no action"
  11314.     categoryArray at: index put: newCategory! !
  11315.  
  11316. !ClassOrganizer methodsFor: 'printing'!
  11317. printOn: aStream 
  11318.     "Refer to the comment in Object|printOn:."
  11319.  
  11320.     | elementIndex lastStop |
  11321.     elementIndex _ 1.
  11322.     lastStop _ 1.
  11323.     1 to: categoryArray size do: 
  11324.         [:i | 
  11325.         aStream nextPut: $(.
  11326.         (categoryArray at: i) asString printOn: aStream.
  11327.         [elementIndex <= (categoryStops at: i)]
  11328.             whileTrue: 
  11329.                 [aStream space.
  11330.                 (elementArray at: elementIndex) printOn: aStream.
  11331.                 elementIndex _ elementIndex + 1].
  11332.         aStream nextPut: $).
  11333.         aStream cr]! !
  11334.  
  11335. !ClassOrganizer methodsFor: 'fileIn/Out'!
  11336. scanFrom: aStream
  11337.     "Reads in the organization from the next chunk on aStream.
  11338.     Categories or elements not found in the definition are not affected.
  11339.     New elements are ignored."
  11340.  
  11341.     self changeFromString: aStream nextChunk! !
  11342.  
  11343. !ClassOrganizer methodsFor: 'private'!
  11344. setDefaultList: aSortedCollection
  11345.  
  11346.     self classComment: ''.
  11347.     categoryArray _ Array with: Default.
  11348.     categoryStops _ Array with: aSortedCollection size.
  11349.     elementArray _ aSortedCollection asArray! !
  11350. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  11351.  
  11352. ClassOrganizer class
  11353.     instanceVariableNames: ''!
  11354.  
  11355. !ClassOrganizer class methodsFor: 'class initialization'!
  11356. default 
  11357.     ^ Default!
  11358. initialize
  11359.     Default _ 'as yet unclassified' asSymbol.
  11360.     NullCategory _ 'no messages' asSymbol.
  11361.     "ClassOrganizer initialize"!
  11362. nullCategory
  11363.     ^ NullCategory! !
  11364.  
  11365. !ClassOrganizer class methodsFor: 'instance creation'!
  11366. defaultList: aSortedCollection 
  11367.     "Answer an instance of me with initial elements from the argument, 
  11368.     aSortedCollection."
  11369.  
  11370.     ^self new setDefaultList: aSortedCollection! !
  11371.  
  11372. !ClassOrganizer class methodsFor: 'documentation'!
  11373. documentation
  11374.     "Instances consist of an Array of category names (categoryArray), each of 
  11375.     which refers to an Array of elements (elementArray). This association is 
  11376.     made through an Array of stop indices (categoryStops), each of which is 
  11377.     the index in elementArray of the last element (if any) of the 
  11378.     corresponding category. For example: categories _ Array with: 'firstCat' 
  11379.     with: 'secondCat' with: 'thirdCat'. stops _ Array with: 1 with: 4 with: 4. 
  11380.     elements _ Array with: #a with: #b with: #c with: #d. This means that 
  11381.     category firstCat has only #a, secondCat has #b, #c, and #d, and 
  11382.     thirdCat has no elements. This means that stops at: stops size must be the 
  11383.     same as elements size." ! !
  11384.  
  11385. ClassOrganizer initialize!
  11386. Model subclass: #CngsClassList
  11387.     instanceVariableNames: 'parent list listIndex controller '
  11388.     classVariableNames: ''
  11389.     poolDictionaries: ''
  11390.     category: 'Interface-Changes'!
  11391.  
  11392. !CngsClassList methodsFor: 'menu messages'!
  11393. browse
  11394.     "Create and schedule a message browser on the selected class (and message)."
  11395.  
  11396.     | myClass |
  11397.     controller controlTerminate.
  11398.     myClass _ self selectedClassOrMetaClass.
  11399.     myClass notNil ifTrue: [
  11400.         Browser postOpenSuggestion: 
  11401.             (Array with: myClass with: parent selectedMessageName).
  11402.         Browser newOnClass: self selectedClass].
  11403.     controller controlInitialize!
  11404. browseFull
  11405.     "Create and schedule a System Browser with the selected class as its opening selection.  1/12/96 sw"
  11406.  
  11407.     | myClass |
  11408.  
  11409.     (myClass _ self selectedClassOrMetaClass) notNil ifTrue: 
  11410.         [BrowserView browseFullForClass: myClass method: parent selectedMessageName from: controller]!
  11411. browseInstVarRefs
  11412.     "Browse inst refs for the selected class.  1/15/96 sw"
  11413.  
  11414.     | myClass |
  11415.  
  11416.     (myClass _ self selectedClassOrMetaClass) notNil ifTrue: 
  11417.         [myClass browseInstVarRefs]!
  11418. classVariables
  11419.     "Browse class variables selected class. 2/1/96 sw"
  11420.  
  11421.     | myClass |
  11422.  
  11423.     (myClass _ self selectedClassOrMetaClass) notNil ifTrue: 
  11424.         [myClass browseClassVariables]!
  11425. copyToOther
  11426.     "Place this change in the other changeSet also"
  11427.     | changeSet other info cls |
  11428.  
  11429.     controller controlTerminate.
  11430.     changeSet _ parent changeSet.
  11431.     other _ (parent parent other: parent) changeSet.
  11432.  
  11433.     info _ changeSet classChangeAt: (cls _ self selectedClassOrMetaClass) name.
  11434.     info do: [:each | other atClass: cls add: each].
  11435.  
  11436.     info _ changeSet methodChanges at: cls name ifAbsent: [Dictionary new].
  11437.     info associationsDo: [:ass |
  11438.         other atSelector: ass key class: cls put: ass value].
  11439.     (parent parent other: parent) launch.
  11440.     controller controlInitialize!
  11441. forget
  11442.     "Remove all mention of this class from the changeSet"
  11443.     controller controlTerminate.
  11444.     listIndex = 0 ifFalse: [
  11445.         parent changeSet removeClassChanges: self selectedClassOrMetaClass.
  11446.         parent launch].
  11447.     controller controlInitialize!
  11448. instVarRefs
  11449.     "Browse inst refs for the selected class.  1/15/96 sw"
  11450.  
  11451.     | myClass |
  11452.  
  11453.     (myClass _ self selectedClassOrMetaClass) notNil ifTrue: 
  11454.         [myClass browseInstVarRefs]!
  11455. performMenuMessage: sel
  11456.     self perform: sel! !
  11457.  
  11458. !CngsClassList methodsFor: 'list'!
  11459. changed: what
  11460.     what == #emphasize ifTrue: [^ parent launch].
  11461.     super changed: what!
  11462. list
  11463.     ^ list!
  11464. list: anObject
  11465.     list _ anObject.
  11466.     listIndex _ 0.
  11467.     self changed: #list.
  11468.     parent changed: #class!
  11469. selectedClass
  11470.     | class |
  11471.     listIndex = 0 ifTrue: [^ nil].
  11472.     class _ self selectedClassOrMetaClass.
  11473.     ^ class theNonMetaClass        "the class, or soleInstance if its a metaclass"!
  11474. selectedClassOrMetaClass
  11475.     | sel |
  11476.     ^ listIndex = 0
  11477.         ifFalse: [Smalltalk classNamed: (list at: listIndex)]
  11478.         ifTrue: [nil]!
  11479. selection
  11480.     ^ listIndex = 0 
  11481.         ifFalse: [list at: listIndex]
  11482.         ifTrue: [nil]!
  11483. selection: item
  11484.     "If this item is in the list, select it."
  11485.     | index |
  11486.     (index _ list indexOf: item) = 0 ifFalse: [
  11487.         listIndex == index ifFalse: [
  11488.                 self toggleListIndex: index]
  11489.             ifTrue: [self changed: #listIndex.
  11490.                 parent changed: #class]].!
  11491. toggleListIndex: aNumber
  11492.     "What to do when the user chooses an item"
  11493.     listIndex == aNumber ifTrue: [listIndex _ 0]
  11494.         ifFalse: [listIndex _ aNumber].
  11495.     self changed: #listIndex.
  11496.     parent changed: #class! !
  11497.  
  11498. !CngsClassList methodsFor: 'accessing'!
  11499. controller: anObject
  11500.     controller _ anObject!
  11501. listIndex
  11502.     ^listIndex!
  11503. parent
  11504.     ^parent!
  11505. parent: anObject
  11506.     parent _ anObject! !Model subclass: #CngsMsgList
  11507.     instanceVariableNames: 'parent list listIndex controller '
  11508.     classVariableNames: ''
  11509.     poolDictionaries: ''
  11510.     category: 'Interface-Changes'!
  11511.  
  11512. !CngsMsgList methodsFor: 'as yet unclassified'!
  11513. allImplementorsOf
  11514.     "Create and schedule a message set browser on all implementors of all
  11515.     the messages sent by the current method."
  11516.  
  11517.     controller controlTerminate.
  11518.     self browseAllMessages.
  11519.     controller controlInitialize!
  11520. browseAllMessages
  11521.     "Create and schedule a message set browser on all implementors of all
  11522.     the messages sent by the current method.  Originally conceived and implemented by tck, 1991
  11523.      2/5/96 sw: give it a title"
  11524.  
  11525.     | method filteredList aClass aName |    
  11526.  
  11527.     listIndex ~= 0 ifTrue:
  11528.         [method _ (aClass _ parent selectedClassOrMetaClass) compiledMethodAt:
  11529.                         (aName _ parent selectedMessageName).
  11530.         filteredList _ method messages reject: 
  11531.             [:each | #(new initialize = ) includes: each].
  11532.         Smalltalk browseAllImplementorsOfList: filteredList asSortedCollection
  11533.              title: 'All messages sent in ', aClass name, '.', aName]!
  11534. browseSendersOfMessages
  11535.     "Create and schedule a message set browser on the senders of a user-chosen selector sent in the current message."
  11536.  
  11537.     controller controlTerminate.
  11538.     listIndex = 0 ifFalse: [
  11539.         Smalltalk showMenuThenBrowseSendersOf:
  11540.             (parent selectedClassOrMetaClass compiledMethodAt: 
  11541.                 self selection asSymbol) messages asSortedCollection].
  11542.     controller controlInitialize!
  11543. copyToOther
  11544.     "Place this change in the other changeSet also"
  11545.     | changeSet other info cls sel |
  11546.     listIndex = 0 ifTrue: [^ self].
  11547.  
  11548.     controller controlTerminate.
  11549.     changeSet _ parent changeSet.
  11550.     other _ (parent parent other: parent) changeSet.
  11551.     cls _ parent selectedClassOrMetaClass.
  11552.     sel _ self selection asSymbol.
  11553.  
  11554.     info _ changeSet methodChanges at: cls name ifAbsent: [Dictionary new].
  11555.     other atSelector: sel
  11556.         class: cls 
  11557.         put: (info at: sel).
  11558.     (parent parent other: parent) launch.
  11559.     controller controlInitialize!
  11560. fileOut
  11561.     "this method"
  11562.     listIndex = 0 ifFalse: [
  11563.         controller controlTerminate.
  11564.         Cursor write showWhile:
  11565.             [parent selectedClassOrMetaClass fileOutMethod: 
  11566.                 self selection asSymbol].
  11567.         controller controlInitialize].!
  11568. forget
  11569.     "Drop this method from the changeSet"
  11570.     listIndex = 0 ifTrue: [^ self].
  11571.     parent changeSet removeSelectorChanges: parent selectedMessageName 
  11572.             class: parent selectedClassOrMetaClass.
  11573.     parent launch.!
  11574. implementors
  11575.     "Create and schedule a message set browser on the implementations of the 
  11576.     selected message."
  11577.  
  11578.     controller controlTerminate.
  11579.     listIndex ~= 0 
  11580.         ifTrue: [Smalltalk browseAllImplementorsOf: self selection asSymbol].
  11581.     controller controlInitialize!
  11582. list: anObject
  11583.     list _ anObject.
  11584.     listIndex _ 0.
  11585.     self changed: #list.
  11586.     parent changed: #message!
  11587. messages
  11588.     "Create and schedule a message set browser on the the messages sent by 
  11589.     the selected message."
  11590.  
  11591.     controller controlTerminate.
  11592.     listIndex = 0 ifFalse: [
  11593.         Smalltalk showMenuThenBrowse:
  11594.             (parent selectedClassOrMetaClass compiledMethodAt: 
  11595.                 self selection asSymbol) messages asSortedCollection].
  11596.     controller controlInitialize!
  11597. performMenuMessage: sel
  11598.     self perform: sel!
  11599. selection
  11600.     ^ listIndex = 0 
  11601.         ifFalse: [list at: listIndex]
  11602.         ifTrue: [nil]!
  11603. selection: item
  11604.     "If this item is in the list, select it."
  11605.     | index |
  11606.     (index _ list indexOf: item) = 0 ifFalse: [
  11607.         
  11608.         self toggleListIndex: index.
  11609.         self changed: #listIndex.
  11610. "        self toggleListIndex: index."
  11611.         " listIndex _ index. "].!
  11612. senders
  11613.     "Create and schedule a message set browser on the methods in which the 
  11614.     selected message is sent."
  11615.  
  11616.     controller controlTerminate.
  11617.     listIndex ~= 0 
  11618.         ifTrue: [Smalltalk browseAllCallsOn: self selection asSymbol].
  11619.     controller controlInitialize!
  11620. toggleListIndex: aNumber
  11621.     "What to do when the user chooses an item"
  11622.     listIndex == aNumber ifTrue: [listIndex _ 0]
  11623.         ifFalse: [listIndex _ aNumber].
  11624.     self changed: #listIndex.
  11625.     parent changed: #message!
  11626. versions
  11627.     "Create and schedule a changelist browser on the versions of the 
  11628.     selected message."
  11629.  
  11630.     | class selector |
  11631.     controller controlTerminate.
  11632.     listIndex = 0 ifFalse: [
  11633.         class _ parent selectedClassOrMetaClass.
  11634.         selector _ parent selectedMessageName.
  11635.         ChangeList
  11636.             browseVersionsOf: (class compiledMethodAt: selector)
  11637.             class: parent selectedClass
  11638.             meta: class isMeta
  11639.             category: (class whichCategoryIncludesSelector: selector)
  11640.             selector: selector].
  11641.     controller controlInitialize! !
  11642.  
  11643. !CngsMsgList methodsFor: 'accessing'!
  11644. controller: anObject
  11645.     controller _ anObject!
  11646. list
  11647.     ^list!
  11648. listIndex
  11649.     ^listIndex!
  11650. parent
  11651.     ^parent!
  11652. parent: anObject
  11653.     parent _ anObject! !Object subclass: #Collection
  11654.     instanceVariableNames: ''
  11655.     classVariableNames: 'RandomForPicking '
  11656.     poolDictionaries: ''
  11657.     category: 'Collections-Abstract'!
  11658. Collection comment:
  11659. 'I am the abstract superclass of all classes that represent a group of elements.'!
  11660.  
  11661. !Collection methodsFor: 'accessing'!
  11662. size
  11663.     "Answer how many elements the receiver contains."
  11664.  
  11665.     | tally |
  11666.     tally _ 0.
  11667.     self do: [:each | tally _ tally + 1].
  11668.     ^tally! !
  11669.  
  11670. !Collection methodsFor: 'testing'!
  11671. includes: anObject 
  11672.     "Answer whether anObject is one of the receiver's elements."
  11673.  
  11674.     self do: [:each | anObject = each ifTrue: [^true]].
  11675.     ^false!
  11676. includesAllOf: aCollection 
  11677.     "Answer whether all the elements of aCollection are in the receiver."
  11678.     aCollection do: [:elem | (self includes: elem) ifFalse: [^ false]].
  11679.     ^ true!
  11680. includesAnyOf: aCollection 
  11681.     "Answer whether any element of aCollection is one of the receiver's elements."
  11682.     aCollection do: [:elem | (self includes: elem) ifTrue: [^ true]].
  11683.     ^ false!
  11684. isEmpty
  11685.     "Answer whether the receiver contains any elements."
  11686.  
  11687.     ^self size = 0!
  11688. occurrencesOf: anObject 
  11689.     "Answer how many of the receiver's elements are equal to anObject."
  11690.  
  11691.     | tally |
  11692.     tally _ 0.
  11693.     self do: [:each | anObject = each ifTrue: [tally _ tally + 1]].
  11694.     ^tally! !
  11695.  
  11696. !Collection methodsFor: 'adding'!
  11697. add: newObject 
  11698.     "Include newObject as one of the receiver's elements. Answer newObject. 
  11699.     ArrayedCollections cannot respond to this message."
  11700.  
  11701.     self subclassResponsibility!
  11702. addAll: aCollection 
  11703.     "Include all the elements of aCollection as the receiver's elements. Answer 
  11704.     aCollection."
  11705.  
  11706.     aCollection do: [:each | self add: each].
  11707.     ^aCollection! !
  11708.  
  11709. !Collection methodsFor: 'removing'!
  11710. remove: oldObject 
  11711.     "Remove oldObject as one of the receiver's elements. Answer oldObject 
  11712.     unless no element is equal to oldObject, in which case, create an error 
  11713.     notification."
  11714.  
  11715.     ^self remove: oldObject ifAbsent: [self errorNotFound]!
  11716. remove: oldObject ifAbsent: anExceptionBlock 
  11717.     "Remove oldObject as one of the receiver's elements. If several of the 
  11718.     elements are equal to oldObject, only one is removed. If no element is 
  11719.     equal to oldObject, answer the result of evaluating anExceptionBlock. 
  11720.     Otherwise, answer the argument, oldObject. SequenceableCollections 
  11721.     cannot respond to this message."
  11722.  
  11723.     self subclassResponsibility!
  11724. removeAll: aCollection 
  11725.     "Remove each element of aCollection from the receiver. If successful for 
  11726.     each, answer aCollection. Otherwise create an error notification."
  11727.  
  11728.     aCollection do: [:each | self remove: each].
  11729.     ^aCollection!
  11730. removeAllFoundIn: aCollection 
  11731.     "Remove each element of aCollection which is present in the receiver from the receiver"
  11732.  
  11733.     aCollection do: [:each | self remove: each ifAbsent: []].
  11734.     ^aCollection!
  11735. removeAllSuchThat: aBlock
  11736.     "Apply the condition to each element and remove it if the condition is true.  Use a copy to enumerate collections whose order changes when an element is removed (Set)."
  11737.     | copy newCollection |
  11738.     newCollection _ self species new.
  11739.     copy _ self copy.
  11740.     copy do: [:element |
  11741.         (aBlock value: element) ifTrue: [
  11742.             self remove: element.
  11743.             newCollection add: element]].
  11744.     ^ newCollection! !
  11745.  
  11746. !Collection methodsFor: 'enumerating'!
  11747. associationsDo: aBlock
  11748.     "Evaluate aBlock for each of the receiver's elements (key/value 
  11749.     associations).  If any non-association is within, the error is not caught now,
  11750.     but later, when a key or value message is sent to it."
  11751.  
  11752.     self do: aBlock!
  11753. collect: aBlock 
  11754.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  11755.     Collect the resulting values into a collection like the receiver. Answer 
  11756.     the new collection."
  11757.  
  11758.     | newCollection |
  11759.     newCollection _ self species new.
  11760.     self do: [:each | newCollection add: (aBlock value: each)].
  11761.     ^newCollection!
  11762. collect: collectBlock thenSelect: selectBlock
  11763.     ^ (self collect: collectBlock) select: selectBlock!
  11764. count: aBlock
  11765.     "Evaluate aBlock with each of the receiver's elements as the argument.  Return the number that answered true."
  11766.  
  11767.     | sum |
  11768.     sum _ 0.
  11769.     self do: [:each | 
  11770.         (aBlock value: each) ifTrue: [sum _ sum + 1]].
  11771.     ^ sum!
  11772. detect: aBlock 
  11773.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  11774.     Answer the first element for which aBlock evaluates to true."
  11775.  
  11776.     ^self detect: aBlock ifNone: [self errorNotFound]!
  11777. detect: aBlock ifNone: exceptionBlock 
  11778.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  11779.     Answer the first element for which aBlock evaluates to true. If none 
  11780.     evaluate to true, then evaluate the argument, exceptionBlock."
  11781.  
  11782.     self do: [:each | (aBlock value: each) ifTrue: [^each]].
  11783.     ^exceptionBlock value!
  11784. detectMax: aBlock
  11785.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  11786.     Answer the element for which aBlock evaluates to the highest magnitude.
  11787.     If collection empty, return nil.  This method might also be called elect:."
  11788.  
  11789.     | maxElement maxValue val |
  11790.     self do: [:each | 
  11791.         maxValue == nil
  11792.             ifFalse: [
  11793.                 (val _ aBlock value: each) > maxValue ifTrue: [
  11794.                     maxElement _ each.
  11795.                     maxValue _ val]]
  11796.             ifTrue: ["first element"
  11797.                 maxElement _ each.
  11798.                 maxValue _ aBlock value: each].
  11799.                 "Note that there is no way to get the first element that works 
  11800.                 for all kinds of Collections.  Must test every one."].
  11801.     ^ maxElement!
  11802. detectMin: aBlock
  11803.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  11804.     Answer the element for which aBlock evaluates to the lowest number.
  11805.     If collection empty, return nil."
  11806.  
  11807.     | minElement minValue val |
  11808.     self do: [:each | 
  11809.         minValue == nil
  11810.             ifFalse: [
  11811.                 (val _ aBlock value: each) < minValue ifTrue: [
  11812.                     minElement _ each.
  11813.                     minValue _ val]]
  11814.             ifTrue: ["first element"
  11815.                 minElement _ each.
  11816.                 minValue _ aBlock value: each].
  11817.                 "Note that there is no way to get the first element that works 
  11818.                 for all kinds of Collections.  Must test every one."].
  11819.     ^ minElement!
  11820. detectSum: aBlock
  11821.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  11822.     Return the sum of the answers."
  11823.     | sum |
  11824.     sum _ 0.
  11825.     self do: [:each | 
  11826.         sum _ (aBlock value: each) + sum].  
  11827.     ^ sum!
  11828. do: aBlock 
  11829.     "Evaluate aBlock with each of the receiver's elements as the argument."
  11830.  
  11831.     self subclassResponsibility!
  11832. inject: thisValue into: binaryBlock 
  11833.     "Accumulate a running value associated with evaluating the argument, 
  11834.     binaryBlock, with the current value of the argument, thisValue, and the 
  11835.     receiver as block arguments. For instance, to sum the numeric elements 
  11836.     of a collection, aCollection inject: 0 into: [:subTotal :next | subTotal + 
  11837.     next]."
  11838.  
  11839.     | nextValue |
  11840.     nextValue _ thisValue.
  11841.     self do: [:each | nextValue _ binaryBlock value: nextValue value: each].
  11842.     ^nextValue!
  11843. reject: aBlock 
  11844.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  11845.     Collect into a new collection like the receiver only those elements for 
  11846.     which aBlock evaluates to false. Answer the new collection."
  11847.  
  11848.     ^self select: [:element | (aBlock value: element) == false]!
  11849. select: aBlock 
  11850.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  11851.     Collect into a new collection like the receiver, only those elements for 
  11852.     which aBlock evaluates to true. Answer the new collection."
  11853.  
  11854.     | newCollection |
  11855.     newCollection _ self species new.
  11856.     self do: [:each | (aBlock value: each) ifTrue: [newCollection add: each]].
  11857.     ^newCollection!
  11858. select: selectBlock thenCollect: collectBlock
  11859.     ^ (self select: selectBlock) collect: collectBlock! !
  11860.  
  11861. !Collection methodsFor: 'converting'!
  11862. asBag
  11863.     "Answer a Bag whose elements are the elements of the receiver."
  11864.  
  11865.     | aBag |
  11866.     aBag _ Bag new.
  11867.     self do: [:each | aBag add: each].
  11868.     ^aBag!
  11869. asOrderedCollection
  11870.     "Answer an OrderedCollection whose elements are the elements of the 
  11871.     receiver. The order in which elements are added depends on the order in 
  11872.     which the receiver enumerates its elements. In the case of unordered 
  11873.     collections, the ordering is not necessarily the same for multiple requests 
  11874.     for the conversion."
  11875.  
  11876.     | anOrderedCollection |
  11877.     anOrderedCollection _ OrderedCollection new: self size.
  11878.     self do: [:each | anOrderedCollection addLast: each].
  11879.     ^anOrderedCollection!
  11880. asSet
  11881.     "Answer a Set whose elements are the unique elements of the receiver."
  11882.  
  11883.     | aSet |
  11884.     aSet _ Set new: self size.
  11885.     self do: [:each | aSet add: each].
  11886.     ^aSet!
  11887. asSortedArray
  11888.     "Return a copy of the receiver in sorted order, as an Array.  6/10/96 sw"
  11889.  
  11890.     ^ self asSortedCollection asArray!
  11891. asSortedCollection
  11892.     "Answer a SortedCollection whose elements are the elements of the 
  11893.     receiver. The sort order is the default less than or equal."
  11894.  
  11895.     | aSortedCollection |
  11896.     aSortedCollection _ SortedCollection new: self size.
  11897.     aSortedCollection addAll: self.
  11898.     ^aSortedCollection!
  11899. asSortedCollection: aBlock 
  11900.     "Answer a SortedCollection whose elements are the elements of the 
  11901.     receiver. The sort order is defined by the argument, aBlock."
  11902.  
  11903.     | aSortedCollection |
  11904.     aSortedCollection _ SortedCollection new: self size.
  11905.     aSortedCollection sortBlock: aBlock.
  11906.     aSortedCollection addAll: self.
  11907.     ^aSortedCollection! !
  11908.  
  11909. !Collection methodsFor: 'printing'!
  11910. printOn: aStream 
  11911.     "Refer to the comment in Object|printOn:."
  11912.  
  11913.     | tooMany |
  11914.     tooMany _ self maxPrint.    
  11915.         "Need absolute limit, or infinite recursion will never 
  11916.         notice anything going wrong.  7/26/96 tk"
  11917.     aStream nextPutAll: self class name, ' ('.
  11918.     self do: 
  11919.         [:element | 
  11920.         aStream position > tooMany ifTrue: [aStream nextPutAll: '...etc...)'. ^self].
  11921.         element printOn: aStream.
  11922.         aStream space].
  11923.     aStream nextPut: $)!
  11924. storeOn: aStream 
  11925.     "Refer to the comment in Object|storeOn:."
  11926.  
  11927.     | noneYet |
  11928.     aStream nextPutAll: '(('.
  11929.     aStream nextPutAll: self class name.
  11930.     aStream nextPutAll: ' new)'.
  11931.     noneYet _ true.
  11932.     self do: 
  11933.         [:each | 
  11934.         noneYet
  11935.             ifTrue: [noneYet _ false]
  11936.             ifFalse: [aStream nextPut: $;].
  11937.         aStream nextPutAll: ' add: '.
  11938.         aStream store: each].
  11939.     noneYet ifFalse: [aStream nextPutAll: '; yourself'].
  11940.     aStream nextPut: $)! !
  11941.  
  11942. !Collection methodsFor: 'private'!
  11943. emptyCheck
  11944.  
  11945.     self isEmpty ifTrue: [self errorEmptyCollection]!
  11946. errorEmptyCollection
  11947.  
  11948.     self error: 'this collection is empty'!
  11949. errorNoMatch
  11950.  
  11951.     self error: 'collection sizes do not match'!
  11952. errorNotFound
  11953.  
  11954.     self error: 'Object is not in the collection.'!
  11955. errorNotKeyed
  11956.  
  11957.     self error: self class name, 's do not respond to keyed accessing messages.'!
  11958. fill: numElements fromStack: aContext 
  11959.     "Fill me with numElements elements, popped in reverse order from
  11960.      the stack of aContext.  Do not call directly: this is called indirectly by {1. 2. 3}
  11961.      constructs.  Subclasses that support at:put: instead of add: should override
  11962.      this and call Context<pop:toIndexable:"
  11963.  
  11964.     aContext pop: numElements toAddable: self!
  11965. maxPrint
  11966.     "Answer the maximum number of characters to print with printOn:."
  11967.  
  11968.     ^5000!
  11969. maxSize
  11970.     "Answer the largest basicSize which is valid for the receiver's class."
  11971.  
  11972.     ^65486 "for VM3 interpreter DoradoST80Aug19"!
  11973. toBraceStack: itsSize 
  11974.     "Push receiver's elements onto the stack of thisContext sender.  Error if receiver does
  11975.      not have itsSize elements or if receiver is unordered.
  11976.      Do not call directly: this is called by {a. b} _ ... constructs."
  11977.  
  11978.     self size ~= itsSize ifTrue:
  11979.         [self error: 'Trying to store ', self size printString,
  11980.                     ' values into ', itsSize printString, ' variables.'].
  11981.     thisContext sender push: itsSize fromIndexable: self! !
  11982. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  11983.  
  11984. Collection class
  11985.     instanceVariableNames: ''!
  11986.  
  11987. !Collection class methodsFor: 'instance creation'!
  11988. fromBraceStack: itsSize 
  11989.     "Answer an instance of me with itsSize elements, popped in reverse order from
  11990.      the stack of thisContext sender.  Do not call directly: this is called by {1. 2. 3}
  11991.      constructs."
  11992.  
  11993.     ^ self newFrom: ((Array new: itsSize) fill: itsSize fromStack: thisContext sender)!
  11994. with: anObject 
  11995.     "Answer an instance of me containing anObject."
  11996.  
  11997.     | newCollection |
  11998.     newCollection _ self new.
  11999.     newCollection add: anObject.
  12000.     ^newCollection!
  12001. with: firstObject with: secondObject 
  12002.     "Answer an instance of me containing the two arguments as elements."
  12003.  
  12004.     | newCollection |
  12005.     newCollection _ self new.
  12006.     newCollection add: firstObject.
  12007.     newCollection add: secondObject.
  12008.     ^newCollection!
  12009. with: firstObject with: secondObject with: thirdObject 
  12010.     "Answer an instance of me containing the three arguments as elements."
  12011.  
  12012.     | newCollection |
  12013.     newCollection _ self new.
  12014.     newCollection add: firstObject.
  12015.     newCollection add: secondObject.
  12016.     newCollection add: thirdObject.
  12017.     ^newCollection!
  12018. with: firstObject with: secondObject with: thirdObject with: fourthObject 
  12019.     "Answer an instance of me, containing the four arguments as the 
  12020.     elements."
  12021.  
  12022.     | newCollection |
  12023.     newCollection _ self new.
  12024.     newCollection add: firstObject.
  12025.     newCollection add: secondObject.
  12026.     newCollection add: thirdObject.
  12027.     newCollection add: fourthObject.
  12028.     ^newCollection! !
  12029.  
  12030. !Collection class methodsFor: 'private'!
  12031. initialize
  12032.     "Set up a Random number generator to be used by pickOne when the user does not feel like creating his own Random generator."
  12033.     RandomForPicking _ Random new.
  12034.     ! !
  12035.  
  12036. Collection initialize!
  12037. Object subclass: #Color
  12038.     instanceVariableNames: 'rgb cachedDepth cachedBitPattern '
  12039.     classVariableNames: 'LightYellow RandomStream Magenta ComponentMax Cyan LightGray Depth16GreenShift PureBlue White PureYellow Depth16RedShift GrayToIndexMap Green ColorChart Depth32BlueShift LightGreen Depth16BlueShift Yellow PureCyan ColorNames HalfComponentMask DarkGray Blue Black VeryDarkGray Red BlueShift VeryLightGray LightMagenta GreenShift Depth32GreenShift Depth32RedShift RedShift PureMagenta IndexedColors ComponentMask PureGreen LightRed LightCyan HighLightBitmaps Gray LightOrange LightBrown PureRed LightBlue '
  12040.     poolDictionaries: ''
  12041.     category: 'Graphics-Display Objects'!
  12042. Color comment:
  12043. 'This class represents abstract color, regardless of the depth of bitmap it will be shown in.  At the very last moment a Color is converted to a pixelValue that depends on the depth of the actual Bitmap inside the Form it will be used with.  The supported depths (in bits) are 1, 2, 4, 8, 16, and 32.  The number of actual colors at these depths are: 2, 4, 16, 256, 32768, and 16 million.  (See comment in BitBlt.)  To change the depth of the Display and set how many colors you can see, execute: (Display newDepth: 8).  (See comment in DisplayMedium)
  12044.     Color is represented as the amount of light in red, green, and blue.  White is (1.0, 1.0, 1.0) and black is (0, 0, 0).  Pure red is (1.0, 0, 0).  These colors are "additive".  Think of Color''s instance variables as:
  12045.     r    amount of red, a Float between 0.0 and 1.0.
  12046.     g    amount of green, a Float between 0.0 and 1.0.
  12047.     b    amount of blue, a Float between 0.0 and 1.0.
  12048. (But, in fact, the three are encoded as values from 0 to 1023 and combined in a single integer, rgb.  The user does not need to know this.)
  12049.     Many colors are named.  You find a color by name by sending a message to class Color, for example (Color lightBlue).  Also, (Color red: 0.2 green: 0.6 blue: 1.0) or (Color r: 0.2 g: 0.6 b: 1.0) creates a color. (see below)
  12050.     A color is essentially immutable.  Once you set red, green, and blue, you cannot change them.  Instead, create a new Color and use it.
  12051.     Applications such as contour maps and bar graphs will want to display one of a set of shades based on a number.  Convert the range of this number to an integer from 1 to N.  Then call (Color green lightShades: N) to get an Array of colors from white to green.  Use the Array messages at:, atPin:, or atWrap: to pull out the correct color from the array.  atPin: gives the first (or last) color if the index is out of range.  atWrap: wraps around to the other end if the index is out of range.
  12052.     Here are some fun things to run in when your screen has color:
  12053.         Pen new mandala: 30 diameter: Display height-100.
  12054.         Pen new web  "Draw with the mouse, opt-click to end"
  12055.         Display fillWhite.  Pen new hilberts: 5.
  12056.         Form toothpaste: 30  "Draw with mouse, opt-click to end"
  12057. You might also want to try the comment in
  12058.     Form>class>examples>tinyText...
  12059.  
  12060.  
  12061. Messages:
  12062.     mixed: proportion with: aColor    Answer this color mixed with the given color additively. The proportion, a number between 0.0 and 1.0, determines what what fraction of the receiver to use in the mix.
  12063.  
  12064.     +     add two colors
  12065.     -     subtract two colors
  12066.     *    multiply the values of r, g, b by a number or an Array of factors.  ((Color named: #white) * 0.3) gives a darkish gray.  (aColor * #(0 0 0.9)) gives a color with slightly less blue.
  12067.     /    divide a color by a factor or an array of three factors.
  12068.  
  12069.     errorForDepth: d     How close the nearest color at this depth is to this abstract color.  Sum of the squares of the RGB differences, square rooted and normalized to 1.0.  Multiply by 100 to get percent.
  12070.  
  12071.     hue            Returns the hue of the color. On a wheel from 0 to 360 with pure red at 0 and again at 360.
  12072.     saturation    Returns the saturation of the color.  0.0 to 1.0
  12073.     brightness    Returns the brightness of the color.  0.0 to 1.0
  12074.  
  12075.     name    Look to see if this Color has a name.
  12076.     display    Show a swatch of this color tracking the cursor.
  12077.  
  12078.     lightShades: thisMany        An array of thisMany colors from white to the receiver. 
  12079.     darkShades: thisMany        An array of thisMany colors from black to the receiver.  Array is of length num.
  12080.     mix: color2 shades: thisMany        An array of thisMany colors from the receiver to color2.
  12081.     wheel: thisMany            An array of thisMany colors around the color wheel starting and ending at the receiver.
  12082.  
  12083.     pixelValueForDepth: d    Returns the bits that appear be in a Bitmap of this depth for this color.  Represents the nearest available color at this depth.  Normal users do not need to know which pixelValue is used for which color. 
  12084.  
  12085. Messages to Class Color.
  12086.     red: r green: g blue: b        Return a color with the given r, g, and b components.
  12087.     r: g: b:        Same as above, for fast typing.
  12088.  
  12089.      hue: h saturation: s brightness: b        Create a color with the given hue, saturation, and brightness.
  12090.  
  12091.     pink
  12092.      blue
  12093.     red ...    Many colors have messages that return an instance of Color.
  12094.     canUnderstand: #brown      Returns true if #brown is a defined color.
  12095.     names        An OrderedCollection of the names of the colors.
  12096.     named: #notAllThatGray put: aColor    Add a new color to the list and create an access message and a class variable for it.
  12097.     fromUser    Shows the palette of colors available at this display depth.  Click anywhere to return the color you clicked on.
  12098.  
  12099.     hotColdShades: thisMany    An array of thisMany colors showing temperature from blue to red to white hot.
  12100.  
  12101.     stdColorsForDepth: d        An Array of colors available at this depth.  For 16 bit and 32 bits, returns a ColorGenerator.  It responds to at: with a Color for that index, simulating a very big Array. 
  12102.  
  12103.    colorFromPixelValue: value depth: d    Returns a Color whose bit pattern (inside a Bitmap) at this depth is the number specified.  Normal users do not need to use this.
  12104.  
  12105. (See also comments in these classes: Form, Bitmap, BitBlt, Pattern, MaskedForm.)'!
  12106.  
  12107. !Color methodsFor: 'examples'!
  12108. display
  12109.     "Show a swatch of this color tracking the cursor until the next mouseClick. 6/14/96 tk"
  12110.     "Color red display"
  12111.     | f c |
  12112.     f _ Form extent: 40@20 depth: Display depth.
  12113.     c _ Bitmap with: (self pixelWordForDepth: Display depth).
  12114.     f fillColor: c.
  12115.     Cursor blank showWhile:
  12116.         [f follow: [Sensor cursorPoint] while: [Sensor noButtonPressed]]!
  12117. hsvExample
  12118.     "Shows a palette of hues, varying the saturation and brightness for each one."
  12119.     "Color new hsvExample.  Modified 6/14/96 tk"
  12120.  
  12121.     | d v x y c rect |
  12122.     d _ Display depth.
  12123.     c _ Color new.        "modified in loop below"
  12124.     rect _ 0@0 extent: 5@5.    "modified in loop below"
  12125.     0 to: 179 by: 15 do: [:h |
  12126.         0 to: 10 do: [:s |
  12127.             0 to: 10 do: [:v |
  12128.                 c setHue: h saturation: s asFloat / 10.0 brightness: v asFloat / 10.0.
  12129.                 rect left: (h*4) + (s*5); width: 5.
  12130.                 rect top: (v*5); height: 5.
  12131.                 Display fill: rect fillColor: (c bitPatternForDepth: d).
  12132.  
  12133.                 c setHue: h + 180 saturation: s asFloat / 10.0 brightness: v asFloat / 10.0.
  12134.                 rect top: (v*5) + 80; height: 5.
  12135.                 Display fill: rect fillColor: (c bitPatternForDepth: d).
  12136.             ].
  12137.         ].
  12138.     ].
  12139. !
  12140. showHuesAtSaturation: s brightness: v
  12141.     "Shows a palette of hues at the given (saturation, brightness) point."
  12142.     "Color new showHuesAtSaturation: 0.9 brightness: 0.9"
  12143.  
  12144.     | rect c |
  12145.     rect _ 0@0 extent: 5@5.    "modified in loop below"
  12146.     0 to: 179 by: 10 do: [:h |
  12147.         c _ Color hue: h saturation: s brightness: v.
  12148.         rect left: 5 + (h*4); width: 35.
  12149.         rect top: 5; height: 35.
  12150.         Display fill: rect fillColor: c.
  12151.  
  12152.         c setHue: h + 180 saturation: s brightness: v.
  12153.         rect top: 45; height: 35.
  12154.         Display fill: rect fillColor: c.
  12155.     ].
  12156. !
  12157. showHuesInteractively
  12158.     "Shows a palette of hues at (saturation, brightness) point determined by the mouse position. Click mouse button to exit and return the selected saturation and brightness."
  12159.     "Color new showHuesInteractively"
  12160.  
  12161.     | baseP p s v |
  12162.     baseP _ Sensor cursorPoint.
  12163.     [Sensor anyButtonPressed] whileFalse: [
  12164.         p _ Sensor cursorPoint.
  12165.         s _ ((p x - baseP x) + 80) asFloat / 100.0.
  12166.         v _ ((p y - baseP y) + 80) asFloat / 100.0.
  12167.         self showHuesAtSaturation: s brightness: v.
  12168.     ].
  12169.     ^ (s min: 1.0) @ (v min: 1.0)!
  12170. showPalette
  12171.     "Show the 12x12x12 palette used in fromUser.
  12172.     Color new showPalette"
  12173.  
  12174.      | c rect |
  12175.     "RGB display gives 12x12x12 cube to choose from"
  12176.     c _ Color new.        "modified in loop below"
  12177.     rect _ 0@0 extent: 5@5.    "modified in loop below"
  12178.     0 to: 11 do: [:r |
  12179.         0 to: 11 do: [:g |
  12180.             0 to: 11 do: [:b |
  12181.                 c setRed: r green: g blue: b range: 11.
  12182.                 rect left: (r*60) + (b*5); width: 5.
  12183.                 rect top: (g*5); height: 5.
  12184.                 Display fill: rect fillColor: c.
  12185.             ].
  12186.         ].
  12187.     ].
  12188. !
  12189. test
  12190.  
  12191.     IndexedColors do: [ :c |
  12192.     ].!
  12193. test: depth
  12194.     "Color new test: 8"
  12195.  
  12196.     | i c |
  12197.     1 to: (1 << depth) do: [ :i |
  12198.         c _ IndexedColors at: i.
  12199.         (Color colorFromPixelValue: (c pixelValueForDepth: depth) value depth: depth) = c
  12200.             ifFalse: [ self error: 'bad conversion' ].
  12201.     ].! !
  12202.  
  12203. !Color methodsFor: 'access'!
  12204. blue
  12205.     "Answer my blue component, a float in the range [0.0..1.0].  
  12206.  
  12207. Don't confuse this with the class message (Color blue) that returns the color pure blue.  6/13/96 tk"
  12208.  
  12209.     ^ self privateBlue asFloat / ComponentMax!
  12210. brightness
  12211.     "Return the brightness of this paint color, a float in the range [0.0..1.0]."
  12212.  
  12213.     ^ ((self privateRed max:
  12214.         self privateGreen) max:
  12215.         self privateBlue) asFloat / ComponentMax!
  12216. green
  12217.     "Answer my green component, a float in the range [0.0..1.0].  
  12218.  
  12219. Don't confuse this with the class message (Color green) that returns the color pure green.  6/13/96 tk"
  12220.  
  12221.     ^ self privateGreen asFloat / ComponentMax!
  12222. hue
  12223.     "Return the hue of this color, an angle in the range [0.0..360.0]."
  12224.  
  12225.     | r g b max min span h |
  12226.     r _ self privateRed.
  12227.     g _ self privateGreen.
  12228.     b _ self privateBlue. 
  12229.  
  12230.     max _ ((r max: g) max: b).
  12231.     min _ ((r min: g) min: b).
  12232.     span _ (max - min) asFloat.
  12233.     span = 0.0 ifTrue: [ ^ 0.0 ].
  12234.  
  12235.     r = max ifTrue: [
  12236.         h _ ((g - b) asFloat / span) * 60.0.
  12237.     ] ifFalse: [
  12238.         g = max
  12239.             ifTrue: [ h _ 120.0 + (((b - r) asFloat / span) * 60.0). ]
  12240.             ifFalse: [ h _ 240.0 + (((r - g) asFloat / span) * 60.0). ].
  12241.     ].
  12242.  
  12243.     h < 0.0 ifTrue: [ h _ 360.0 + h ].
  12244.     ^ h!
  12245. red
  12246.     "Answer my red component, a float in the range [0.0..1.0].  
  12247.  
  12248. Don't confuse this with the class message (Color red) that returns the color pure red.  6/13/96 tk"
  12249.  
  12250.     ^ self privateRed asFloat / ComponentMax!
  12251. saturation
  12252.     "Return the saturation of this color, a value between 0.0 and 1.0."
  12253.  
  12254.     | r g b max min |
  12255.     r _ self privateRed.
  12256.     g _ self privateGreen.
  12257.     b _ self privateBlue. 
  12258.  
  12259.     max _ ((r max: g) max: b).
  12260.     min _ ((r min: g) min: b).
  12261.     max = 0
  12262.         ifTrue: [ ^ 0.0 ]
  12263.         ifFalse: [ ^ (max - min) asFloat / max asFloat ].
  12264. ! !
  12265.  
  12266. !Color methodsFor: 'groups of shades'!
  12267. darkShades: thisMany
  12268.     "An array of thisMany colors from black to the receiver.  Array is of length num. Very useful for displaying color based on a variable in your program.  6/18/96 tk"
  12269.  
  12270.     ^ self class black mix: self shades: thisMany
  12271.  
  12272. "| a r |  a _ (Color red darkShades: 10).  
  12273.     r _ 0@0 extent: 30@30.
  12274.     a do: [:each |
  12275.         r moveBy: 30@0.
  12276.         Display fill: r fillColor: each].
  12277. "!
  12278. lightShades: thisMany
  12279.     "An array of thisMany colors from white to self. Very useful for displaying color based on a variable in your program.  6/18/96 tk"
  12280.  
  12281.     ^ self class white mix: self shades: thisMany
  12282.  
  12283. "| a r |  a _ (Color red lightShades: 10).  
  12284.     r _ 0@0 extent: 30@30.
  12285.     a do: [:each |
  12286.         r moveBy: 30@0.
  12287.         Display fill: r fillColor: each].
  12288. "!
  12289. mix: color2 shades: thisMany
  12290.     "Return an array of thisMany colors from self to color2. Very useful for displaying color based on a variable in your program.  6/18/96 tk"
  12291.  
  12292.     | redInc greenInc blueInc rr gg bb c out |
  12293.     thisMany = 1 ifTrue: [^ Array with: color2].
  12294.     redInc _ color2 red - self red / (thisMany-1).
  12295.     greenInc _ color2 green - self green / (thisMany-1).
  12296.     blueInc _ color2 blue - self blue / (thisMany-1).
  12297.     rr _ self red.  gg _ self green.  bb _ self blue.
  12298.     out _ (1 to: thisMany) collect: [:num |
  12299.         c _ Color r: rr g: gg b: bb.
  12300.         rr _ rr + redInc.
  12301.         gg _ gg + greenInc.
  12302.         bb _ bb + blueInc.
  12303.         c].
  12304.     out at: out size put: color2.    "hide roundoff errors"
  12305.     ^ out
  12306.  
  12307. "| a r |  a _ (Color red mix: Color green shades: 10).  
  12308.     r _ 0@0 extent: 30@30.
  12309.     a do: [:each |
  12310.         r moveBy: 30@0.
  12311.         Display fill: r fillColor: each].
  12312. "!
  12313. wheel: thisMany
  12314.     "An array of thisMany colors around the color wheel starting at self and ending all the way around the hue space just before self.  Array is of length thisMany.  Very useful for displaying color based on a variable in your program.  6/18/96 tk"
  12315.  
  12316.     | sat bri hue step c |
  12317.     thisMany = 1 ifTrue: [^ Array with: self].
  12318.     sat _ self saturation.
  12319.     bri _ self brightness.
  12320.     hue _ self hue.
  12321.     step _ 360.0/thisMany.
  12322.     ^ (1 to: thisMany) collect: [:num |
  12323.         c _ Color hue: hue saturation: sat brightness: bri.
  12324.         hue _ hue + step.    "it does mod 360"
  12325.         c].
  12326.  
  12327.  
  12328. "| a r |  a _ (Color blue wheel: 20).  
  12329.     r _ 0@0 extent: 30@30.
  12330.     a do: [:each |
  12331.         r moveBy: 30@0.
  12332.         Display fill: r fillColor: each].
  12333. "! !
  12334.  
  12335. !Color methodsFor: 'equality'!
  12336. = aColor
  12337.     ^ aColor isColor and: [aColor rgb = rgb]!
  12338. hash
  12339.  
  12340.     ^ rgb!
  12341. isColor
  12342.     ^ true! !
  12343.  
  12344. !Color methodsFor: 'transformations'!
  12345. * aFactor
  12346.     "Answer this color with its RGB multiplied by aFactor or a vector of factors.  Try:
  12347.     ((Color white) * 0.3) display         a darkish gray.  
  12348.     ((Color blue) * #(0 0 0.9)) display    slightly less than blue.  6/18/96 tk"
  12349.  
  12350. (aFactor isKindOf: Number) ifTrue: [
  12351.     ^ Color
  12352.         red: ((self red * aFactor) min: 1.0 max: 0.0)
  12353.         green: ((self green * aFactor) min: 1.0 max: 0.0)
  12354.         blue: ((self blue * aFactor) min: 1.0 max: 0.0)].
  12355.  
  12356. "(aFactor isKindOf: ArrayedCollection) ifTrue: ["
  12357.     ^ Color
  12358.         red: ((self red * (aFactor at: 1)) min: 1.0 max: 0.0)
  12359.         green: ((self green * (aFactor at: 2)) min: 1.0 max: 0.0)
  12360.         blue: ((self blue * (aFactor at: 3)) min: 1.0 max: 0.0).
  12361. !
  12362. + aColor
  12363.     "Answer this color mixed with the given color. Additive color mixing.  6/18/96 tk"
  12364.  
  12365.     ^ Color
  12366.         red: ((self red + aColor red) min: 1.0 max: 0.0)
  12367.         green: ((self green + aColor green) min: 1.0 max: 0.0)
  12368.         blue: ((self blue + aColor  blue) min: 1.0 max: 0.0)
  12369. !
  12370. - aColor
  12371.     "Answer aColor is subtracted from the given color.  Removing color in an additive color space.  6/18/96 tk"
  12372.  
  12373.     ^ Color
  12374.         red: ((self red - aColor red) min: 1.0 max: 0.0)
  12375.         green: ((self green - aColor green) min: 1.0 max: 0.0)
  12376.         blue: ((self blue - aColor  blue) min: 1.0 max: 0.0)
  12377. !
  12378. / aFactor
  12379.     "Answer this color with its RGB divided by aFactor or a vector of factors.  Try:
  12380.     ((Color white) / 3) display         a darkish gray.  
  12381.     ((Color white) / #(1 1 2)) display    slightly less than blue.  6/18/96 tk"
  12382.  
  12383. (aFactor isKindOf: Number) ifTrue: [
  12384.     ^ Color
  12385.         red: ((self red / aFactor) min: 1.0 max: 0.0)
  12386.         green: ((self green / aFactor) min: 1.0 max: 0.0)
  12387.         blue: ((self blue / aFactor) min: 1.0 max: 0.0)].
  12388.  
  12389. "(aFactor isKindOf: ArrayedCollection) ifTrue: ["
  12390.     ^ Color
  12391.         red: ((self red / (aFactor at: 1)) min: 1.0 max: 0.0)
  12392.         green: ((self green / (aFactor at: 2)) min: 1.0 max: 0.0)
  12393.         blue: ((self blue / (aFactor at: 3)) min: 1.0 max: 0.0).
  12394. !
  12395. alpha: alphaValue
  12396.     ^ TranslucentColor new setRgb: rgb alpha: alphaValue!
  12397. darker
  12398.     "Return a lighter shade of the same color.  1/6th towards white. 6/18/96 tk  Should this be an absolute step, instead of relative?"
  12399.     ^ self mixed: 5/6 with: Color black!
  12400. hsvScaleBy: anArray
  12401.     "Scale hue, saturation, and brightness by this factor.  Useful for varying brightness under program control.  6/24/96 tk"
  12402.  
  12403.     ^ Color
  12404.         hue: (self hue * (anArray at: 1))    "it does mod 360"
  12405.         saturation: ((self saturation * (anArray at: 2)) min: 1.0 max: 0.0)
  12406.         brightness: ((self brightness * (anArray at: 3)) min: 1.0 max: 0.0).
  12407. !
  12408. lighter
  12409.     "Return a lighter shade of the same color.  1/6th towards white. 6/18/96 tk  Should this be an absolute step, instead of relative?"
  12410.     ^ self mixed: 5/6 with: Color white!
  12411. mixed: proportion with: aColor
  12412.     "Answer this color mixed with the given color. The proportion,
  12413.      a number between 0.0 and 1.0, determines what what fraction
  12414.      of the receiver to use in the mix. For example, 0.9 would yield
  12415.      a color close to the receiver."
  12416.     "Details: This method uses RGB interpolation; HSV interpolation
  12417.      can lead to surprises."
  12418.  
  12419.     | frac1 frac2 |
  12420.     frac1 _ proportion asFloat min: 1.0 max: 0.0.
  12421.     frac2 _ 1.0 - frac1.
  12422.     ^ Color
  12423.         red: (self    red * frac1) + (aColor    red * frac2) 
  12424.         green: (self green * frac1) + (aColor green * frac2) 
  12425.         blue: (self   blue * frac1) + (aColor  blue * frac2)
  12426. ! !
  12427.  
  12428. !Color methodsFor: 'conversions'!
  12429. bitPatternForDepth: depth
  12430.     "The raw call on BitBlt needs a Bitmap to represent this color.  Return the color at the destination Form depth as a Bitmap.  Pattern returns a longer Bitmap.  6/14/96 tk
  12431.     For the bits that are in a single pixel, use pixelValueAtDepth:.
  12432.     For a 32-bit integer of (32/depth) pixels, use pixelWordAtDepth:"
  12433.  
  12434.     depth == cachedDepth ifTrue: [^ cachedBitPattern].
  12435.     cachedDepth _ depth.
  12436.  
  12437.     depth > 1 ifTrue: [^ cachedBitPattern _ Bitmap with: (self pixelWordForDepth: depth)].
  12438.  
  12439.     "Spatial halftone for gray for depth 1"
  12440.     self = Black ifTrue: [^ cachedBitPattern _ Bitmap with: 16rFFFFFFFF].
  12441.     self = White ifTrue: [^ cachedBitPattern _ Bitmap with: 16r0].
  12442.     self = Gray ifTrue: [^ cachedBitPattern _ Bitmap with: 16r55555555 with: 16rAAAAAAAA].
  12443.     self = LightGray ifTrue: [^ cachedBitPattern _ Bitmap with: 16r44444444 with: 16r11111111].
  12444.     self = DarkGray ifTrue: [^ cachedBitPattern _ Bitmap with: 16rBBBBBBBB with: 16rEEEEEEEE].
  12445.     ^ cachedBitPattern _ Bitmap with: 16r0.    "everything else"!
  12446. errorForDepth: d
  12447.     "How close the nearest color at this depth is to this abstract color.  Sum of the squares of the RGB differences, square rooted and normalized to 1.0.  Multiply by 100 to get percent. 6/19/96 tk"
  12448.  
  12449.     | p col r g b rdiff gdiff bdiff diff |
  12450.     p _ self pixelValueForDepth: d.
  12451.     col _ Color colorFromPixelValue: p depth: d.
  12452.     r _ self privateRed.  g _ self privateGreen.  b _ self privateBlue.
  12453.     rdiff _ r - col privateRed.
  12454.     gdiff _ g - col privateGreen.
  12455.     bdiff _ b - col privateBlue.
  12456.     diff _ (rdiff*rdiff) + (gdiff*gdiff) + (bdiff*bdiff).
  12457.     ^ diff asFloat sqrt / 1771.89        "= (1023*1023*3) sqrt" !
  12458. mapIndexForDepth: d
  12459.     "Return the index corresponding to this color in a 512-entry color transformation map. RGB forms collapse to 3 bits per color when indexing into such a colorMap."
  12460.  
  12461.     | colorValue bpc r g b |
  12462.     colorValue _ self pixelValueForDepth: d.
  12463.     d <= 8 ifTrue: [ ^ colorValue + 1 ].
  12464.     d = 16
  12465.         ifTrue: [ bpc _ 5 ]  "5 bits per color"
  12466.         ifFalse: [ bpc _ 8 ].  "8 bits per color"
  12467.  
  12468.     r _ (colorValue bitShift: 3 - bpc - bpc - bpc) bitAnd: 7.
  12469.     g _ (colorValue bitShift: 3 - bpc - bpc) bitAnd: 7.
  12470.     b _ (colorValue bitShift: 3 - bpc) bitAnd: 7.
  12471.     ^ (r bitShift: 6) + (g bitShift: 3) + b + 1
  12472.     "Is this pre or post G and B switch???"!
  12473. name
  12474.     "Look to see if this Color has a name.  Must be an exact match of color. 6/19/96 tk"
  12475.     ColorNames do: [:each | 
  12476.         (Color perform: each) = self ifTrue: [
  12477.             ^ each]].
  12478.     ^ nil!
  12479. originate: aPoint on: destForm
  12480.     "Answer a new Color whose bits have been wrapped around
  12481.     in represent a stipple.  We are not a stipple.  6/24/96 tk"
  12482.  
  12483.     ^ self!
  12484. pixelValue: val toBitPatternDepth: depth
  12485.     "convert to a 32 bit quantity.  Covers 32//depth pixels. Dan's method 6/22/96 tk"
  12486.  
  12487.     depth = 32 ifTrue: [^ Bitmap with: val].
  12488.     ^ Bitmap with: ((val bitAnd: (1 bitShift: depth) - 1) * 
  12489.         (#(16rFFFFFFFF  "replicate for every bit"
  12490.             16r55555555 -    "2 bits"
  12491.             16r11111111 - - -  "4 bits"
  12492.             16r01010101 - - - - - - -  "8 bits"
  12493.             16r00010001) at: depth))
  12494.  
  12495. "The above gives the same result as this explanation:
  12496.     | d word |
  12497.     d _ depth.
  12498.     word _ val.
  12499.     [d >= 32] whileFalse: [
  12500.         word _ word bitOr: (word bitShift: d).
  12501.         d _ d+d].
  12502.     ^ Bitmap with: word
  12503. "!
  12504. pixelValue: val toPixelWordDepth: depth
  12505.     "convert to a 32 bit quantity.  Covers 32//depth pixels. 6/14/96 tk"
  12506.     | d word |
  12507.     d _ depth.
  12508.     word _ val.
  12509.     [d >= 32] whileFalse: [
  12510.         word _ word bitOr: (word bitShift: d).
  12511.         d _ d+d].
  12512.     ^ word
  12513. !
  12514. pixelValueForDepth: d
  12515.     "Answer bits that appear in ONE pixel of this color in a Bitmap of the given depth. The depth must be one of 1, 2, 4, 8, 16, or 32.  Returns an integer.  Contrast with pixelWordForDepth: and bitPatternForDepth:.  Inverse is the class message colorFromPixelValue:depth:"
  12516.     "Details: For depths of 8 or less, the result is a colorMap index (zero order). For depths of 16 and 32, it is a direct color with 5 or 8 bits per color component.  6/1/96 jm, 6/14/96 tk"
  12517.  
  12518.     d < 8 ifTrue: [ ^ self closestPixelValueDepth: d ].
  12519.     d = 8 ifTrue: [ ^ self closestPixelValue8 ].
  12520.  
  12521.     d = 16 ifTrue: [
  12522.         "five bits per component; top bits ignored"
  12523.         ^ (((rgb bitShift: Depth16RedShift) bitAnd: 16r7C00) bitOr:
  12524.              ((rgb bitShift: Depth16GreenShift) bitAnd: 16r03E0)) bitOr:
  12525.              ((rgb bitShift: Depth16BlueShift) bitAnd: 16r001F).
  12526.     ].
  12527.  
  12528.     d = 32 ifTrue: [
  12529.         "eight bits per component; top 8 bits ignored"
  12530.         ^ (((rgb bitShift: Depth32RedShift) bitAnd: 16rFF0000) bitOr:
  12531.              ((rgb bitShift: Depth32GreenShift) bitAnd: 16r00FF00)) bitOr:
  12532.              ((rgb bitShift: Depth32BlueShift) bitAnd: 16r0000FF).
  12533.     ].
  12534.  
  12535.     self error: 'unknown pixel depth: ', d printString
  12536.  
  12537. !
  12538. pixelWordForDepth: depth
  12539.     "Answer bits that appear in a 32-bit word of a Bitmap of the given depth. This may represent between 32 and 1 pixels, depending on the depth.  The depth must be one of 1, 2, 4, 8, 16, or 32.  Returns an integer."
  12540.     | word d |
  12541.     word _ self pixelValueForDepth: depth.
  12542.     d _ depth.
  12543.     [d >= 32] whileFalse: [
  12544.         word _ word bitOr: (word bitShift: d).
  12545.         d _ d+d].
  12546.     ^ word! !
  12547.  
  12548. !Color methodsFor: 'printing'!
  12549. printOn: aStream
  12550.  
  12551.     aStream
  12552.         nextPutAll: 'Color(';
  12553.         nextPutAll: (self red roundTo: 0.001) printString;
  12554.         nextPutAll: ', ';
  12555.         nextPutAll: (self green roundTo: 0.001) printString;
  12556.         nextPutAll: ', ';
  12557.         nextPutAll: (self blue roundTo: 0.001) printString;
  12558.         nextPutAll: ')'.
  12559. !
  12560. storeOn: aStream
  12561.  
  12562.     aStream
  12563.         nextPutAll: '(Color r:';
  12564.         nextPutAll: (self red roundTo: 0.001) printString;
  12565.         nextPutAll: ' g: ';
  12566.         nextPutAll: (self green roundTo: 0.001) printString;
  12567.         nextPutAll: ' b: ';
  12568.         nextPutAll: (self blue roundTo: 0.001) printString;
  12569.         nextPutAll: ')'.
  12570. ! !
  12571.  
  12572. !Color methodsFor: 'private'!
  12573. closestColor1
  12574.     "Return the nearest approximation to this color for a monochrome Form.
  12575.     Should this be based on r+g+b?  Should it be L. lightness, in L*a*b* space? 6/14/96 tk"
  12576.  
  12577.     self halt. "old"
  12578.     self brightness > 0.5
  12579.         ifTrue: [ ^ 0 ]
  12580.         ifFalse: [ ^ 1 ].!
  12581. closestColor2
  12582.     "Return the nearest approximation to this color for a 2-bit deep Form."
  12583.  
  12584.     | b |
  12585.     self halt. "old"
  12586.     self = PureYellow ifTrue: [ ^ 16rFFFFFFFF ].
  12587.     b _ self brightness.
  12588.     b >= 0.75 ifTrue: [ ^ 0 ].
  12589.     b <= 0.25 ifTrue: [ ^ 16r55555555 ].
  12590.     ^ 16rAAAAAAAA!
  12591. closestColor4
  12592.     "Return the nearest approximation to this color for a 4-bit deep Form."
  12593.  
  12594.     | bIndex |
  12595.     self halt. "old"
  12596.     self = PureYellow ifTrue: [ ^ 16r33333333 ].
  12597.     self = PureRed ifTrue: [ ^ 16r44444444 ].
  12598.     self = PureGreen ifTrue: [ ^ 16r55555555 ].
  12599.     self = PureBlue ifTrue: [ ^ 16r66666666 ].
  12600.     self = PureCyan ifTrue: [ ^ 16r77777777 ].
  12601.     self = PureMagenta ifTrue: [ ^ 16r88888888 ].
  12602.  
  12603.     bIndex _ (self brightness * 8.0) rounded.  "bIndex in [0..8]"
  12604.     ^ #(
  12605.         16r11111111            "black"
  12606.         16r99999999            "7/8 gray"
  12607.         16rAAAAAAAA    "6/8 gray"
  12608.         16rBBBBBBBB        "5/8 gray"
  12609.         16rCCCCCCCC        "4/8 gray"
  12610.         16rDDDDDDDD        "3/8 gray"
  12611.         16rEEEEEEEE        "2/8 gray"
  12612.         16rFFFFFFFF        "1/8 gray"
  12613.         16r00000000            "white"
  12614.     ) at: bIndex + 1
  12615.  
  12616. !
  12617. closestColor8
  12618.     "Return the nearest approximation to this color for an 8-bit deep Form."
  12619.  
  12620.      ^ IndexedColors at: (self closestPixelValue8)+1!
  12621. closestColor8old
  12622.     "Return the nearest approximation to this color for an 8-bit deep Form."
  12623.  
  12624.     | bIndex p n |
  12625.     self isGray ifTrue: [
  12626.         "select nearest gray"
  12627.         p _ GrayToIndexMap at: (self privateBlue >> 2) + 1.
  12628.     ] ifFalse: [
  12629.         "compute nearest entry in the color cube"
  12630.         p _ ((((self privateRed    * 5) + HalfComponentMask) // ComponentMask) * 36) +
  12631.              ((((self privateBlue * 5) + HalfComponentMask) // ComponentMask) *  6) +
  12632.              (((self privateGreen    * 5) + HalfComponentMask) // ComponentMask) + 40.
  12633.     ].
  12634.     ^ (p bitShift: 24) bitOr: ((p bitShift: 16) bitOr: ((p bitShift: 8) bitOr: p))!
  12635. "** 1. not used
  12636.     2. 1 to: (1 bitShift: depth) ??
  12637. "
  12638. closestColorDepth: depth
  12639.     "Return the nearest approximation to this color for this depth of Form.  Depth can be 1, 2, 4, or 8.  This method is for when we go to L*a*b* color space.  For now use the faster version. 6/14/96 tk"
  12640.     |  least r g b col rdiff gdiff bdiff diff leastIndex |
  12641.     depth > 8 ifTrue: [^ self error: 'depth must be 1, 2, 4, or 8'].
  12642.     least _ ComponentMask*ComponentMask*3.    "start with max"
  12643.     r _ self privateRed.  g _ self privateGreen.  b _ self privateBlue.
  12644.     1 to: (1 bitShift: depth) - 1 do: [:ind |
  12645.         col _ IndexedColors at: ind.
  12646.         rdiff _ r - col privateRed.
  12647.         gdiff _ g - col privateGreen.
  12648.         bdiff _ b - col privateBlue.
  12649.         diff _ (rdiff*rdiff) + (gdiff*gdiff) + (bdiff*bdiff).
  12650.         diff < least ifTrue: [
  12651.             least _ diff.
  12652.             leastIndex _ ind]].
  12653.     ^ IndexedColors at: leastIndex!
  12654. closestPixelValue1
  12655.     "Return the nearest approximation to this color for a monochrome Form.
  12656.     Should this be based on r+g+b?  Should it be L. lightness, in L*a*b* space? 6/14/96 tk"
  12657.  
  12658.     self brightness > 0.5
  12659.         ifTrue: [ ^ 0 ]
  12660.         ifFalse: [ ^ 1 ].!
  12661. closestPixelValue8
  12662.     "Return the index in the standard 8-bit colormap for the nearest match to this color.  Find the closest color in our 6x6x6 color cube.  See if any of the grays are closer to the real color.  6/14/96 tk"
  12663.     | r g b rr gg bb diff gray val diffg diffc pvtGray rd gd bd |
  12664.  
  12665.     rgb = 0 ifTrue: [^ 1].    "Special case for black, very common"
  12666.     rgb = 16r3FFFFFFF ifTrue: [^ 0].
  12667.         "Special case for white, very common"
  12668.     "Find the closest color in our 6x6x6 color cube. Integers in [0..5]" 
  12669.     r _ (((self privateRed    * 5) + HalfComponentMask) // ComponentMask).
  12670.     g _ (((self privateGreen * 5) + HalfComponentMask) // ComponentMask).
  12671.     b _ (((self privateBlue    * 5) + HalfComponentMask) // ComponentMask).
  12672.  
  12673.     rr _ self privateRed.  gg _ self privateGreen.  bb _ self privateBlue.
  12674.     diff _ ((rr-gg)*(rr-gg)) + ((gg-bb)*(gg-bb)) + ((bb-rr)*(bb-rr)).    "least squares"
  12675.     "If diff is big, r g and b not very close, not very much like a gray.  One 6x6x6 step is 1023.0 / 5.0 = 204.6.  Squared is 204.6 * 204.6 =  41861.2
  12676.      Return a color from our cube that starts at index 40." 
  12677.     diff >= 41861 ifTrue: [^ (r * 36) + (b * 6) + g + 40].
  12678.  
  12679.     "Consider using a gray"
  12680.     pvtGray _ rr+gg+bb //3.        "[0..1023]"
  12681.     gray _ (((pvtGray* 32) + HalfComponentMask) // ComponentMask).
  12682.         "33 discrete gray levels [0..32]"
  12683.     val _ pvtGray.
  12684.     "Do error comparison in 1023 space"
  12685.     diffg _ ((val - rr)*(val - rr)) + ((val - gg)*(val - gg)) + 
  12686.             ((val - bb)*(val - bb)).    "error in the Gray"
  12687.  
  12688.     "Color in the cube [0..5], blown back up to [0..1023] with error"
  12689.     rd _ (r * ComponentMask) // 5.    
  12690.     gd _ (g * ComponentMask) // 5.
  12691.     bd _ (b * ComponentMask) // 5.
  12692.     diffc _ ((rd - rr)*(rd - rr)) + ((gd - gg)*(gd - gg)) + ((bd - bb)*(bd - bb)).
  12693.             "error in the color from the cube"
  12694.     "self halt."
  12695.     diffg < diffc
  12696.         ifTrue: ["33 grays.  eighths starting at index 9, 32nds from 16 to 39"
  12697.             ^ #(1 16 17 18 9 19 20 21 10 22 23 24 11 25 26 27 12 
  12698.                  28 29 30 13 31 32 33 14 34 35 36 15 37 38 39 0) at: gray+1]
  12699.         ifFalse: [^ (r * 36) + (b * 6) + g + 40]
  12700. !
  12701. closestPixelValueDepth: depth
  12702.     "Return the nearest approximation to this color for this depth of Form.  Depth can be 1, 2, 4, or 8.  This method is for when we go to L*a*b* color space.  For now use the faster version. 6/14/96 tk"
  12703.     |  least r g b col rdiff gdiff bdiff diff leastIndex |
  12704.  
  12705.     depth > 256 ifTrue: [^ self error: 'depth must be 1, 2, 4, or 8'].
  12706.     least _ ComponentMask*ComponentMask*3 + 100.        "start with max"
  12707.     r _ self privateRed.  g _ self privateGreen.  b _ self privateBlue.
  12708.     0 to: (1 bitShift: depth) - 1 do: [:ind |
  12709.         col _ IndexedColors at: ind+1.
  12710.         rdiff _ r - col privateRed.
  12711.         gdiff _ g - col privateGreen.
  12712.         bdiff _ b - col privateBlue.
  12713.         diff _ (rdiff*rdiff) + (gdiff*gdiff) + (bdiff*bdiff).
  12714.         diff < least ifTrue: [
  12715.             least _ diff.
  12716.             leastIndex _ ind]].
  12717.     ^ leastIndex!
  12718. closestPixelWord1
  12719.     "Return the nearest approximation to this color for a monochrome Form.  6/14/96 tk"
  12720.  
  12721.     self brightness > 0.5
  12722.         ifTrue: [ ^ 0 ]
  12723.         ifFalse: [ ^ 16rFFFFFFFF ].    "32 pixels by 1 bit each"!
  12724. closestPixelWord2
  12725.     "Return the nearest approximation to this color for a 2-bit deep Form."
  12726.  
  12727.     | b |
  12728.     self = PureYellow ifTrue: [ ^ 16rFFFFFFFF ].    "16 pixels by 2 bits each"
  12729.     b _ self brightness.
  12730.     b >= 0.75 ifTrue: [ ^ 0 ].
  12731.     b <= 0.25 ifTrue: [ ^ 16r55555555 ].
  12732.     ^ 16rAAAAAAAA!
  12733. isGray
  12734.     "Find least squared distance of r, g, b from one another. 6/18/96 tk"
  12735.  
  12736.     | rr gg bb diff |
  12737.     rr _ self privateRed.  gg _ self privateGreen.  bb _ self privateBlue.
  12738.     diff _ ((rr-gg)*(rr-gg)) + ((gg-bb)*(gg-bb)) + ((bb-rr)*(bb-rr)).         "least squares"
  12739.     "If diff is big, r g and b not very close, not very much like a gray.  One 6x6x6 step is 1023.0 / 5.0 = 204.6.  Squared is 204.6 * 204.6 =  41861.2
  12740. If closer than that, its more a gray than a color." 
  12741.     ^ diff < 41861!
  12742. privateBlue
  12743.     "Private!! Answer the internal representation of my blue component."
  12744.  
  12745.     ^ rgb bitAnd: ComponentMask!
  12746. privateGreen
  12747.     "Private!! Answer the internal representation of my green component."
  12748.  
  12749.     ^ (rgb >> GreenShift) bitAnd: ComponentMask!
  12750. privateRed
  12751.     "Private!! Answer the internal representation of my red component."
  12752.  
  12753.     ^ (rgb bitShift: 0 - RedShift) bitAnd: ComponentMask!
  12754. rgb
  12755.     ^ rgb!
  12756. setHue: hue saturation: saturation brightness: brightness
  12757.     "Initialize this color to the given hue, saturation, and brightness. See the comment in the instance creation method for details."
  12758.  
  12759.     | s v h i f p q t |
  12760.     s _ (saturation asFloat max: 0.0) min: 1.0.
  12761.     v _ (brightness asFloat max: 0.0) min: 1.0.
  12762.  
  12763.     "zero saturation yields gray with the given brightness"
  12764.     s = 0.0 ifTrue: [ ^ self setRed: v green: v blue: v ].
  12765.  
  12766.     h _ (hue \\ 360) asFloat / 60.0.
  12767.     (0.0 > h) ifTrue: [ h _ 6.0 + h ].
  12768.     i _ h asInteger.  "integer part of hue"
  12769.     f _ h - i.         "fractional part of hue"
  12770.     p _ (1.0 - s) * v.
  12771.     q _ (1.0 - (s * f)) * v.
  12772.     t _ (1.0 - (s * (1.0 - f))) * v.
  12773.  
  12774.     0 = i ifTrue: [ ^ self setRed: v green: t blue: p ].
  12775.     1 = i ifTrue: [ ^ self setRed: q green: v blue: p ].
  12776.     2 = i ifTrue: [ ^ self setRed: p green: v blue: t ].
  12777.     3 = i ifTrue: [ ^ self setRed: p green: q blue: v ].
  12778.     4 = i ifTrue: [ ^ self setRed: t green: p blue: v ].
  12779.     5 = i ifTrue: [ ^ self setRed: v green: p blue: q ].
  12780.  
  12781.     self error: 'implementation error'.
  12782. !
  12783. setRed: r green: g blue: b
  12784.     "Initialize this color's r, g, and b components to the given values in [0.0..1.0].  Encoded in a single variable as 3 integers [0..1023].
  12785.     A color is essentially immutable.  Once you set red, green, and blue, you cannot change them.  Instead, create a new Color and use it.
  12786.     6/18/96 tk"
  12787.  
  12788.     rgb == nil ifFalse: [^ self error: 'Can''t change a Color.  Please make a new one'].
  12789.     rgb _
  12790.         (((r * ComponentMax) rounded bitAnd: ComponentMask) bitShift: RedShift) +
  12791.         (((g * ComponentMax) rounded bitAnd: ComponentMask) bitShift: GreenShift) +
  12792.          ((b * ComponentMax) rounded bitAnd: ComponentMask)!
  12793. setRed: r green: g blue: b range: zeroToThis
  12794.     "Initialize this color's r, g, and b components to the given values in [0.0..1.0].  Range is [0..r], a weird numbering system with size r+epsilon, min 0, max r.  6/14/96 tk"
  12795.     | range |
  12796.  
  12797.     range _ zeroToThis.
  12798.     rgb == nil ifFalse: [^ self error: 'Can''t write into a Color.  Make a new one'].
  12799.     rgb _
  12800.         ((((r * ComponentMask) // range) bitAnd: ComponentMask) bitShift: RedShift) +
  12801.         ((((g * ComponentMask) // range) bitAnd: ComponentMask) bitShift: GreenShift) +
  12802.          (((b * ComponentMask) // range) bitAnd: ComponentMask)! !
  12803.  
  12804. !Color methodsFor: 'testing--to be removed'! !
  12805. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  12806.  
  12807. Color class
  12808.     instanceVariableNames: ''!
  12809.  
  12810. !Color class methodsFor: 'colors'!
  12811. allColorsForDepth: d
  12812.     "Return the colorMap for the depth.  Use a ColorGenerator to simulate a very big Array for 16 and 32.  6/22/96 tk"
  12813.  
  12814.     d < 16 ifTrue: [^ IndexedColors copyFrom: 1 to: (1 bitShift: d)].
  12815.     ^ ColorGenerator new depth: d!
  12816. black
  12817.     ^Black!
  12818. blue
  12819.     ^Blue!
  12820. cyan
  12821.     ^Cyan!
  12822. darkGray
  12823.     ^DarkGray!
  12824. gray
  12825.     ^Gray!
  12826. green
  12827.     ^Green!
  12828. lightBlue
  12829.     ^LightBlue!
  12830. lightBrown
  12831.     ^LightBrown!
  12832. lightCyan
  12833.     ^LightCyan!
  12834. lightGray
  12835.     ^LightGray!
  12836. lightGreen
  12837.     ^LightGreen!
  12838. lightMagenta
  12839.     ^LightMagenta!
  12840. lightOrange
  12841.     ^LightOrange!
  12842. lightRed
  12843.     ^LightRed!
  12844. lightYellow
  12845.     ^LightYellow!
  12846. magenta
  12847.     ^Magenta!
  12848. named: newName put: aColor
  12849.     "Add a new color to the list and create an access message and a class variable for it.  The name should start with a lowercase letter.  (The class variable will start with an uppercase letter.)  (Color names) gives a list of the colors.  6/13/96 tk"
  12850.     | str cap sym accessor csym |
  12851.     (aColor isKindOf: self) ifFalse: [^ self error: 'not a Color'].
  12852.     str _ newName asString.
  12853.     sym _ str asSymbol.
  12854.     cap _ str copy.
  12855.     cap at: 1 put: (cap at: 1) asUppercase.
  12856.     csym _ cap asSymbol.
  12857.     (self class canUnderstand: sym) ifFalse: [
  12858.         "define access message"
  12859.         accessor _ str, (String with: Character cr with: Character tab),             '^', cap.
  12860.         self class compile: accessor
  12861.             classified: 'colors'].
  12862.     (self classPool includesKey: csym) ifFalse: [
  12863.         self addClassVarName: cap].
  12864.     (ColorNames includes: sym) ifFalse: [
  12865.         ColorNames add: sym].
  12866.     ^ self classPool at: csym put: aColor!
  12867. names
  12868.     "Return a list of names of colors.  An OrederdCollection of symbols.  6/14/96 tk
  12869.       Color perform: (Color names at: 1)    "
  12870.     ^ ColorNames!
  12871. red
  12872.     ^Red!
  12873. veryDarkGray
  12874.     ^VeryDarkGray!
  12875. veryLightGray
  12876.     ^VeryLightGray!
  12877. white
  12878.     ^White!
  12879. yellow
  12880.     ^Yellow! !
  12881.  
  12882. !Color class methodsFor: 'instance creation'!
  12883. colorChartForDepth: depth extent: chartExtent
  12884.     "Displays a color palette using abstract colors.  fromUser can then save it.  Different for each depth.  6/26/96 tk
  12885.     Modified to produce a form of variable size instead of being
  12886.     fixed-size and running on the display 8/20/96 di"
  12887.     "(Color colorChartForDepth: Display depth extent: 720@100) display"
  12888.     | c p f nSteps rect w h |
  12889.     f _ Form extent: chartExtent depth: depth.
  12890.     nSteps _ depth>8 ifTrue: [12] ifFalse: [6].
  12891.     w _ chartExtent x // (nSteps*nSteps).
  12892.     h _ chartExtent y - 20 // nSteps.
  12893.     0 to: nSteps-1 do: [:r |
  12894.         0 to: nSteps-1 do: [:g |
  12895.             0 to: nSteps-1 do: [:b |
  12896.                 c _ self red: r green: g blue: b range: nSteps-1.
  12897.                 rect _ ((r*nSteps*w) + (b*w)) @ (g*h) extent: w@(h+1).
  12898.                 f fill: rect fillColor: c].
  12899.             ].
  12900.         ].
  12901.     p _ chartExtent x // 3 @ (chartExtent y - 20).
  12902.     w _ chartExtent x - p x - 20 / 100.
  12903.     0 to: 99 do:
  12904.         [ :v | c _ self red: v green: v blue: v range: 99.
  12905.         f fill: ((v*w)@0 + p extent: (w+1)@20) fillColor: c].
  12906.     ^ f!
  12907. colorFromPixelValue: p depth: d
  12908.     "Convert a pixel value for the given display depth into a color."
  12909.     "Details: For depths of 8 or less, the pixel value is simply looked
  12910.      up in a table. For depths of 16 and 32, the color components are
  12911.      extracted and converted into a color."
  12912.  
  12913.     | r g b |
  12914.     d = 1 ifTrue: [ ^ IndexedColors at: (p bitAnd: 16r01) + 1 ].
  12915.     d = 2 ifTrue: [ ^ IndexedColors at: (p bitAnd: 16r03) + 1 ].
  12916.     d = 4 ifTrue: [ ^ IndexedColors at: (p bitAnd: 16r0F) + 1 ].
  12917.     d = 8 ifTrue: [ ^ IndexedColors at: (p bitAnd: 16rFF) + 1 ].
  12918.  
  12919.     d = 16 ifTrue: [
  12920.         "five bits per component; top bit ignored"
  12921.         r _ (p bitShift: -10) bitAnd: 16r1F.
  12922.         g _ (p bitShift:  -5) bitAnd: 16r1F.
  12923.         b _ p bitAnd: 16r1F.
  12924.         ^ self red: r green: g blue: b range: 31
  12925.     ].
  12926.  
  12927.     d = 32 ifTrue: [
  12928.         "eight bits per component; top 8 bits ignored"
  12929.         r _ (p bitShift: -16) bitAnd: 16rFF.
  12930.         g _ (p bitShift:  -8) bitAnd: 16rFF.
  12931.         b _ p bitAnd: 16rFF.
  12932.         ^ self red: r green: g blue: b range: 255
  12933.     ].
  12934.  
  12935.     self error: 'unknown pixel depth: ', d printString
  12936. !
  12937. fromUser
  12938.     "Displays a color palette using abstract colors, then waits for a mouse click. Try it at various display depths!!"
  12939.     "Color fromUser"
  12940.     | save d c rect old new s p |
  12941.     d _ Display depth.
  12942.     ((ColorChart == nil) or: [ColorChart depth ~= Display depth]) 
  12943.         ifTrue: [ColorChart _ self colorChartForDepth: d extent: 720@100].
  12944.     save _ Form fromDisplay: (0@0 extent: ColorChart extent).
  12945.     ColorChart displayAt: 0@0.
  12946.  
  12947.     old _ 0.
  12948.     [Sensor anyButtonPressed] whileFalse: [
  12949.         p _ Display pixelValueAt: Sensor cursorPoint.
  12950.         c _ self colorFromPixelValue: p depth: d.
  12951.         Display fill: (0@80 extent: 60@20) fillColor: c.
  12952.         (new _ p) = old ifFalse: [
  12953.             Display fillWhite: (60@80 extent: 180@20).
  12954.             s _ c printString.
  12955.             s _ 'R,G,B = ', (s copyFrom: 7 to: s size - 1).
  12956.             s displayAt: 63@83.
  12957.             old _ new.
  12958.         ].
  12959.     ].
  12960.     save displayAt: 0@0.
  12961.     Sensor waitNoButton.
  12962.     ^ c
  12963. !
  12964. hotColdShades: thisMany
  12965.     "An array of thisMany colors showing temperature from blue to red to white hot.  (Later improve this by swinging in hue.)  6/19/96 tk"
  12966.  
  12967. | n s1 s2 s3 s4 s5 |
  12968. thisMany < 5 ifTrue: [^ self error: 'must be at least 5 shades'].
  12969. n _ thisMany // 5.
  12970. s1 _ self white mix: self yellow shades: (thisMany - (n*4)).
  12971. s2 _ self yellow mix: self red shades: n+1.
  12972. s2 _ s2 copyFrom: 2 to: n+1.
  12973. s3 _ self red mix: self green darker shades: n+1.
  12974. s3 _ s3 copyFrom: 2 to: n+1.
  12975. s4 _ self green darker mix: self blue shades: n+1.
  12976. s4 _ s4 copyFrom: 2 to: n+1.
  12977. s5 _ self blue mix: self black shades: n+1.
  12978. s5 _ s5 copyFrom: 2 to: n+1.
  12979. ^ s1,s2,s3,s4,s5
  12980.  
  12981. "| a r |  a _ (Color hotColdShades: 25).  
  12982.     r _ 0@0 extent: 30@30.
  12983.     a do: [:each |
  12984.         r moveBy: 30@0.
  12985.         Display fill: r fillColor: each].
  12986. "!
  12987. hue: hue saturation: saturation brightness: brightness
  12988.     "Create a color with the given hue, saturation, and brightness. Hue is given as the angle in degrees of the color on the color circle where red is zero degrees. Saturation and brightness are numbers in [0.0..1.0] where larger values are more saturated or brighter colors. For example:
  12989.  
  12990.     Color new setHue: 0 saturation: 1 brightness: 1
  12991.  
  12992. is pure red."
  12993.  
  12994.     ^ self basicNew setHue: hue saturation: saturation brightness: brightness!
  12995. new
  12996.  
  12997.     ^ self basicNew setRed: 0.0 green: 0.0 blue: 0.0!
  12998. r: r g: g b: b
  12999.     "Return a color with the given r, g, and b components."
  13000.  
  13001.     ^ self basicNew setRed: r green: g blue: b!
  13002. r: r g: g b: b alpha: alpha
  13003.     ^ (self r: r g: g b: b) alpha: alpha!
  13004. random
  13005.  
  13006.     ^ self basicNew
  13007.         setHue: (360.0 * RandomStream next)
  13008.         saturation: (0.3 + (RandomStream next * 0.7))
  13009.         brightness: (0.4 + (RandomStream next * 0.6))!
  13010. red: r green: g blue: b
  13011.     "Return a color with the given r, g, and b components."
  13012.  
  13013.     ^ self basicNew setRed: r green: g blue: b!
  13014. red: r green: g blue: b range: range
  13015.     "Return a color with the given r, g, and b components specified as integers in the range [0..r]. This avoids the floating point arithmetic in the red:green:blue: message and is thus a bit faster for certain applications (such as computing a sequence of colors for a palette)."
  13016.  
  13017.     ^ self basicNew setRed: r green: g blue: b range: range! !
  13018.  
  13019. !Color class methodsFor: 'misc'!
  13020. makeColorMap: colorArray depth: bitsPerPixel
  13021.     "colorArray is now an Array of (256) Colors that the picture wants to use.  We have a fixed palette of 256 Colors.  Convert each to the closest of our colors and return a mapping vector.  Note we use zero-order (0-255) colors here.  6/24/96 tk"
  13022.  
  13023.     bitsPerPixel > 8 ifTrue: [self error: 'Unknown depth'].
  13024.         "GIFs can't come in 16, 24, or 32"
  13025.         "later deal with 3,4,5,6,7 bit deep GIFs"
  13026.     ^ colorArray collect: [:color | 
  13027.         color pixelValueForDepth: bitsPerPixel].
  13028. !
  13029. quickHighLight: depth
  13030.     "Quickly return a Bitblt-ready raw colorValue for highlighting areas.  6/22/96 tk"
  13031.  
  13032.     ^ HighLightBitmaps at: depth! !
  13033.  
  13034. !Color class methodsFor: 'class initialization'!
  13035. indexedColors
  13036.  
  13037.     ^ IndexedColors!
  13038. initialize
  13039.     "Color initialize"
  13040.  
  13041.     "Details: Externally, the red, green, and blue components of color
  13042.     are floats in the range [0.0..1.0]. Internally, they are represented
  13043.     as integers in the range [0..ComponentMask] packing into a
  13044.     small integer to save space and to allow fast hashing and
  13045.     equality testing.
  13046.  
  13047.     For a general description of color representations for computer
  13048.     graphics, including the relationship between the RGB and HSV
  13049.     color models used here, see Chapter 17 of Foley and van Dam,
  13050.     Fundamentals of Interactive Computer Graphics, Addison-Wesley,
  13051.     1982."
  13052.  
  13053.     ComponentMask _ 1023.
  13054.     HalfComponentMask _ 512.  "used to round up in integer calculations"
  13055.     ComponentMax _ 1023.0.  "a Float used to normalize components"
  13056.     RedShift _ 20.
  13057.     GreenShift _ 10.
  13058.     BlueShift _ 0.
  13059.  
  13060.     Depth16RedShift        _ (5-10) * 3.    "bits"
  13061.     Depth16GreenShift    _ (5-10) * 2.
  13062.     Depth16BlueShift    _ 5-10.
  13063.  
  13064.     Depth32RedShift        _ (8-10) * 3.    "bits"
  13065.     Depth32GreenShift    _ (8-10) * 2.
  13066.     Depth32BlueShift    _ 8-10.
  13067.  
  13068.     PureRed         _ self red: 1 green: 0 blue: 0.
  13069.     PureGreen     _ self red: 0 green: 1 blue: 0.
  13070.     PureBlue     _ self red: 0 green: 0 blue: 1.
  13071.     PureYellow     _ self red: 1 green: 1 blue: 0.
  13072.     PureCyan     _ self red: 0 green: 1 blue: 1.
  13073.     PureMagenta _ self red: 1 green: 0 blue: 1.
  13074.  
  13075.     RandomStream _ Random new.
  13076.  
  13077.     self initializeIndexedColors.
  13078.     self initializeGrayToIndexMap.
  13079.     self initializeNames.
  13080.     self initializeHighLights.!
  13081. initializeGrayToIndexMap
  13082.     "Build an array of gray values available in the fixed colormap. This array is used
  13083.      to map from a pixel value back to its color."
  13084.     "Note: This must be called after initializeIndexedColors, since it uses IndexedColors."
  13085.     "Color initializeGrayToIndexMap"
  13086.  
  13087.     | grayLevels grayIndices c distToClosest dist indexOfClosest |
  13088.     "record the level and index of each gray in the 8-bit color table"
  13089.     grayLevels _ OrderedCollection new.
  13090.     grayIndices _ OrderedCollection new.
  13091.     1 to: IndexedColors size do: [ :i |
  13092.         c _ IndexedColors at: i.
  13093.         c saturation = 0.0 ifTrue: [
  13094.             grayLevels add: (c privateBlue) >> 2.
  13095.             grayIndices add: i - 1.  "hardward colormap is 0-based"
  13096.         ].
  13097.     ].
  13098.     grayLevels _ grayLevels asArray.
  13099.     grayIndices _ grayIndices asArray.
  13100.  
  13101.     "for each gray level in [0..255], select the closest match"
  13102.     GrayToIndexMap _ ByteArray new: 256.
  13103.     0 to: 255 do: [ :level |
  13104.         distToClosest _ 10000.  "greater than distance to any real gray"
  13105.         1 to: grayLevels size do: [ :i |
  13106.             dist _ (level - (grayLevels at: i)) abs.
  13107.             dist < distToClosest ifTrue: [
  13108.                 distToClosest _ dist.
  13109.                 indexOfClosest _ grayIndices at: i.
  13110.             ].
  13111.         ].
  13112.         GrayToIndexMap at: (level + 1) put: indexOfClosest.
  13113.     ].
  13114.  
  13115.     
  13116. !
  13117. initializeHighLights
  13118.     "Special set of very fast colors (Bitmaps) for highlighting text and areas without converting colors. 6/22/96 tk
  13119.     Color initializeHighLights"
  13120.  
  13121. "A default color that will at least reverse most bits"
  13122. | v |
  13123. HighLightBitmaps _ Array new: 32.
  13124. #(1 2 4 8 16 32) do: [:depth |
  13125.     v _ depth <= 8
  13126.         ifTrue: [self new pixelValue: (#(1 3 0 5 0 0 0 8) at: depth)
  13127.                     toBitPatternDepth: depth]
  13128.         ifFalse: [Bitmap with: 16rFFFFFFFF].
  13129.     HighLightBitmaps at: depth put: v].!
  13130. initializeIndexedColors
  13131.     "Build an array of colors corresponding to the fixed colormap used
  13132.      for display depths of 1, 2, 4, or 8 bits."
  13133.     "Color initializeIndexedColors"
  13134.  
  13135.     | a index grayVal |
  13136.     a _ Array new: 256.
  13137.  
  13138.     "1-bit colors (monochrome)"
  13139.     a at: 1 put: (self red: 1.0 green: 1.0 blue: 1.0).  "white"
  13140.     a at: 2 put: (self red: 0.0 green: 0.0 blue: 0.0).  "black"
  13141.  
  13142.     "additional colors for 2-bit color"
  13143.     a at: 3 put: (self red: 0.5 green: 0.5 blue: 0.5).  "50% gray"
  13144.     a at: 4 put: (self red: 1.0 green: 1.0 blue: 0.0).  "yellow"
  13145.  
  13146.     "additional colors for 4-bit color"
  13147.     a at: 5 put: (self red: 1.0 green: 0.0 blue: 0.0).  "red"
  13148.     a at: 6 put: (self red: 0.0 green: 1.0 blue: 0.0).  "green"
  13149.     a at: 7 put: (self red: 0.0 green: 0.0 blue: 1.0).  "blue"
  13150.     a at: 8 put: (self red: 0.0 green: 1.0 blue: 1.0).  "cyan"
  13151.     a at: 9 put: (self red: 1.0 green: 0.0 blue: 1.0).  "magenta"
  13152.  
  13153.     a at: 10 put: (self red: 0.125 green: 0.125 blue: 0.125).    "1/8 gray"
  13154.     a at: 11 put: (self red: 0.25 green: 0.25 blue: 0.25).        "2/8 gray"
  13155.     a at: 12 put: (self red: 0.375 green: 0.375 blue: 0.375).    "3/8 gray"
  13156.     a at: 13 put: (self red: 0.50 green: 0.50 blue: 0.50).        "4/8 gray"
  13157.     a at: 14 put: (self red: 0.625 green: 0.625 blue: 0.625).    "5/8 gray"
  13158.     a at: 15 put: (self red: 0.75 green: 0.75 blue: 0.75).        "6/8 gray"
  13159.     a at: 16 put: (self red: 0.875 green: 0.875 blue: 0.875).    "7/8 gray"
  13160.  
  13161.     "additional colors for 8-bit color"
  13162.     "24 more shades of gray (1/32 increments but not repeating 1/8 increments)"
  13163.     index _ 17.
  13164.     1 to: 31 do: [ :v |
  13165.         (v \\ 4) = 0 ifFalse: [
  13166.             grayVal _ v / 32.0.
  13167.             a at: index put: (self red: grayVal green: grayVal blue: grayVal).
  13168.             index _ index + 1.
  13169.         ].
  13170.     ].
  13171.  
  13172.     "The remainder of color table defines a color cube with six steps
  13173.      for each primary color. Note that the corners of this cube repeat
  13174.      previous colors, but this simplifies the mapping between RGB colors
  13175.      and color map indices. This color cube spans indices 40 through 255
  13176.      (indices 41-256 in this 1-based array)."
  13177.  
  13178.     0 to: 5 do: [ :r |
  13179.         0 to: 5 do: [ :g |
  13180.             0 to: 5 do: [ :b |
  13181.                 index _ 41 + ((36 * r) + (6 * b) + g).
  13182.                 index > 256 ifTrue: [
  13183.                     self error: 'index out of range in color table compuation'.
  13184.                 ].
  13185.                 a at: index put:
  13186.                     (self red: r green: g blue: b range: 5).
  13187.             ].
  13188.         ].
  13189.     ].
  13190.  
  13191.     IndexedColors _ a.!
  13192. initializeNames
  13193.     "Set values of the named colors. 6/13/96 tk
  13194.     Color initializeNames"
  13195.  
  13196.     ColorNames _ OrderedCollection new.
  13197.     #(white black gray yellow red green blue cyan
  13198.         magenta - veryDarkGray darkGray - lightGray 
  13199.         veryLightGray - )
  13200.         doWithIndex:
  13201.         [:colorPut :i | colorPut == #- ifFalse:
  13202.             [self named: colorPut put: (IndexedColors at: i)]].
  13203.  
  13204.     #(lightBlue lightBrown lightCyan lightGray lightGreen lightMagenta lightOrange lightRed lightYellow)
  13205.             with:  "Color fromUser first bitAnd: 255"
  13206.         #( 219 206 147 37 207 254 236 248 249)
  13207.             do: [:colorPut :i | 
  13208.                 self named: colorPut put: (IndexedColors at: i+1)].
  13209. ! !
  13210.  
  13211. Color initialize!
  13212. Object subclass: #ColorGenerator
  13213.     instanceVariableNames: 'depth '
  13214.     classVariableNames: ''
  13215.     poolDictionaries: ''
  13216.     category: 'Graphics-Display Objects'!
  13217. ColorGenerator comment:
  13218. 'This class behaves like an array holding a very large number of colors.  It responds to at: by looking up the Nth Color, making an instance of it and returning it.  For the colorMap of 16-bit and 32-bit colors as given by Color allColorsForDepth: d.
  13219.  
  13220.     at: index        Returns a Color by calling (Color colorForPixelValue: index depth: d) which unpacks the bits in the pixelValue.
  13221.     size            the maximum index that is a color.
  13222. '!
  13223.  
  13224. !ColorGenerator methodsFor: 'as yet unclassified'!
  13225. at: index
  13226.     "Return the Nth color at this depth, as if this were a very big array. Index is 1-order, pixelValues are 0-order.  6/22/96 tk"
  13227.  
  13228.      ^ Color colorFromPixelValue: index-1 depth: depth!
  13229. depth
  13230.     ^ depth!
  13231. depth: d
  13232.     "Set the depth.  6/22/96 tk"
  13233.  
  13234.     (d = 16) | (d = 32) ifFalse: [
  13235.         ^ self error: 'Use an Array for other depths'].
  13236.     depth _ d!
  13237. size
  13238.     depth = 16 ifTrue: [^ 32768].
  13239.     depth = 32 ifTrue: [^ 256*256*256].    "really 24 bit"
  13240.     ^ 0! !StandardSystemView subclass: #ColorSystemView
  13241.     instanceVariableNames: ''
  13242.     classVariableNames: ''
  13243.     poolDictionaries: ''
  13244.     category: 'Interface-Support'!
  13245.  
  13246. !ColorSystemView methodsFor: 'as yet unclassified'!
  13247. cacheBitsAsTwoTone
  13248.     ^ false! !ByteArray variableByteSubclass: #CompiledMethod
  13249.     instanceVariableNames: ''
  13250.     classVariableNames: 'LargeFrame TempNameCache SpecialConstants SmallFrame '
  13251.     poolDictionaries: ''
  13252.     category: 'Kernel-Methods'!
  13253. CompiledMethod comment:
  13254. 'I represent a method suitable for interpretation by the virtual machine. My instances have pointer fields, including a header and some literals, followed by non-pointer fields comprising the byte encoded instructions for the method. The header encodes the number of arguments, the number of literals, and the amount of temporary space needed (for context allocation).
  13255.     
  13256. An extra three bytes are added after the executable code. These contain an external file address to the source code for the method.'!
  13257.  
  13258. !CompiledMethod methodsFor: 'initialize-release'!
  13259. needsFrameSize: newFrameSize
  13260.     "Set the largeFrameBit to accomodate the newFrameSize.
  13261.     NOTE: I think the >= below is overly cautious.
  13262.     Recompile the system with just > some day - DI 2/26/96"
  13263.     | largeFrameBit header |
  13264.     largeFrameBit _ 16r20000.
  13265.     (self numTemps + newFrameSize) >= LargeFrame
  13266.         ifTrue: [^self error: 'Cannot compile--stack including temps is too deep'].
  13267.     header _ self objectAt: 1.
  13268.     (header bitAnd: largeFrameBit) ~= 0
  13269.         ifTrue: [header _ header - largeFrameBit].
  13270.     self objectAt: 1 put: header
  13271.             + ((self numTemps + newFrameSize) >= SmallFrame
  13272.                     ifTrue: [largeFrameBit]
  13273.                     ifFalse: [0])! !
  13274.  
  13275. !CompiledMethod methodsFor: 'accessing'!
  13276. bePrimitive: primitiveIndex 
  13277.     "Used in conjunction with simulator only"
  13278.     self objectAt: 1
  13279.         put: ((self objectAt: 1) bitAnd: 16rFFFFFE00) + primitiveIndex!
  13280. endPC
  13281.     "Answer the index of the last bytecode."
  13282.  
  13283.     (self last between: 120 and: 124) ifTrue: [^self size].
  13284.     ^self size - 3!
  13285. frameSize
  13286.     "Answer the size of temporary frame needed to run the receiver."
  13287.  
  13288.     (self header noMask: 16r20000)
  13289.         ifTrue: [^ SmallFrame]
  13290.         ifFalse: [^ LargeFrame]!
  13291. initialPC
  13292.     "Answer the program counter for the receiver's first bytecode."
  13293.  
  13294.     ^ (self numLiterals + 1) * 4 + 1!
  13295. numArgs
  13296.     "Answer the number of arguments the receiver takes."
  13297.  
  13298.     ^ (self header bitShift: -24) bitAnd: 16r1F!
  13299. numLiterals
  13300.     "Answer the number of literals used by the receiver."
  13301.     
  13302.     ^ (self header bitShift: -9) bitAnd: 16rFF!
  13303. numTemps
  13304.     "Answer the number of temporary variables used by the receiver."
  13305.     
  13306.     ^ (self header bitShift: -18) bitAnd: 16r3F!
  13307. primitive
  13308.     "Answer the primitive index associated with the receiver. Zero indicates 
  13309.     that there is either no primitive or just a quick primitive."
  13310.     
  13311.     ^ self header bitAnd: 16r1FF!
  13312. returnField
  13313.     "Answer the index of the instance variable returned by a quick return 
  13314.     method."
  13315.     | prim |
  13316.     prim _ self primitive.
  13317.     prim < 264
  13318.         ifTrue: [self error: 'only meaningful for quick-return']
  13319.         ifFalse: [^ prim - 264]! !
  13320.  
  13321. !CompiledMethod methodsFor: 'comparing'!
  13322. = method
  13323.     "Answer whether the receiver implements the same code as the 
  13324.     argument, method."
  13325.     (method isKindOf: CompiledMethod) ifFalse: [^false].
  13326.     self size = method size ifFalse: [^false].
  13327.     self header = method header ifFalse: [^false].
  13328.     self literals = method literals ifFalse: [^false].
  13329.     self initialPC to: self endPC do:
  13330.         [:i | (self at: i) = (method at: i) ifFalse: [^false]].
  13331.     ^true! !
  13332.  
  13333. !CompiledMethod methodsFor: 'testing'!
  13334. isQuick
  13335.     "Answer whether the receiver is a quick return (of self or of an instance 
  13336.     variable)."
  13337.     ^ self primitive >= 256!
  13338. isReturnField
  13339.     "Answer whether the receiver is a quick return of an instance variable."
  13340.     ^ self primitive >= 264!
  13341. isReturnSelf
  13342.     "Answer whether the receiver is a quick return of self."
  13343.  
  13344.     ^ self primitive = 256!
  13345. isReturnSpecial
  13346.     "Answer whether the receiver is a quick return of self or constant."
  13347.  
  13348.     ^ self primitive between: 256 and: 263! !
  13349.  
  13350. !CompiledMethod methodsFor: 'printing'!
  13351. decompileString
  13352.     | clAndSel cl sel |
  13353.     clAndSel _ self who.
  13354.     cl _ clAndSel first.
  13355.     sel _ clAndSel last.
  13356.     ^ (cl decompilerClass new
  13357.             decompile: sel in: cl method: self) decompileString!
  13358. printOn: aStream 
  13359.     "Overrides method inherited from the byte arrayed collection."
  13360.  
  13361.     aStream nextPutAll: 'a CompiledMethod'!
  13362. storeLiteralsOn: aStream forClass: aBehavior
  13363.     "Store the literals referenced by the receiver on aStream, each terminated by a space."
  13364.  
  13365.     | literal |
  13366.     2 to: self numLiterals + 1 do:
  13367.         [:index |
  13368.          aBehavior storeLiteral: (self objectAt: index) on: aStream.
  13369.          aStream space]!
  13370. storeOn: aStream
  13371.  
  13372.     | noneYet index |
  13373.     aStream nextPutAll: '(('.
  13374.     aStream nextPutAll: self class name.
  13375.     aStream nextPutAll: ' newMethod: '.
  13376.     aStream store: self size - self initialPC + 1.
  13377.     aStream nextPutAll: ' header: '.
  13378.     aStream store: self header.
  13379.     aStream nextPut: $).
  13380.     noneYet _ self storeElementsFrom: self initialPC to: self endPC on: aStream.
  13381.     1 to: self numLiterals do:
  13382.         [:index |
  13383.         noneYet
  13384.             ifTrue: [noneYet _ false]
  13385.             ifFalse: [aStream nextPut: $;].
  13386.         aStream nextPutAll: ' literalAt: '.
  13387.         aStream store: index.
  13388.         aStream nextPutAll: ' put: '.
  13389.         aStream store: (self literalAt: index)].
  13390.     noneYet ifFalse: [aStream nextPutAll: '; yourself'].
  13391.     aStream nextPut: $)!
  13392. symbolic
  13393.     "Answer a String that contains a list of all the byte codes in a method 
  13394.     with a short description of each." 
  13395.     | aStream |
  13396.     self isQuick ifTrue: 
  13397.         [self isReturnSpecial ifTrue: [^ 'Quick return ' ,
  13398.                 (#('self' 'true' 'false' 'nil' '-1' '0' '1' '2')
  13399.                         at: self primitive - 255)].
  13400.         ^ 'Quick return field ' , self returnField printString , ' (0-based)'].
  13401.     aStream _ WriteStream on: (String new: 1000).
  13402.     self primitive > 0 
  13403.         ifTrue: 
  13404.             [aStream nextPutAll: '<primitive: '.
  13405.             aStream print: self primitive.
  13406.             aStream nextPut: $>.
  13407.             aStream cr].
  13408.     (InstructionPrinter on: self) printInstructionsOn: aStream.
  13409.     ^aStream contents!
  13410. who 
  13411.     "Answer an Array of the class in which the receiver is defined and the 
  13412.     selector to which it corresponds."
  13413.  
  13414.     Smalltalk allBehaviorsDo:
  13415.         [:class |
  13416.         class selectorsDo:
  13417.             [:sel |
  13418.             (class compiledMethodAt: sel) == self 
  13419.                 ifTrue: [^Array with: class with: sel]]]! !
  13420.  
  13421. !CompiledMethod methodsFor: 'literals'!
  13422. hasLiteral: literal 
  13423.     "Answer whether the receiver references the argument, literal."
  13424.     2 to: self numLiterals + 1 do:
  13425.         [:index |
  13426.         literal == (self objectAt: index) ifTrue: [^ true]].
  13427.     ^false!
  13428. header
  13429.     "Answer the word containing the information about the form of the 
  13430.     receiver and the form of the context needed to run the receiver."
  13431.  
  13432.     ^self objectAt: 1!
  13433. literalAt: index 
  13434.     "Answer the literal indexed by the argument."
  13435.  
  13436.     ^self objectAt: index + 1!
  13437. literalAt: index put: value 
  13438.     "Replace the literal indexed by the first argument with the second 
  13439.     argument. Answer the second argument."
  13440.  
  13441.     ^self objectAt: index + 1 put: value!
  13442. literals
  13443.     "Answer an Array of the literals referenced by the receiver."
  13444.     | literals numberLiterals |
  13445.     literals _ Array new: (numberLiterals _ self numLiterals).
  13446.     1 to: numberLiterals do:
  13447.         [:index |
  13448.         literals at: index put: (self objectAt: index + 1)].
  13449.     ^literals!
  13450. literalStrings
  13451.     | lits litStrs |
  13452.     lits _ self literals.
  13453.     litStrs _ OrderedCollection new: lits size * 3.
  13454.     self literals do:
  13455.         [:lit | 
  13456.         (lit isMemberOf: Association)
  13457.             ifTrue: [litStrs addLast: lit key]
  13458.             ifFalse: [(lit isMemberOf: Symbol)
  13459.                 ifTrue: [litStrs addAll: lit keywords]
  13460.                 ifFalse: [litStrs addLast: lit printString]]].
  13461.     ^ litStrs!
  13462. objectAt: index 
  13463.     "Primitive. Answer the method header (if index=1) or a literal (if index 
  13464.     >1) from the receiver. Essential. See Object documentation 
  13465.     whatIsAPrimitive."
  13466.  
  13467.     <primitive: 68>
  13468.     self primitiveFailed!
  13469. objectAt: index put: value 
  13470.     "Primitive. Store the value argument into a literal in the receiver. An 
  13471.     index of 2 corresponds to the first literal. Fails if the index is less than 2 
  13472.     or greater than the number of literals. Answer the value as the result. 
  13473.     Normally only the compiler sends this message, because only the 
  13474.     compiler stores values in CompiledMethods. Essential. See Object 
  13475.     documentation whatIsAPrimitive."
  13476.  
  13477.     <primitive: 69>
  13478.     self primitiveFailed! !
  13479.  
  13480. !CompiledMethod methodsFor: 'scanning'!
  13481. messages
  13482.     "Answer a Set of all the message selectors sent by this method."
  13483.  
  13484.     | scanner aSet |
  13485.     aSet _ Set new.
  13486.     scanner _ InstructionStream on: self.
  13487.     scanner    
  13488.         scanFor: 
  13489.             [:x | 
  13490.             scanner addSelectorTo: aSet.
  13491.             false    "keep scanning"].
  13492.     ^aSet!
  13493. readsField: varIndex 
  13494.     "Answer whether the receiver loads the instance variable indexed by the 
  13495.     argument."
  13496.  
  13497.     self isReturnField ifTrue: [^self returnField + 1 = varIndex].
  13498.     varIndex <= 16 ifTrue: [^self scanFor: varIndex - 1].
  13499.     ^self scanLongLoad: varIndex - 1!
  13500. readsRef: literalAssociation 
  13501.     "Answer whether the receiver loads the argument."
  13502.  
  13503.     | lit |
  13504.     lit _ self literals indexOf: literalAssociation ifAbsent: [^false].
  13505.     lit <= 32 ifTrue: [^self scanFor: 64 + lit - 1].
  13506.     ^self scanLongLoad: 192 + lit - 1!
  13507. scanFor: byte 
  13508.     "Answer whether the receiver contains the argument as a bytecode."
  13509.     | instr |
  13510.     ^ (InstructionStream on: self) scanFor: [:instr | instr = byte]
  13511. "
  13512. Smalltalk browseAllSelect: [:m | m scanFor: 134]
  13513. "!
  13514. scanLongLoad: extension 
  13515.     "Answer whether the receiver contains a long load whose extension is the 
  13516.     argument."
  13517.  
  13518.     | scanner |
  13519.     scanner _ InstructionStream on: self.
  13520.     ^scanner scanFor: [:instr | instr = 128 and: [scanner followingByte = extension]]!
  13521. scanLongStore: extension 
  13522.     "Answer whether the receiver contains a long store whose extension is 
  13523.     the argument."
  13524.  
  13525.     | scanner |
  13526.     scanner _ InstructionStream on: self.
  13527.     ^scanner scanFor: 
  13528.         [:instr | 
  13529.         (instr between: 129 and: 130) and: [scanner followingByte = extension]]!
  13530. sendsToSuper
  13531.     "Answer whether the receiver sends any message to super."
  13532.  
  13533.     ^ (self scanFor: 16r85) or: [self scanFor: 16r86]!
  13534. writesField: field 
  13535.     "Answer whether the receiver stores into the instance variable indexed 
  13536.     by the argument."
  13537.  
  13538.     self isQuick ifTrue: [^false].
  13539.     (field <= 8 and: [self scanFor: 96 + field - 1])
  13540.         ifTrue: [^true]
  13541.         ifFalse: [^self scanLongStore: field - 1]!
  13542. writesRef: ref 
  13543.     "Answer whether the receiver stores the argument."
  13544.  
  13545.     | lit |
  13546.     lit _ self literals indexOf: ref ifAbsent: [^false].
  13547.     ^self scanLongStore: 192 + lit - 1! !
  13548.  
  13549. !CompiledMethod methodsFor: 'source code management'!
  13550. cacheTempNames: names
  13551.  
  13552.     TempNameCache _ Association key: self value: names!
  13553. copySourceTo: aFileStream
  13554.     "Copy the source code for the receiver to aFileStream. Answer true if there are no 
  13555.     problems, false if no files specified in the global SourceFiles or position is zero."
  13556.     | position |
  13557.     (SourceFiles at: self fileIndex) == nil ifTrue: [^false].
  13558.     Cursor read
  13559.         showWhile: 
  13560.             [position _ self filePosition.
  13561.             position ~= 0
  13562.                 ifTrue: [(SourceFiles at: self fileIndex) position: position;
  13563.                             copyChunkTo: aFileStream]].
  13564.     ^position ~= 0!
  13565. fileIndex
  13566.     "Answer 1 if the source code of the receiver is on the *.sources file and 2 
  13567.     if it is on the *.changes file."
  13568.  
  13569.     (self last between: 120 and: 124)
  13570.         ifTrue: [self error: 'Somehow a method does not have a file index.'].
  13571.     ^self last // 64 + 1!
  13572. filePosition
  13573.     "Answer the file position of this method's source code."
  13574.     | end |
  13575.     end _ self size.
  13576.     ^ ((self at: end) bitAnd: 63) * 256 + (self at: end - 1) * 256 + (self at: end - 2)!
  13577. getSource
  13578.     "Answer the source code for the receiver. Answer nil if there are no 
  13579.     source files specified in the global SourceFiles."
  13580.     | source position |
  13581.     (SourceFiles at: self fileIndex) == nil ifTrue: [^nil].
  13582.     Cursor read
  13583.         showWhile: 
  13584.             [position _ self filePosition.
  13585.             position = 0
  13586.                 ifTrue: [source _ nil]
  13587.                 ifFalse: [source _ (RemoteString newFileNumber: self fileIndex
  13588.                                                 position: position) string]].
  13589.     ^source!
  13590. putSource: sourceStr class: class category: catName
  13591.     inFile: fileIndex priorMethod: priorMethod 
  13592.     "Print an expression that is a message to the argument, class, asking the 
  13593.     class to accept the source code, sourceStr, as a method in category, 
  13594.     catName. This is part of the format for writing descriptions of methods 
  13595.     on files. If no sources are specified, i.e., SourceFile iEs nil, then do 
  13596.     nothing. If the fileIndex is 1, print on *.sources; if it is 2, print on 
  13597.     *.canges.  If priorMethod is not nil, then link this source to the prior
  13598.     method and supply the time and date for this definition."
  13599.     | file remoteString |
  13600.     file _ SourceFiles at: fileIndex.
  13601.     file == nil ifTrue: [^self].
  13602.     file setToEnd.
  13603.     class printCategoryChunk: catName on: file priorMethod: priorMethod.
  13604.     file cr.
  13605.     remoteString _ 
  13606.         RemoteString
  13607.             newString: sourceStr
  13608.             onFileNumber: fileIndex
  13609.             toFile: file.
  13610.     file nextChunkPut: ' '; flush.
  13611.     self setSourcePosition: remoteString position inFile: fileIndex!
  13612. putSource: sourceStr inFile: fileIndex 
  13613.     "Store the source code for the receiver on an external file.
  13614.     If no sources are specified, i.e., SourceFile is nil, then do nothing.
  13615.     If the fileIndex is 1, print on *.sources;  if it is 2, print on *.changes."
  13616.  
  13617.     | file remoteString |
  13618.     file _ SourceFiles at: fileIndex.
  13619.     file == nil ifTrue: [^self].
  13620.     file setToEnd; readWriteShorten.
  13621.     file cr; nextPut: $!!; nextChunkPut: 'Behavior method'; cr.
  13622.     remoteString _ 
  13623.         RemoteString
  13624.             newString: sourceStr
  13625.             onFileNumber: fileIndex
  13626.             toFile: file.
  13627.     file nextChunkPut: ' '; readOnly.
  13628.     self setSourcePosition: remoteString position inFile: fileIndex!
  13629. setSourcePosition: position inFile: fileIndex 
  13630.     "Store the location of the source code for the receiver in the receiver. The 
  13631.     location consists of which source file (*.sources or *.changes) and the 
  13632.     position in that file."
  13633.  
  13634.     | index hiByte middleByte lowByte |
  13635.     "set last three bytes to be position in file (1-4)"
  13636.     fileIndex > 4 ifTrue: [^self error: 'invalid file number'].
  13637.     index _ self size - 2.
  13638.     middleByte _ position bitShift: -8.
  13639.     hiByte _ middleByte bitShift: -8.
  13640.     middleByte _ middleByte bitAnd: 255.
  13641.     lowByte _ position bitAnd: 255.
  13642.     hiByte > 62 ifTrue: [Transcript show: 'Source file is getting full!!!!'; cr].
  13643.     self at: index + 2 put: fileIndex - 1 * 64 + hiByte.
  13644.     self at: index + 1 put: middleByte.
  13645.     self at: index put: lowByte!
  13646. setTempNamesIfCached: aBlock
  13647.  
  13648.     TempNameCache == nil ifTrue: [^self].
  13649.     TempNameCache key == self
  13650.         ifTrue: [aBlock value: TempNameCache value]! !
  13651. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  13652.  
  13653. CompiledMethod class
  13654.     instanceVariableNames: ''!
  13655.  
  13656. !CompiledMethod class methodsFor: 'class initialization'!
  13657. initialize
  13658.     "Initialize class variables specifying the size of the temporary frame
  13659.     needed to run instances of me."
  13660.  
  13661.     SmallFrame _ 12.    "Context range for temps+stack"
  13662.     LargeFrame _ 32
  13663.  
  13664.     "CompiledMethod initialize"! !
  13665.  
  13666. !CompiledMethod class methodsFor: 'instance creation'!
  13667. newBytes: numberOfBytes nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex
  13668.     "Answer an instance of me. The header is specified by the message 
  13669.     arguments. The remaining parts are not as yet determined."
  13670.     | largeBit |
  13671.     largeBit _ (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0].
  13672.     ^ self 
  13673.         newMethod: numberOfBytes + 3     "+3 to store source code ptr" 
  13674.         header: (nArgs bitShift: 24) +
  13675.                 (nTemps bitShift: 18) +
  13676.                 (largeBit bitShift: 17) +
  13677.                 (nLits bitShift: 9) +
  13678.                 primitiveIndex!
  13679. newMethod: numberOfBytes header: headerWord 
  13680.     "Primitive. Answer an instance of me. The number of literals (and other 
  13681.     information) is specified the headerWord. The first argument specifies 
  13682.     the number of fields for bytecodes in the method. Fail if either 
  13683.     argument is not a SmallInteger, or if numberOfBytes is negative. Once 
  13684.     the header of a method is set by this primitive, it cannot be changed in 
  13685.     any way. Essential. See Object documentation whatIsAPrimitive."
  13686.  
  13687.     <primitive: 79>
  13688.     (numberOfBytes isInteger and:
  13689.      [headerWord isInteger and:
  13690.      [numberOfBytes >= 0]]) ifTrue: [
  13691.         "args okay; space must be low"
  13692.         Smalltalk signalLowSpace.
  13693.         "retry if user proceeds"
  13694.         ^ self newMethod: numberOfBytes header: headerWord
  13695.     ].
  13696.     ^self primitiveFailed!
  13697. toReturnConst: constCode
  13698.     "Answer an instance of me that is a quick return of a constant
  13699.     constCode = 1...7  ->  true, false, nil, -1, 0, 1, 2."
  13700.  
  13701.     ^ self newBytes: 0 nArgs: 0 nTemps: 0 nStack: 0 nLits: 0 primitive: 256 + constCode!
  13702. toReturnConstant: index 
  13703.     "Answer an instance of me that is a quick return of the constant
  13704.     indexed in (true false nil -1 0 1 2)."
  13705.  
  13706.     ^ self newBytes: 0 nArgs: 0 nTemps: 0 nStack: 0 nLits: 0 primitive: 256 + index
  13707. !
  13708. toReturnField: field 
  13709.     "Answer an instance of me that is a quick return of the instance variable 
  13710.     indexed by the argument, field."
  13711.  
  13712.     ^ self newBytes: 0 nArgs: 0 nTemps: 0 nStack: 0 nLits: 0 primitive: 264 + field
  13713. !
  13714. toReturnSelf
  13715.     "Answer an instance of me that is a quick return of the instance (^self)."
  13716.  
  13717.     ^ self newBytes: 0 nArgs: 0 nTemps: 0 nStack: 0 nLits: 0 primitive: 256
  13718. ! !
  13719.  
  13720. CompiledMethod initialize!
  13721. Object subclass: #Compiler
  13722.     instanceVariableNames: 'sourceStream requestor class context '
  13723.     classVariableNames: ''
  13724.     poolDictionaries: ''
  13725.     category: 'System-Compiler'!
  13726. Compiler comment:
  13727. 'The compiler accepts Smalltalk source code and compiles it with respect to a given class. The user of the compiler supplies a context so that temporary variables are accessible during compilation. If there is an error, a requestor (usually a kind of StringHolderController) is sent the message notify:at:in: so that the error message can be displayed. If there is no error, then the result of compilation is a MethodNode, which is the root of a parse tree whose nodes are kinds of ParseNodes. The parse tree can be sent messages to (1) generate code for a CompiledMethod (this is done for compiling methods or evaluating expressions); (2) pretty-print the code (for formatting); or (3) produce a map from object code back to source code (used by debugger program-counter selection). See also Parser, Encoder, ParseNode.'!
  13728.  
  13729. !Compiler methodsFor: 'error handling'!
  13730. interactive 
  13731.     "Answer whether there is a requestor of the compiler who should be 
  13732.     informed that an error occurred."
  13733.  
  13734.     ^ (requestor == nil or: [requestor isKindOf: SyntaxError]) not!
  13735. notify: aString 
  13736.     "Refer to the comment in Object|notify:."
  13737.  
  13738.     ^self notify: aString at: sourceStream position + 1!
  13739. notify: aString at: location
  13740.     "Refer to the comment in Object|notify:."
  13741.  
  13742.     requestor == nil
  13743.         ifTrue: [^SyntaxError 
  13744.                     errorInClass: class
  13745.                     withCode: 
  13746.                         (sourceStream contents
  13747.                             copyReplaceFrom: location
  13748.                             to: location - 1
  13749.                             with: aString)]
  13750.         ifFalse: [^requestor
  13751.                     notify: aString
  13752.                     at: location
  13753.                     in: sourceStream]! !
  13754.  
  13755. !Compiler methodsFor: 'public access'!
  13756. compile: textOrStream in: aClass notifying: aRequestor ifFail: failBlock 
  13757.     "Answer a MethodNode for the argument, textOrStream. If the 
  13758.     MethodNode can not be created, notify the argument, aRequestor; if 
  13759.     aRequestor is nil, evaluate failBlock instead. The MethodNode is the root 
  13760.     of a parse tree. It can be told to generate a CompiledMethod to be 
  13761.     installed in the method dictionary of the argument, aClass."
  13762.  
  13763.     self from: textOrStream
  13764.         class: aClass
  13765.         context: nil
  13766.         notifying: aRequestor.
  13767.     ^self
  13768.         translate: sourceStream
  13769.         noPattern: false
  13770.         ifFail: failBlock!
  13771. evaluate: textOrStream in: aContext to: receiver notifying: aRequestor ifFail: failBlock
  13772.     "Compiles the sourceStream into a parse tree, then generates code into a 
  13773.     method. This method is then installed in the receiver's class so that it 
  13774.     can be invoked. In other words, if receiver is not nil, then the text can 
  13775.     refer to instance variables of that receiver (the Inspector uses this). If 
  13776.     aContext is not nil, the text can refer to temporaries in that context (the 
  13777.     Debugger uses this). If aRequestor is not nil, then it will receive a 
  13778.     notify:at: message before the attempt to evaluate is aborted. Finally, the 
  13779.     compiled method is invoked from here as DoIt or (in the case of 
  13780.     evaluation in aContext) DoItIn:. The method is subsequently removed 
  13781.     from the class, but this will not get done if the invocation causes an 
  13782.     error which is terminated. Such garbage can be removed by executing: 
  13783.     Smalltalk allBehaviorsDo: [:cl | cl removeSelector: #DoIt; removeSelector: 
  13784.     #DoItIn:]."
  13785.  
  13786.     | methodNode method value |
  13787.     class _ (aContext == nil ifTrue: [receiver] ifFalse: [aContext receiver]) class.
  13788.     self from: textOrStream class: class context: aContext notifying: aRequestor.
  13789.     methodNode _ self translate: sourceStream noPattern: true ifFail:
  13790.         [^failBlock value].
  13791.     method _ methodNode generate: #(0 0 0).
  13792.     context == nil
  13793.         ifTrue: [class addSelector: #DoIt withMethod: method.
  13794.                 value _ receiver DoIt.
  13795.                 class removeSelectorSimply: #DoIt.
  13796.                 ^value]
  13797.         ifFalse: [class addSelector: #DoItIn: withMethod: method.
  13798.                 value _ receiver DoItIn: context.
  13799.                 class removeSelectorSimply: #DoItIn:.
  13800.                 ^value]!
  13801. format: textOrStream in: aClass notifying: aRequestor
  13802.     "Compile a parse tree from the argument, textOrStream. Answer a string 
  13803.     containing the original code, formatted nicely."
  13804.  
  13805.     | aNode |
  13806.     self from: textOrStream
  13807.         class: aClass
  13808.         context: nil
  13809.         notifying: aRequestor.
  13810.     aNode _ self format: sourceStream noPattern: false ifFail: [^nil].
  13811.     ^aNode decompileString!
  13812. parse: textOrStream in: aClass notifying: req
  13813.     "Compile the argument, textOrStream, with respect to the class, aClass, 
  13814.     and answer the MethodNode that is the root of the resulting parse tree. 
  13815.     Notify the argument, req, if an error occurs. The failBlock is defaulted to 
  13816.     an empty block."
  13817.  
  13818.     self from: textOrStream class: aClass context: nil notifying: req.
  13819.     ^self translate: sourceStream noPattern: false ifFail: []! !
  13820.  
  13821. !Compiler methodsFor: 'private'!
  13822. format: aStream noPattern: noPattern ifFail: failBlock
  13823.  
  13824.     | tree |
  13825.     tree _ 
  13826.         Parser new
  13827.             parse: aStream
  13828.             class: class
  13829.             noPattern: noPattern
  13830.             context: context
  13831.             notifying: requestor
  13832.             ifFail: [^failBlock value].
  13833.     ^tree!
  13834. from: textOrStream class: aClass context: aContext notifying: req
  13835.  
  13836.     (textOrStream isKindOf: PositionableStream)
  13837.         ifTrue: [sourceStream _ textOrStream]
  13838.         ifFalse: [sourceStream _ ReadStream on: textOrStream asString].
  13839.     class _ aClass.
  13840.     context _ aContext.
  13841.     requestor _ req!
  13842. translate: aStream noPattern: noPattern ifFail: failBlock
  13843.  
  13844.     | tree |
  13845.     tree _ 
  13846.         Parser new
  13847.             parse: aStream
  13848.             class: class
  13849.             noPattern: noPattern
  13850.             context: context
  13851.             notifying: requestor
  13852.             ifFail: [^failBlock value].
  13853.     ^tree!
  13854. translate: aStream withLocals: localDict noPattern: noPattern ifFail: failBlock
  13855.  
  13856.     | tree |
  13857.     tree _ 
  13858.         Parser new
  13859.             parse: aStream
  13860.             class: class
  13861.             noPattern: noPattern
  13862.             locals: localDict
  13863.             notifying: requestor
  13864.             ifFail: [^failBlock value].
  13865.     ^tree! !
  13866. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  13867.  
  13868. Compiler class
  13869.     instanceVariableNames: ''!
  13870.  
  13871. !Compiler class methodsFor: 'accessing'!
  13872. parserClass
  13873.     "Return a parser class to use for parsing method headers."
  13874.  
  13875.     ^Parser! !
  13876.  
  13877. !Compiler class methodsFor: 'evaluating'!
  13878. evaluate: textOrString 
  13879.     "See Compiler|evaluate:for:notifying:logged:. If a compilation error occurs, 
  13880.     a Syntax Error view is created rather than notifying any requestor. 
  13881.     Compilation is carried out with respect to nil, i.e., no object, and the 
  13882.     invocation is not logged."
  13883.  
  13884.     ^self evaluate: textOrString for: nil logged: false!
  13885. evaluate: textOrString for: anObject logged: logFlag 
  13886.     "See Compiler|evaluate:for:notifying:logged:. If a compilation error occurs, 
  13887.     a Syntax Error view is created rather than notifying any requestor."
  13888.  
  13889.     ^self evaluate: textOrString for: anObject notifying: nil logged: logFlag!
  13890. evaluate: textOrString for: anObject notifying: aController logged: logFlag
  13891.     "Compile and execute the argument, textOrString with respect to the class 
  13892.     of anObject. If a compilation error occurs, notify aController. If both 
  13893.     compilation and execution are successful then, if logFlag is true, log 
  13894.     (write) the text onto a system changes file so that it can be replayed if 
  13895.     necessary."
  13896.  
  13897.     | val |
  13898.     val _ self new
  13899.                 evaluate: textOrString
  13900.                 in: nil
  13901.                 to: anObject
  13902.                 notifying: aController
  13903.                 ifFail: [^nil].
  13904.     logFlag ifTrue: [Smalltalk logChange: textOrString].
  13905.     ^val!
  13906. evaluate: textOrString logged: logFlag 
  13907.     "See Compiler|evaluate:for:notifying:logged:. If a compilation error occurs, 
  13908.     a Syntax Error view is created rather than notifying any requestor. 
  13909.     Compilation is carried out with respect to nil, i.e., no object."
  13910.  
  13911.     ^self evaluate: textOrString for: nil logged: logFlag!
  13912. evaluate: textOrString notifying: aController logged: logFlag 
  13913.     "See Compiler|evaluate:for:notifying:logged:. Compilation is carried out 
  13914.     with respect to nil, i.e., no object."
  13915.  
  13916.     ^self evaluate: textOrString for: nil notifying: aController logged: logFlag! !CharacterScanner subclass: #CompositionScanner
  13917.     instanceVariableNames: 'spaceX spaceIndex '
  13918.     classVariableNames: ''
  13919.     poolDictionaries: 'TextConstants '
  13920.     category: 'Graphics-Support'!
  13921. CompositionScanner comment:
  13922. 'CompositionScanners are used to measure text and determine where line breaks and space padding should occur.'!
  13923.  
  13924. !CompositionScanner methodsFor: 'initialize-release'!
  13925. in: aParagraph 
  13926.     "Initialize the paragraph to be scanned as the argument, aParagraph. Set 
  13927.     the composition frame for the paragraph."
  13928.  
  13929.     super initializeFromParagraph: aParagraph clippedBy: aParagraph clippingRectangle! !
  13930.  
  13931. !CompositionScanner methodsFor: 'accessing'!
  13932. rightX
  13933.     "Meaningful only when a line has just been composed -- refers to the 
  13934.     line most recently composed. This is a subtrefuge to allow for easy 
  13935.     resizing of a composition rectangle to the width of the maximum line. 
  13936.     Useful only when there is only one line in the form or when each line 
  13937.     is terminated by a carriage return. Handy for sizing menus and lists."
  13938.  
  13939.     ^spaceX! !
  13940.  
  13941. !CompositionScanner methodsFor: 'scanning'!
  13942. composeLine: lineIndex fromCharacterIndex: startIndex inParagraph: aParagraph 
  13943.     "Answer an instance of TextLineInterval that represents the next line in the paragraph. "
  13944.     
  13945.     | runLengtrh done stopCondition |
  13946.     spaceX _ destX _ leftMargin _ aParagraph leftMarginForCompositionForLine: lineIndex.
  13947.     destY _ 0.
  13948.     rightMargin _ aParagraph rightMarginForComposition.
  13949.     leftMargin >= rightMargin ifTrue: [self error: 'No room between margins to compose'].
  13950.     lastIndex _ startIndex.    "scanning sets last index"
  13951.     self setStopConditions.    "also sets font"
  13952.     runLengtrh _ text runLengthFor: startIndex.
  13953.     runStopIndex _ (lastIndex _ startIndex) + (runLengtrh - 1).
  13954.     line _ TextLineInterval
  13955.         start: lastIndex
  13956.         stop: 0
  13957.         internalSpaces: 0
  13958.         paddingWidth: 0.
  13959.     spaceCount _ 0.
  13960.     done _ false.
  13961.     [done]
  13962.         whileFalse: 
  13963.             [stopCondition _ super
  13964.                 scanCharactersFrom: lastIndex
  13965.                 to: runStopIndex
  13966.                 in: text string
  13967.                 rightX: rightMargin
  13968.                 stopConditions: stopConditions
  13969.                 displaying: false.
  13970.             "See setStopConditions for stopping conditions for composing."
  13971.             (self perform: stopCondition)
  13972.                 ifTrue: [^line]]! !
  13973.  
  13974. !CompositionScanner methodsFor: 'stop conditions'!
  13975. cr
  13976.     "Answer true. Set up values for the text line interval currently being 
  13977.     composed."
  13978.  
  13979.     line stop: lastIndex.
  13980.     spaceX _ destX.
  13981.     line paddingWidth: rightMargin - destX.
  13982.     ^true!
  13983. crossedX
  13984.     "There is a word that has fallen across the right edge of the composition 
  13985.     rectangle. This signals the need for wrapping which is done to the last 
  13986.     space that was encountered, as recorded by the space stop condition."
  13987.  
  13988.     line stop: spaceIndex.
  13989.     spaceCount > 1    
  13990.         ifTrue:    ["The common case. First back off the space at which we wrap."
  13991.                 spaceCount _ spaceCount - 1.
  13992.                 spaceIndex _ spaceIndex - 1.
  13993.                 ["Check to see if any spaces preceding the one at which we wrap.
  13994.                     Double space after a period, most likely."
  13995.                 (spaceCount > 1 and: [(text at: spaceIndex) = Space])]
  13996.                     whileTrue:
  13997.                         [spaceCount _ spaceCount - 1.
  13998.                         "Account for backing over a run which might
  13999.                             change width of space."
  14000.                         font _ textStyle fontAt:
  14001.                                 (text emphasisAt: spaceIndex).
  14002.                         spaceIndex _ spaceIndex - 1.
  14003.                         spaceX _ spaceX - (font widthOf: Space)].
  14004.                         line paddingWidth: rightMargin - spaceX.
  14005.                         line internalSpaces: spaceCount]
  14006.         ifFalse:    [spaceCount = 1
  14007.                     ifTrue:    ["wrap at space, but no internal spaces"
  14008.                             line internalSpaces: 0.
  14009.                             line paddingWidth: rightMargin - spaceX]
  14010.                     ifFalse:    ["Neither internal nor trailing spaces, almost never happen,
  14011.                                 she says confidently."
  14012.                             lastIndex _ lastIndex - 1.
  14013.                             [destX <= rightMargin]
  14014.                             whileFalse:
  14015.                                 [destX _ destX - (font widthOf:
  14016.                                                     (text at: lastIndex)).
  14017.                                         "bug --doesn't account for backing over
  14018.                                          run and changing actual width of
  14019.                                         characters. Also doesn't account for
  14020.                                         backing over a tab.  Happens only
  14021.                                         when no spaces in line, presumably rare."
  14022.                                 lastIndex _ lastIndex - 1].
  14023.                             spaceX _ destX.
  14024.                             line paddingWidth: rightMargin - destX.
  14025.                             lastIndex < line first
  14026.                                 ifTrue:    [line stop: line first]
  14027.                                 ifFalse:    [line stop: lastIndex]]].
  14028.     ^true!
  14029. endOfRun
  14030.     "Answer true if scanning has reached the end of the paragraph. 
  14031.     Otherwise step conditions (mostly install potential new font) and answer 
  14032.     false."
  14033.  
  14034.     | runLength |
  14035.     lastIndex = text size
  14036.     ifTrue:    [line stop: lastIndex.
  14037.             spaceX _ destX.
  14038.             line paddingWidth: rightMargin - destX.
  14039.             ^true]
  14040.     ifFalse:    [runLength _ (text runLengthFor: (lastIndex _ lastIndex + 1)).
  14041.             runStopIndex _ lastIndex + (runLength - 1).
  14042.             self setStopConditions.
  14043.             ^false]
  14044. !
  14045. setStopConditions
  14046.     "Set the font and the stop conditions for the current run."
  14047.     
  14048.     self setFont!
  14049. space
  14050.     "Record left x and character index of the space character just encounted. 
  14051.     Used for wrap-around. Answer whether the character has crossed the 
  14052.     right edge of the composition rectangle of the paragraph."
  14053.  
  14054.     spaceX _ destX.
  14055.     destX _ spaceX + spaceWidth.
  14056.     lastIndex _ (spaceIndex _ lastIndex) + 1.
  14057.     spaceCount _ spaceCount + 1.
  14058.     destX > rightMargin ifTrue:     [^self crossedX].
  14059.     ^false
  14060. !
  14061. tab
  14062.     "Advance destination x according to tab settings in the paragraph's 
  14063.     textStyle. Answer whether the character has crossed the right edge of 
  14064.     the composition rectangle of the paragraph."
  14065.  
  14066.     destX _ textStyle
  14067.                 nextTabXFrom: destX leftMargin: leftMargin rightMargin: rightMargin.
  14068.     destX > rightMargin ifTrue:    [^self crossedX].
  14069.     lastIndex _ lastIndex + 1.
  14070.     ^false
  14071. ! !InstructionStream subclass: #ContextPart
  14072.     instanceVariableNames: 'stackp '
  14073.     classVariableNames: 'TryPrimitiveMethods TryPrimitiveSelectors '
  14074.     poolDictionaries: ''
  14075.     category: 'Kernel-Methods'!
  14076. ContextPart comment:
  14077. 'To the instruction parsing ability of InstructionStream I add the actual semantics for execution. The execution state is stored in the indexable fields of my subclasses. This includes temporary variables and a stack of values used in evaluating expressions. The actual semantics of execution can be found in my category "system simulation" and "instruction decode". These methods exactly parallel the operation of the Smalltalk machine itself.
  14078.     
  14079. The simulator is a group of my methods that do what the Smalltalk interpreter does: execute Smalltalk bytecodes. By adding code to the simulator, you may take statistics on the running of Smalltalk methods. For example,
  14080.     Transcript show: (ContextPart runSimulated: [3 factorial]) printString.'!
  14081.  
  14082. !ContextPart methodsFor: 'accessing'!
  14083. client
  14084.     "Answer the client, that is, the object that sent the message that created this context."
  14085.  
  14086.     ^sender receiver!
  14087. failureCatcher: exceptMethod
  14088.     "Answer a context in the sender chain that is executing BlockContext ifFail:
  14089.      Skip such that are matched by contexts above them executing
  14090.      exceptMethod.  Answer nil if none found.  Called only by Failure propagate."
  14091.  
  14092.     | stackFrame failureCatcher count |
  14093.     failureCatcher _ BlockContext compiledMethodAt: #ifFail:.
  14094.     stackFrame _ sender.
  14095.     count _ 1.
  14096.     [stackFrame ~~ nil and:
  14097.         [stackFrame method == failureCatcher ifTrue: [count _ count - 1].
  14098.          stackFrame method == exceptMethod ifTrue: [count _ count + 1].
  14099.          count > 0]] whileTrue:
  14100.             [stackFrame _ stackFrame sender].
  14101.     ^stackFrame!
  14102. home
  14103.     "Answer the context in which the receiver was defined."
  14104.  
  14105.     self subclassResponsibility!
  14106. method
  14107.     "Answer the method of this context."
  14108.  
  14109.     self subclassResponsibility!
  14110. receiver
  14111.     "Answer the receiver of the message that created this context."
  14112.  
  14113.     self subclassResponsibility!
  14114. tempAt: index
  14115.     "Answer the value of the temporary variable whose index is the 
  14116.     argument, index."
  14117.  
  14118.     self subclassResponsibility!
  14119. tempAt: index put: value 
  14120.     "Store the argument, value, as the temporary variable whose index is the 
  14121.     argument, index."
  14122.  
  14123.     self subclassResponsibility! !
  14124.  
  14125. !ContextPart methodsFor: 'instruction decoding'!
  14126. doDup
  14127.     "Simulate the action of a 'duplicate top of stack' bytecode."
  14128.  
  14129.     self push: self top!
  14130. doPop
  14131.     "Simulate the action of a 'remove top of stack' bytecode."
  14132.  
  14133.     self pop!
  14134. jump: distance 
  14135.     "Simulate the action of a 'unconditional jump' bytecode whose offset is 
  14136.     the argument, distance."
  14137.  
  14138.     pc _ pc + distance!
  14139. jump: distance if: condition 
  14140.     "Simulate the action of a 'conditional jump' bytecode whose offset is the 
  14141.     argument, distance, and whose condition is the argument, condition."
  14142.  
  14143.     (self pop eqv: condition) ifTrue: [self jump: distance]!
  14144. methodReturnConstant: value 
  14145.     "Simulate the action of a 'return constant' bytecode whose value is the 
  14146.     argument, value. This corresponds to a source expression like '^0'."
  14147.  
  14148.     ^self return: value to: self home sender!
  14149. methodReturnReceiver
  14150.     "Simulate the action of a 'return receiver' bytecode. This corresponds to 
  14151.     the source expression '^self'."
  14152.  
  14153.     ^self return: self receiver to: self home sender!
  14154. methodReturnTop
  14155.     "Simulate the action of a 'return top of stack' bytecode. This corresponds 
  14156.     to source expressions like '^something'."
  14157.  
  14158.     ^self return: self pop to: self home sender!
  14159. popIntoLiteralVariable: value 
  14160.     "Simulate the action of bytecode that removes the top of the stack and 
  14161.     stores it into a literal variable of my method."
  14162.  
  14163.     value value: self pop!
  14164. popIntoReceiverVariable: offset 
  14165.     "Simulate the action of bytecode that removes the top of the stack and 
  14166.     stores it into an instance variable of my receiver."
  14167.  
  14168.     self receiver instVarAt: offset + 1 put: self pop!
  14169. popIntoTemporaryVariable: offset 
  14170.     "Simulate the action of bytecode that removes the top of the stack and 
  14171.     stores it into one of my temporary variables."
  14172.  
  14173.     self home at: offset + 1 put: self pop!
  14174. pushActiveContext
  14175.     "Simulate the action of bytecode that pushes the the active context on the 
  14176.     top of its own stack."
  14177.  
  14178.     self push: self!
  14179. pushConstant: value 
  14180.     "Simulate the action of bytecode that pushes the constant, value, on the 
  14181.     top of the stack."
  14182.  
  14183.     self push: value!
  14184. pushLiteralVariable: value 
  14185.     "Simulate the action of bytecode that pushes the contents of the literal 
  14186.     variable whose index is the argument, index, on the top of the stack."
  14187.  
  14188.     self push: value value!
  14189. pushReceiver
  14190.     "Simulate the action of bytecode that pushes the active context's receiver 
  14191.     on the top of the stack."
  14192.  
  14193.     self push: self receiver!
  14194. pushReceiverVariable: offset 
  14195.     "Simulate the action of bytecode that pushes the contents of the receiver's 
  14196.     instance variable whose index is the argument, index, on the top of the 
  14197.     stack."
  14198.  
  14199.     self push: (self receiver instVarAt: offset + 1)!
  14200. pushTemporaryVariable: offset 
  14201.     "Simulate the action of bytecode that pushes the contents of the 
  14202.     temporary variable whose index is the argument, index, on the top of 
  14203.     the stack."
  14204.  
  14205.     self push: (self home at: offset + 1)!
  14206. send: selector super: superFlag numArgs: numArgs
  14207.     "Simulate the action of bytecodes that send a message with selector, 
  14208.     selector. The argument, superFlag, tells whether the receiver of the 
  14209.     message was specified with 'super' in the source method. The arguments 
  14210.     of the message are found in the top numArgs locations on the stack and 
  14211.     the receiver just below them."
  14212.  
  14213.     | receiver arguments |
  14214.     arguments _ Array new: numArgs.
  14215.     numArgs to: 1 by: -1 do: [ :i | arguments at: i put: self pop].
  14216.     receiver _ self pop.
  14217.     (selector == #halt or: [selector == #halt:]) ifTrue:
  14218.         [self error: 'Cant simulate halt.  Proceed to bypass it.'.
  14219.         self push: nil. ^self].
  14220.     ^self send: selector to: receiver with: arguments super: superFlag!
  14221. storeIntoLiteralVariable: value 
  14222.     "Simulate the action of bytecode that stores the top of the stack into a 
  14223.     literal variable of my method."
  14224.  
  14225.     value value: self top!
  14226. storeIntoReceiverVariable: offset 
  14227.     "Simulate the action of bytecode that stores the top of the stack into an 
  14228.     instance variable of my receiver."
  14229.  
  14230.     self receiver instVarAt: offset + 1 put: self top!
  14231. storeIntoTemporaryVariable: offset 
  14232.     "Simulate the action of bytecode that stores the top of the stack into one 
  14233.     of my temporary variables."
  14234.  
  14235.     self home at: offset + 1 put: self top! !
  14236.  
  14237. !ContextPart methodsFor: 'debugger access'!
  14238. depthBelow: aContext
  14239.     "Answer how many calls there are between this and aContext."
  14240.  
  14241.     | this depth |
  14242.     this _ self.
  14243.     depth _ 0.
  14244.     [this == aContext or: [this == nil]]
  14245.         whileFalse:
  14246.             [this _ this sender.
  14247.             depth _ depth + 1].
  14248.     ^depth!
  14249. mclass 
  14250.     "Answer the class in which the receiver's method was found."
  14251.  
  14252.     | mclass |
  14253.     self receiver class selectorAtMethod: self method setClass: [:mclass].
  14254.     ^mclass!
  14255. pc
  14256.     "Answer the index of the next bytecode to be executed."
  14257.  
  14258.     ^pc!
  14259. release
  14260.     "Remove information from the receiver and all of the contexts on its 
  14261.     sender chain in order to break circularities."
  14262.  
  14263.     self releaseTo: nil!
  14264. releaseTo: caller 
  14265.     "Remove information from the receiver and the contexts on its sender 
  14266.     chain up to caller in order to break circularities."
  14267.  
  14268.     | c s |
  14269.     c _ self.
  14270.     [c == nil or: [c == caller]]
  14271.         whileFalse: 
  14272.             [s _ c sender.
  14273.             c singleRelease.
  14274.             c _ s]!
  14275. selector
  14276.     "Answer the selector of the method that created the receiver."
  14277.  
  14278.     ^self receiver class 
  14279.         selectorAtMethod: self method 
  14280.         setClass: [:ignored]!
  14281. sender
  14282.     "Answer the context that sent the message that created the receiver."
  14283.  
  14284.     ^sender!
  14285. shortStack
  14286.     "Answer a String showing the top four contexts on my sender chain."
  14287.     | shortStackStream |
  14288.     shortStackStream _ WriteStream on: (String new: 400).
  14289.     (self stackOfSize: 5) do: 
  14290.         [:item | shortStackStream print: item; cr].
  14291.     ^shortStackStream contents!
  14292. singleRelease
  14293.     "Remove information from the receiver in order to break circularities."
  14294.  
  14295.     stackp == nil ifFalse: [1 to: stackp do: [:i | self at: i put: nil]].
  14296.     sender _ nil!
  14297. sourceCode
  14298.     | mclass code |
  14299.     Sensor leftShiftDown ifFalse:
  14300.         [code _ self method getSource.
  14301.         code isNil ifFalse: [^ code]].
  14302.     mclass _ self receiver class selectorAtMethod: self method setClass: [:c | c].
  14303.     ^ (self receiver class decompilerClass new
  14304.         decompile: mclass
  14305.         in: self receiver class
  14306.         method: self method) decompileString!
  14307. stack 
  14308.     "Answer an Array of the contexts on the receiver's sender chain."
  14309.  
  14310.     ^self stackOfSize: 9999!
  14311. stackOfSize: limit 
  14312.     "Answer an OrderedCollection of the top 'limit' contexts
  14313.         on the receiver's sender chain."
  14314.  
  14315.     | a stack |
  14316.     stack _ OrderedCollection new.
  14317.     stack addLast: (a _ self).
  14318.     [(a _ a sender) ~~ nil and: [stack size < limit]]
  14319.         whileTrue: [stack addLast: a].
  14320.     ^ stack!
  14321. swapSender: coroutine 
  14322.     "Replace the receiver's sender with coroutine and answer the receiver's 
  14323.     previous sender. For use in coroutining."
  14324.  
  14325.     | oldSender |
  14326.     oldSender _ sender.
  14327.     sender _ coroutine.
  14328.     ^oldSender!
  14329. tempNames
  14330.     "Answer an OrderedCollection of the names of the receiver's temporary 
  14331.     variables, which are strings."
  14332.  
  14333.     | names |
  14334.     self method setTempNamesIfCached: [:names | ^names].
  14335.     names _ (self mclass compilerClass new
  14336.             parse: self sourceCode
  14337.             in: self mclass
  14338.             notifying: nil) tempNames.
  14339.     self method cacheTempNames: names.
  14340.     ^names!
  14341. tempsAndValues
  14342.     "Return a string of the temporary variabls and their current values"
  14343.     | aStream |
  14344.     aStream _ WriteStream on: (String new: 100).
  14345.     self tempNames
  14346.         doWithIndex: [:title :index |
  14347.             aStream nextPutAll: title; nextPut: $:; space; tab.
  14348.             (self tempAt: index) printOn: aStream.
  14349.             aStream cr].
  14350.     ^aStream contents! !
  14351.  
  14352. !ContextPart methodsFor: 'controlling'!
  14353. activateMethod: newMethod withArgs: args receiver: rcvr class: class 
  14354.     "Answer a ContextPart initialized with the arguments."
  14355.  
  14356.     ^MethodContext 
  14357.         sender: self
  14358.         receiver: rcvr
  14359.         method: newMethod
  14360.         arguments: args!
  14361. blockCopy: numArgs 
  14362.     "Primitive. Distinguish a block of code from its enclosing method by 
  14363.     creating a new BlockContext for that block. The compiler inserts into all 
  14364.     methods that contain blocks the bytecodes to send the message 
  14365.     blockCopy:. Do not use blockCopy: in code that you write!! Only the 
  14366.     compiler can decide to send the message blockCopy:. Fail if numArgs is 
  14367.     not a SmallInteger. Optional. No Lookup. See Object documentation 
  14368.     whatIsAPrimitive."
  14369.  
  14370.     <primitive: 80>
  14371.     ^(BlockContext new: self size)
  14372.         home: self home
  14373.         startpc: pc + 2
  14374.         nargs: numArgs!
  14375. hasSender: context 
  14376.     "Answer whether the receiver is strictly above context on the stack."
  14377.  
  14378.     | s |
  14379.     self == context ifTrue: [^false].
  14380.     s _ sender.
  14381.     [s == nil]
  14382.         whileFalse: 
  14383.             [s == context ifTrue: [^true].
  14384.             s _ s sender].
  14385.     ^false!
  14386. pop
  14387.     "Answer the top of the receiver's stack and remove the top of the stack."
  14388.  
  14389.     | val |
  14390.     val _ self at: stackp.
  14391.     self at: stackp put: nil.
  14392.     stackp _ stackp - 1.
  14393.     ^val!
  14394. push: val 
  14395.     "Push val on the receiver's stack."
  14396.  
  14397.     self at: (stackp _ stackp + 1) put: val!
  14398. return: value to: sendr 
  14399.     "Simulate the return of value to sendr."
  14400.  
  14401.     self releaseTo: sendr.
  14402.     ^sendr push: value!
  14403. send: selector to: rcvr with: args super: superFlag 
  14404.     "Simulate the action of sending a message with selector, selector, and 
  14405.     arguments, args, to receiver. The argument, superFlag, tells whether the 
  14406.     receiver of the message was specified with 'super' in the source method."
  14407.  
  14408.     | class meth val |
  14409.     class _ 
  14410.         superFlag
  14411.             ifTrue: [(self method literalAt: self method numLiterals) value superclass]
  14412.             ifFalse: [rcvr class].
  14413.     [class == nil]
  14414.         whileFalse: 
  14415.             [(class includesSelector: selector)
  14416.                 ifTrue: 
  14417.                     [meth _ class compiledMethodAt: selector.
  14418.                     val _ 
  14419.                         self tryPrimitiveFor: meth
  14420.                             receiver: rcvr
  14421.                             args: args.
  14422.                     val == #simulatorFail ifFalse: [^val].
  14423.                     (selector == #doesNotUnderstand: and: [class == Object]) ifTrue:
  14424.                         [ ^ self error: 'Simulated message ' , (args at: 1) selector , ' not understood' ].
  14425.                     ^self
  14426.                         activateMethod: meth
  14427.                         withArgs: args
  14428.                         receiver: rcvr
  14429.                         class: class].
  14430.             class _ class superclass].
  14431.     ^self send: #doesNotUnderstand:
  14432.         to: rcvr
  14433.         with: (Array with: (Message selector: selector arguments: args))
  14434.         super: superFlag!
  14435. top
  14436.     "Answer the top of the receiver's stack."
  14437.  
  14438.     ^self at: stackp! !
  14439.  
  14440. !ContextPart methodsFor: 'printing'!
  14441. printOn: aStream 
  14442.     | mclass selector class |
  14443.     selector _ 
  14444.         (class _ self receiver class) 
  14445.             selectorAtMethod: self method 
  14446.             setClass: [:mclass].
  14447.     selector == #?
  14448.         ifTrue: 
  14449.             [aStream nextPut: $?; print: self method who.
  14450.             ^self].
  14451.     aStream nextPutAll: class name.
  14452.     mclass == class 
  14453.         ifFalse: 
  14454.             [aStream nextPut: $(.
  14455.             aStream nextPutAll: mclass name.
  14456.             aStream nextPut: $)].
  14457.     aStream nextPutAll: '>>'.
  14458.     aStream nextPutAll: selector! !
  14459.  
  14460. !ContextPart methodsFor: 'system simulation'!
  14461. completeCallee: aContext
  14462.     "Simulate the execution of bytecodes until a return to the receiver."
  14463.  
  14464.     | ctxt current |
  14465.     self class initPrimitives.
  14466.     ctxt _ aContext.
  14467.     [ctxt == current or: [ctxt hasSender: self]]
  14468.         whileTrue: 
  14469.             [current _ ctxt.
  14470.             ctxt _ ctxt step].
  14471.     self stepToSendOrReturn!
  14472. runSimulated: aBlock contextAtEachStep: block2
  14473.     "Simulate the execution of the argument, aBlock, until it ends. aBlock 
  14474.     MUST NOT contain an '^'. Evaluate block2 with the current context 
  14475.     prior to each instruction executed. Answer the simulated value of aBlock."
  14476.  
  14477.     | current |
  14478.     aBlock hasMethodReturn
  14479.         ifTrue: [self error: 'simulation of blocks with ^ can run loose'].
  14480.     self class initPrimitives.
  14481.     current _ aBlock.
  14482.     current pushArgs: Array new from: self.
  14483.     [current == self]
  14484.         whileFalse:
  14485.             [block2 value: current.
  14486.             current _ current step].
  14487.     ^self pop!
  14488. step
  14489.     "Simulate the execution of the receiver's next bytecode. Answer the 
  14490.     context that would be the active context after this bytecode."
  14491.  
  14492.     ^self interpretNextInstructionFor: self!
  14493. stepToSendOrReturn
  14494.     "Simulate the execution of bytecodes until either sending a message or 
  14495.     returning a value to the receiver (that is, until switching contexts)."
  14496.  
  14497.     [self willSend | self willReturn]
  14498.         whileFalse: [self step]! !
  14499.  
  14500. !ContextPart methodsFor: 'private'!
  14501. doPrimitive: primitiveIndex receiver: receiver args: arguments 
  14502.     "Simulate a primitive method whose index is primitiveIndex.  The
  14503.     simulated receiver and arguments are given as arguments to this message."
  14504.     | primitiveMethod value |
  14505.     "If successful, push result and return resuming context,
  14506.         else ^ #simulatorFail"
  14507.     (primitiveIndex = 80 and: [receiver isKindOf: ContextPart])
  14508.         ifTrue: [^self push: 
  14509.                     ((BlockContext new: receiver size)
  14510.                         home: receiver home
  14511.                         startpc: pc + 2
  14512.                         nargs: (arguments at: 1))].
  14513.     (primitiveIndex = 81 and: [receiver isMemberOf: BlockContext])
  14514.         ifTrue: [^receiver pushArgs: arguments from: self].
  14515.     primitiveIndex = 83 
  14516.         ifTrue: [^self send: (arguments at: 1) to: receiver
  14517.                     with: (arguments copyFrom: 2 to: arguments size)
  14518.                     super: false].
  14519.     arguments size > 6 ifTrue: [^#simulatorFail].
  14520.     primitiveMethod _ TryPrimitiveMethods at: arguments size + 1.
  14521.     "slam num into primitive instead of 100 such messages in Object"
  14522.     primitiveMethod bePrimitive: primitiveIndex.
  14523.     "Class flushCache."  "in case interp caches primitive #"
  14524.     value _ receiver perform: (TryPrimitiveSelectors at: arguments size+1)
  14525.                 withArguments: arguments.
  14526.     value == #simulatorFail
  14527.         ifTrue: [^ #simulatorFail]
  14528.         ifFalse: [^ self push: value]!
  14529. pop: numObjects toAddable: anAddableCollection
  14530.     "Pop the top numObjects elements from the stack, and store them in
  14531.      anAddableCollection, topmost element last.
  14532.      Do not call directly.  Called indirectly by {1. 2. 3} constructs."
  14533.  
  14534.     | oldTop i |
  14535.     i _ stackp _ (oldTop _ stackp) - numObjects.
  14536.     [(i _ i + 1) <= oldTop] whileTrue:
  14537.         [anAddableCollection add: (self at: i).
  14538.          self at: i put: nil]!
  14539. pop: numObjects toIndexable: anIndexableCollection
  14540.     "Pop the top numObjects elements from the stack, and store them in
  14541.      anIndexableCollection, topmost element last.
  14542.      Do not call directly.  Called indirectly by {1. 2. 3} constructs."
  14543.  
  14544.     | oldTop i |
  14545.     i _ stackp _ (oldTop _ stackp) - numObjects.
  14546.     [(i _ i + 1) <= oldTop] whileTrue:
  14547.         [anIndexableCollection at: i-stackp put: (self at: i).
  14548.          self at: i put: nil]!
  14549. push: numObjects fromIndexable: anIndexableCollection
  14550.     "Push the elements of anIndexableCollection onto the receiver's stack.
  14551.      Do not call directly.  Called indirectly by {1. 2. 3} constructs."
  14552.  
  14553.     | i |
  14554.     i _ 0.
  14555.     [(i _ i + 1) <= numObjects] whileTrue:
  14556.         [self at: (stackp _ stackp + 1) put: (anIndexableCollection at: i)]!
  14557. stackPtr  "For use only by the SystemTracer"
  14558.     ^ stackp!
  14559. tryPrimitiveFor: method receiver: receiver args: arguments 
  14560.     "Simulate a primitive method, method for the receiver and arguments given
  14561.     as arguments to this message.  Answer resuming the context if successful, else
  14562.     answer the symbol, #simulatorFail."
  14563.     | flag primIndex |
  14564.     (primIndex _ method primitive) = 0 ifTrue: [^#simulatorFail].
  14565.     ^ self doPrimitive: primIndex receiver: receiver args: arguments! !
  14566. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  14567.  
  14568. ContextPart class
  14569.     instanceVariableNames: ''!
  14570.  
  14571. !ContextPart class methodsFor: 'class initialization'!
  14572. initPrimitives   "ContextPart initPrimitives"
  14573.     "The methods (from class Object) that are cached in tryPrimitiveMethods 
  14574.     are used by the simulator to catch failures when simulating primitives."
  14575.     TryPrimitiveSelectors _
  14576. #(tryPrimitive
  14577. tryPrimitiveWith:
  14578. tryPrimitiveWith:with:
  14579. tryPrimitiveWith:with:with:
  14580. tryPrimitiveWith:with:with:with:
  14581. tryPrimitiveWith:with:with:with:with:
  14582. tryPrimitiveWith:with:with:with:with:with:).
  14583.     TryPrimitiveMethods _
  14584.         TryPrimitiveSelectors collect:  [:sel | Object compiledMethodAt: sel]! !
  14585.  
  14586. !ContextPart class methodsFor: 'examples'!
  14587. tallyInstructions: aBlock
  14588.     "This method uses the simulator to count the number of occurrences of
  14589.     each of the Smalltalk instructions executed during evaluation of aBlock.
  14590.     Results appear in order of the byteCode set."
  14591.  
  14592.     | current tallies |
  14593.     tallies _ Bag new.
  14594.     thisContext sender
  14595.         runSimulated: aBlock
  14596.         contextAtEachStep:
  14597.             [:current | tallies add: current nextByte].
  14598.     ^tallies sortedElements
  14599.  
  14600.     "ContextPart tallyInstructions: [3.14159 printString]"!
  14601. tallyMethods: aBlock
  14602.     "This method uses the simulator to count the number of calls on each method
  14603.     invoked in evaluating aBlock. Results are given in order of decreasing counts."
  14604.  
  14605.     | prev current tallies |
  14606.     tallies _ Bag new.
  14607.     prev _ aBlock.
  14608.     thisContext sender
  14609.         runSimulated: aBlock
  14610.         contextAtEachStep:
  14611.             [:current |
  14612.             current == prev ifFalse: "call or return"
  14613.                 [prev sender == nil ifFalse: "call only"
  14614.                     [tallies add: current printString].
  14615.                 prev _ current]].
  14616.     ^tallies sortedCounts
  14617.  
  14618.     "ContextPart tallyMethods: [3.14159 printString]"!
  14619. trace: aBlock        "ContextPart trace: [3 factorial]"
  14620.     "This method uses the simulator to print calls and returned values in the Transcript."
  14621.     | prev current |
  14622.     Transcript clear.
  14623.     prev _ aBlock.
  14624.     ^ thisContext sender
  14625.         runSimulated: aBlock
  14626.         contextAtEachStep:
  14627.             [:current |
  14628.             Sensor anyButtonPressed ifTrue: [^ nil].
  14629.             current == prev
  14630.                 ifFalse:
  14631.                     [prev sender == nil ifTrue:  "returning"
  14632.                         [Transcript space; nextPut: $^; print: current top].
  14633.                     Transcript cr;
  14634.                         nextPutAll: (String new: (current depthBelow: aBlock) withAll: $ );
  14635.                         print: current receiver; space; nextPutAll: current selector; endEntry.
  14636.                     prev _ current]]!
  14637. trace: aBlock onFileNamed: fileName        "ContextPart trace: [3 factorial]"
  14638.     "This method uses the simulator to print calls to a file."
  14639.     | prev current f sel |
  14640.     f _ FileStream fileNamed: fileName.
  14641.     prev _ aBlock.
  14642.     thisContext sender
  14643.         runSimulated: aBlock
  14644.         contextAtEachStep:
  14645.             [:current |
  14646.             Sensor anyButtonPressed ifTrue: [^ nil].
  14647.             current == prev
  14648.                 ifFalse:
  14649.                     [f cr;
  14650.                         nextPutAll: (String new: (current depthBelow: aBlock) withAll: $ );
  14651.                         print: current receiver class; space; nextPutAll: (sel _ current selector); flush.
  14652.                     prev _ current.
  14653.                     sel == #error: ifTrue: [self halt]]].
  14654.     f close! !
  14655.  
  14656. !ContextPart class methodsFor: 'simulation'!
  14657. runSimulated: aBlock
  14658.     "Simulate the execution of the argument, current. Answer the result it 
  14659.     returns."
  14660.  
  14661.     ^ thisContext sender
  14662.         runSimulated: aBlock
  14663.         contextAtEachStep: [:ignored]
  14664.  
  14665.     "ContextPart runSimulated: [Pen new defaultNib: 5; go: 100]"! !BrowserCodeController subclass: #ContextStackCodeController
  14666.     instanceVariableNames: ''
  14667.     classVariableNames: ''
  14668.     poolDictionaries: ''
  14669.     category: 'Interface-Debugger'!
  14670. ContextStackCodeController comment:
  14671. 'I am a BrowserCodeController but the doIt command is redefined. The result of the evaluation is stored as the proceed value for the interrupted (selected) method.'!
  14672.  
  14673. !ContextStackCodeController methodsFor: 'menu messages'!
  14674. doIt
  14675.  
  14676.     | result |
  14677.     result _ super doIt.
  14678.     result ~~ #failedDoit ifTrue: [model proceedValue: result].
  14679.     ^result! !
  14680.  
  14681. !ContextStackCodeController methodsFor: 'displaying'!
  14682. display
  14683.     "By selecting here, debugger windows will select when they redisplay."
  14684.  
  14685.     super display.
  14686.     self select! !
  14687.  
  14688. !ContextStackCodeController methodsFor: 'selecting'!
  14689. initializeSelection
  14690.  
  14691.     self selectionInterval last = 0
  14692.         ifFalse: [super initializeSelection]!
  14693. selectAndScrollFrom: start to: stop
  14694.  
  14695.     "Select the characters from character position start to position stop. Then 
  14696.     move the window so that this selection is visible."
  14697.  
  14698.     self deselect.
  14699.     startBlock _ paragraph characterBlockForIndex: start.
  14700.     stopBlock _ paragraph characterBlockForIndex: stop + 1.
  14701.     self selectAndScroll! !StringHolderView subclass: #ContextStackCodeView
  14702.     instanceVariableNames: ''
  14703.     classVariableNames: ''
  14704.     poolDictionaries: ''
  14705.     category: 'Interface-Debugger'!
  14706. ContextStackCodeView comment:
  14707. 'I am a StringHolderView of the source code retrieved in a Debugger. ContextStackCodeController is my default controller.'!
  14708.  
  14709. !ContextStackCodeView methodsFor: 'updating'!
  14710. update: aSymbol
  14711.     (aSymbol == #contextStackList) | (aSymbol == #contextStackIndex)
  14712.         ifTrue: [^ self].
  14713.     aSymbol == #pc ifTrue: [^ self highlightPC].
  14714.     aSymbol == #contents ifTrue: [^ self updateDisplayContents].
  14715.     super update: aSymbol!
  14716. updateDisplayContents 
  14717.     "Refer to the comment in StringHolderView|updateDisplayContents."
  14718.  
  14719.     | contents |
  14720.     contents _ model contents.
  14721.     displayContents string ~= contents
  14722.         ifTrue: 
  14723.             [displayContents _
  14724.                 (contents asText makeSelectorBoldIn: model selectedClassOrMetaClass) asParagraph.
  14725.             self positionDisplayContents.
  14726.             self controller changeParagraph: displayContents.
  14727.             self displayView.
  14728.             self highlightPC]! !
  14729.  
  14730. !ContextStackCodeView methodsFor: 'private'!
  14731. highlightPC
  14732.  
  14733.     | range |
  14734.     range _ model pcRange.
  14735.     self controller selectAndScrollFrom: range first to: range last! !MessageListController subclass: #ContextStackListController
  14736.     instanceVariableNames: ''
  14737.     classVariableNames: 'ContextStackListYellowButtonMenu ContextStackListYellowButtonMessages '
  14738.     poolDictionaries: ''
  14739.     category: 'Interface-Debugger'!
  14740. ContextStackListController comment:
  14741. 'I am a kind of LockedListController for the upper subView of a DebuggerView that creates a yellow button menu so that messages can be sent to the list selection (a message) to:
  14742.     fullStack    change from displaying the minimal stack to a full one
  14743.     proceed    proceed evaluation from the interrupted expression
  14744.     restart    restart evaluation from the beginning of the method
  14745.     send    execute the next message that a step would invoke
  14746.     spawn    create a browser for the code of the model''s selected message
  14747.     step    execute the next expression in the selected method
  14748.     where    toggle the flag that indicates whether to show the pc selection'!
  14749.  
  14750. !ContextStackListController methodsFor: 'initialize-release'!
  14751. initialize
  14752.  
  14753.     super initialize.
  14754.     self initializeYellowButtonMenu! !
  14755.  
  14756. !ContextStackListController methodsFor: 'menu messages'!
  14757. fullStack
  14758.     "Change from displaying the minimal stack to a full one."
  14759.  
  14760.     model contextStackList size > 7
  14761.         ifTrue:
  14762.             [view flash]
  14763.         ifFalse:
  14764.             [model contextStackIndex = 0
  14765.                 ifFalse: [model toggleContextStackIndex: model contextStackIndex].
  14766.             self controlTerminate.
  14767.             model fullyExpandStack.
  14768.             self controlInitialize]!
  14769. proceed
  14770.     "Proceed execution of the receiver's model, starting after the expression at 
  14771.     which an interruption occurred."
  14772.  
  14773.     self controlTerminate.
  14774.     model proceed: view topView controller.
  14775.     self controlInitialize!
  14776. restart
  14777.     "Proceed execution of the receiver's model, starting at the beginning of 
  14778.     the currently selected method."
  14779.  
  14780.     self controlTerminate.
  14781.     model restart: view topView controller.
  14782.     self controlInitialize!
  14783. send
  14784.     "Evaluate the next expression in the receiver's model's currently selected 
  14785.     method, after the point at which interruption occurred."
  14786.  
  14787.     self controlTerminate.
  14788.     model send.
  14789.     self controlInitialize!
  14790. spawn
  14791.     "Create and schedule a message browser for the code of the model's 
  14792.     selected message. Retain any edits that have not yet been accepted."
  14793.  
  14794.     self controlTerminate.
  14795.     model spawn.
  14796.     self controlInitialize!
  14797. step
  14798.     "Evaluate the next message of the sequence that is initiated by evaluating 
  14799.     the next expression in the receiver's model's currently selected method, 
  14800.     after the point at which interruption occurred."
  14801.  
  14802.     self controlTerminate.
  14803.     model step.
  14804.     self controlInitialize!
  14805. where
  14806.     "Select the expression whose evaluation was interrupted."
  14807.  
  14808.     model selectPC! !
  14809.  
  14810. !ContextStackListController methodsFor: 'private'!
  14811. changeModelSelection: anInteger 
  14812.     Cursor execute showWhile:
  14813.         [model toggleContextStackIndex: anInteger]!
  14814. initializeYellowButtonMenu
  14815.  
  14816.     self yellowButtonMenu: ContextStackListYellowButtonMenu
  14817.         yellowButtonMessages: ContextStackListYellowButtonMessages! !
  14818.  
  14819. !ContextStackListController methodsFor: 'selecting '!
  14820. initializeSelection
  14821.  
  14822.     ^self! !
  14823. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  14824.  
  14825. ContextStackListController class
  14826.     instanceVariableNames: ''!
  14827.  
  14828. !ContextStackListController class methodsFor: 'class initialization'!
  14829. initialize
  14830.     "Modified 1/12/96 sw"
  14831.  
  14832.     ContextStackListYellowButtonMenu _ 
  14833.         PopUpMenu labels: 'fullStack
  14834. restart
  14835. proceed
  14836. step
  14837. send
  14838. where
  14839. senders
  14840. implementors
  14841. senders of...
  14842. implementors of...
  14843. browse full'
  14844.     lines: #(6 11).
  14845.     ContextStackListYellowButtonMessages _ #(fullStack restart proceed step send where senders implementors sendersOf messages browseFull)
  14846.  
  14847.     "ContextStackListController initialize"! !
  14848.  
  14849. ContextStackListController initialize!
  14850. ListView subclass: #ContextStackListView
  14851.     instanceVariableNames: ''
  14852.     classVariableNames: ''
  14853.     poolDictionaries: ''
  14854.     category: 'Interface-Debugger'!
  14855. ContextStackListView comment:
  14856. 'I am a ListView whose items are the methods (interrupted message-sends) of the Debugger that I view. ContextStackListController is my default controller.'!
  14857.  
  14858. !ContextStackListView methodsFor: 'model access'!
  14859. model: aDebugger
  14860.  
  14861.     super model: aDebugger.
  14862.     self list: model contextStackList! !
  14863.  
  14864. !ContextStackListView methodsFor: 'updating'!
  14865. update: aSymbol
  14866.  
  14867.     aSymbol == #contextStackIndex
  14868.         ifTrue: [self moveSelectionBox: model contextStackIndex].
  14869.     aSymbol == #contextStackList
  14870.         ifTrue: 
  14871.             [self list: model contextStackList.
  14872.             self displayView].
  14873.     aSymbol == #notChanged ifTrue: [self flash]! !
  14874.  
  14875. !ContextStackListView methodsFor: 'controller access'!
  14876. defaultControllerClass
  14877.  
  14878.     ^ContextStackListController! !Inspector subclass: #ContextVariablesInspector
  14879.     instanceVariableNames: ''
  14880.     classVariableNames: ''
  14881.     poolDictionaries: ''
  14882.     category: 'Interface-Debugger'!
  14883. ContextVariablesInspector comment:
  14884. 'I represent a query path into the internal representation of a ContextPart. Typically this is a context at a point in the query path of a Debugger. As a StringHolder, the string I represent is the value of the currently selected variable of the observed temporary variable of the context.'!
  14885.  
  14886. !ContextVariablesInspector methodsFor: 'accessing'!
  14887. fieldList 
  14888.     "Refer to the comment in Inspector|fieldList."
  14889.  
  14890.     object == nil ifTrue: [^Array with: 'thisContext'].
  14891.     ^(Array with: 'thisContext' with: 'all temp vars') , object tempNames! !
  14892.  
  14893. !ContextVariablesInspector methodsFor: 'selecting'!
  14894. replaceSelectionValue: anObject 
  14895.     "Refer to the comment in Inspector|replaceSelectionValue:."
  14896.  
  14897.     selectionIndex = 1
  14898.         ifTrue: [^object]
  14899.         ifFalse: [^object tempAt: selectionIndex - 1 put: anObject]!
  14900. selection 
  14901.     "Refer to the comment in Inspector|selection."
  14902.  
  14903.     selectionIndex = 1 ifTrue: [^object].
  14904.     selectionIndex = 2
  14905.         ifTrue: [^object tempsAndValues]
  14906.         ifFalse: [^object tempAt: selectionIndex - 2]! !
  14907.  
  14908. !ContextVariablesInspector methodsFor: 'code'!
  14909. doItContext
  14910.  
  14911.     ^object!
  14912. doItReceiver
  14913.  
  14914.     ^object receiver! !Object subclass: #Controller
  14915.     instanceVariableNames: 'model view sensor '
  14916.     classVariableNames: ''
  14917.     poolDictionaries: ''
  14918.     category: 'Interface-Framework'!
  14919. Controller comment:
  14920. 'A Controller coordinates a View, its model, and user actions. It provides scheduling (control) behavior to determine when the user wants to communicate with the model or view.'!
  14921.  
  14922. !Controller methodsFor: 'initialize-release'!
  14923. initialize
  14924.     "Initialize the state of the receiver. Subclasses should include 'super 
  14925.     initialize' when redefining this message to insure proper initialization."
  14926.  
  14927.     sensor _ InputSensor default!
  14928. release
  14929.     "Breaks the cycle between the receiver and its view. It is usually not 
  14930.     necessary to send release provided the receiver's view has been properly 
  14931.     released independently."
  14932.  
  14933.     model _ nil.
  14934.     view ~~ nil
  14935.         ifTrue: 
  14936.             [view controller: nil.
  14937.             view _ nil]! !
  14938.  
  14939. !Controller methodsFor: 'model access'!
  14940. model
  14941.     "Answer the receiver's model which is the same as the model of the 
  14942.     receiver's view."
  14943.  
  14944.     ^model!
  14945. model: aModel 
  14946.     "Controller|model: and Controller|view: are sent by View|controller: in 
  14947.     order to coordinate the links between the model, view, and controller. In 
  14948.     ordinary usage, the receiver is created and passed as the parameter to 
  14949.     View|controller: so that the receiver's model and view links can be set 
  14950.     up by the view."
  14951.  
  14952.     model _ aModel! !
  14953.  
  14954. !Controller methodsFor: 'view access'!
  14955. inspectView
  14956.     view notNil ifTrue: [^ view inspect]!
  14957. view
  14958.     "Answer the receiver's view."
  14959.  
  14960.     ^view!
  14961. view: aView 
  14962.     "Controller|view: and Controller|model: are sent by View|controller: in 
  14963.     order to coordinate the links between the model, view, and controller. In 
  14964.     ordinary usage, the receiver is created and passed as the parameter to 
  14965.     View|controller: and the receiver's model and view links are set up 
  14966.     automatically by the view."
  14967.  
  14968.     view _ aView! !
  14969.  
  14970. !Controller methodsFor: 'sensor access'!
  14971. sensor
  14972.     "Answer the receiver's sensor. Subclasses may use other objects that are 
  14973.     not instances of Sensor or its subclasses if more general kinds of 
  14974.     input/output functions are required."
  14975.  
  14976.     ^sensor!
  14977. sensor: aSensor
  14978.     "Set the receiver's sensor to aSensor."
  14979.  
  14980.     sensor _ aSensor! !
  14981.  
  14982. !Controller methodsFor: 'basic control sequence'!
  14983. controlInitialize
  14984.     "Sent by Controller|startUp as part of the standard control sequence, it 
  14985.     provides a place in the standard control sequence for initializing the 
  14986.     receiver (taking into account the current state of its model and view). It 
  14987.     should be redefined in subclasses to perform some specific action."
  14988.  
  14989.     ^self!
  14990. controlLoop 
  14991.     "Sent by Controller|startUp as part of the standard control sequence. 
  14992.     Controller|controlLoop sends the message Controller|isControlActive to test 
  14993.     for loop termination. As long as true is returned, the loop continues. 
  14994.     When false is returned, the loop ends. Each time through the loop, the 
  14995.     message Controller|controlActivity is sent."
  14996.  
  14997.     [self isControlActive] whileTrue: [self controlActivity. Processor yield]!
  14998. controlTerminate
  14999.     "Provide a place in the standard control sequence for terminating the 
  15000.     receiver (taking into account the current state of its model and view). It 
  15001.     should be redefined in subclasses to perform some specific action."
  15002.  
  15003.     ^self!
  15004. startUp
  15005.     "Give control to the receiver. The default control sequence is to initialize 
  15006.     (see Controller|controlInitialize), to loop (see Controller|controlLoop), and 
  15007.     then to terminate (see Controller|controlTerminate). After this sequence, 
  15008.     control is returned to the sender of Control|startUp. The receiver's control 
  15009.     sequence is used to coordinate the interaction of its view and model. In 
  15010.     general, this consists of polling the sensor for user input, testing the 
  15011.     input with respect to the current display of the view, and updating the 
  15012.     model to reflect intended changes."
  15013.  
  15014.     self controlInitialize.
  15015.     self controlLoop.
  15016.     self controlTerminate!
  15017. terminateAndInitializeAround: aBlock
  15018.     "1/12/96 sw"
  15019.     self controlTerminate.
  15020.     aBlock value.
  15021.     self controlInitialize! !
  15022.  
  15023. !Controller methodsFor: 'control defaults'!
  15024. controlActivity
  15025.     "Pass control to the next control level (that is, to the Controller of a 
  15026.     subView of the receiver's view) if possible. It is sent by 
  15027.     Controller|controlLoop each time through the main control loop. It should 
  15028.     be redefined in a subclass if some other action is needed."
  15029.  
  15030.     self controlToNextLevel!
  15031. controlToNextLevel
  15032.     "Pass control to the next control level (that is, to the Controller of a 
  15033.     subView of the receiver's view) if possible. The receiver finds the 
  15034.     subView (if any) of its view whose inset display box (see 
  15035.     View|insetDisplayBox) contains the sensor's cursor point. The Controller 
  15036.     of this subView is then given control if it answers true in response to 
  15037.     the message Controller|isControlWanted."
  15038.  
  15039.     | aView |
  15040.     aView _ view subViewWantingControl.
  15041.     aView ~~ nil ifTrue: [aView controller startUp]!
  15042. isControlActive
  15043.     "Answer whether receiver wishes to continue evaluating its controlLoop 
  15044.     method. It is sent by Controller|controlLoop in order to determine when 
  15045.     the receiver's control loop should terminate, and should be redefined in 
  15046.     a subclass if some special condition for terminating the main control loop 
  15047.     is needed."
  15048.  
  15049.     ^ self viewHasCursor
  15050.         & sensor blueButtonPressed not
  15051.         & sensor yellowButtonPressed not
  15052.         "& sensor cmdKeyPressed not"!
  15053. isControlWanted
  15054.     "Answer whether the cursor is inside the inset display box (see 
  15055.     View|insetDisplayBox) of the receiver's view. It is sent by 
  15056.     Controller|controlNextLevel in order to determine whether or not control 
  15057.     should be passed to this receiver from the Controller of the superView of 
  15058.     this receiver's view."
  15059.  
  15060.     ^self viewHasCursor!
  15061. yellowButtonPushed
  15062.     | message superView menu |
  15063.     "Supports several controllers whose only common ancestor is Controller"
  15064.     menu _  Sensor leftShiftDown
  15065.         ifTrue: [self class debuggingMenu]
  15066.         ifFalse: [self class editingMenu].
  15067.     message _ menu startUpWithCaption: model class name.
  15068.     ((superView _ view superView) respondsTo: message)
  15069.         ifTrue: [superView perform: message]
  15070.         ifFalse: [(view respondsTo: message)
  15071.             ifTrue: [view perform: message]
  15072.             ifFalse: [self perform: message]]! !
  15073.  
  15074. !Controller methodsFor: 'cursor'!
  15075. centerCursorInView
  15076.     "Position sensor's mousePoint (which is assumed to be connected to the 
  15077.     cursor) to the center of its view's inset display box (see 
  15078.     Sensor|mousePoint: and View|insetDisplayBox)."
  15079.  
  15080.     ^sensor cursorPoint: view insetDisplayBox center!
  15081. viewHasCursor
  15082.     "Answer whether the cursor point of the receiver's sensor lies within the 
  15083.     inset display box of the receiver's view (see View|insetDisplayBox). 
  15084.     Controller|viewHasCursor is normally used in internal methods."
  15085.  
  15086.     ^view containsPoint: sensor cursorPoint! !
  15087. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  15088.  
  15089. Controller class
  15090.     instanceVariableNames: ''!
  15091.  
  15092. !Controller class methodsFor: 'instance creation'!
  15093. hasEditingMenu
  15094.     ^ false!
  15095. new
  15096.  
  15097.     ^super new initialize! !Object subclass: #ControlManager
  15098.     instanceVariableNames: 'scheduledControllers activeController activeControllerProcess screenController newTopClicked '
  15099.     classVariableNames: ''
  15100.     poolDictionaries: ''
  15101.     category: 'Interface-Framework'!
  15102. ControlManager comment:
  15103. 'I represent the top level control over scheduling which controller of a view on the screen the user is actively using. ScheduledControllers is the global reference to an instance of me, the one attached to the Project currently being used.'!
  15104.  
  15105. !ControlManager methodsFor: 'initialize-release'!
  15106. initialize
  15107.     "Initialize the receiver to refer to only the background controller."
  15108.     | screenView |
  15109.     screenController _ ScreenController new.
  15110.     screenView _ FormView new.
  15111.     screenView model: (InfiniteForm with: Color gray) controller: screenController.
  15112.     screenView window: Display boundingBox.
  15113.     scheduledControllers _ OrderedCollection with: screenController!
  15114. release 
  15115.     "Refer to the comment in Object|release."
  15116.  
  15117.     scheduledControllers == nil
  15118.         ifFalse: 
  15119.             [scheduledControllers 
  15120.                 do: [:controller | (controller isKindOf: Controller)
  15121.                                 ifTrue: [controller view release]
  15122.                                 ifFalse: [controller release]].
  15123.             scheduledControllers _ nil]! !
  15124.  
  15125. !ControlManager methodsFor: 'accessing'!
  15126. activeController
  15127.     "Answer the currently active controller."
  15128.  
  15129.     ^activeController!
  15130. activeController: aController 
  15131.     "Set aController to be the currently active controller. Give the user 
  15132.     control in it."
  15133.  
  15134.     activeController _ aController.
  15135.     (activeController == screenController)
  15136.         ifFalse: [self promote: activeController].
  15137.     activeControllerProcess _ 
  15138.             [activeController startUp.
  15139.             self searchForActiveController] newProcess.
  15140.     activeControllerProcess priority: Processor userSchedulingPriority.
  15141.     activeControllerProcess resume!
  15142. activeControllerNoTerminate: aController andProcess: aProcess
  15143.     "Set aController to be the currently active controller and aProcess to be 
  15144.     the the process that handles controller scheduling activities in the 
  15145.     system. This message differs from activeController:andProcess: in that it 
  15146.     does not send controlTerminate to the currently active controller."
  15147.  
  15148.     self inActiveControllerProcess
  15149.         ifTrue: 
  15150.             [aController~~nil
  15151.                 ifTrue: [(scheduledControllers includes: aController)
  15152.                             ifTrue: [self promote: aController]
  15153.                             ifFalse: [self error: 'Old controller not scheduled']].
  15154.             activeController _ aController.
  15155.             activeController == nil
  15156.                 ifFalse: [activeController controlInitialize].
  15157.             activeControllerProcess _ aProcess.
  15158.             activeControllerProcess resume]
  15159.         ifFalse: 
  15160.             [self error: 'New active controller process must be set from old one'] !
  15161. activeControllerProcess
  15162.     "Answer the process that is currently handling controller scheduling 
  15163.     activities in the system."
  15164.  
  15165.     ^activeControllerProcess!
  15166. controllerSatisfying: aBlock
  15167.     "Return the first scheduled controller which satisfies the 1-argument boolean-valued block, or nil if none.  7/25/96 sw"
  15168.  
  15169.     scheduledControllers do:
  15170.         [:aController | (aBlock value: aController) == true ifTrue: [^ aController]].
  15171.     ^ nil!
  15172. controllerWhoseModelSatisfies: aBlock
  15173.     "Return the first scheduled controller whose model satisfies the 1-argument boolean-valued block, or nil if none.  5/6/96 sw"
  15174.  
  15175.     scheduledControllers do:
  15176.         [:aController | (aBlock value: aController model) == true ifTrue: [^ aController]].
  15177.     ^ nil!
  15178. includes: aController
  15179.     ^ scheduledControllers includes: aController!
  15180. noteNewTop
  15181.     newTopClicked _ true!
  15182. scheduledControllers
  15183.     "Answer a copy of the ordered collection of scheduled controllers."
  15184.  
  15185.     ^scheduledControllers copy!
  15186. scheduledWindowControllers
  15187.     "Same as scheduled controllers, but without ScreenController.  1/13/96 sw"
  15188.  
  15189.     ^ scheduledControllers copyWithout: screenController!
  15190. screenController
  15191.     ^ screenController!
  15192. topmostInactiveTextController
  15193.     "Answer the controller of the window just below the topmost window.  1/31/96 sw"
  15194.  
  15195.     | aView |
  15196.     scheduledControllers doWithIndex: [:ctrlr :i |
  15197.         ( i > 1 & ctrlr isKindOf: StandardSystemController)
  15198.             ifTrue:
  15199.                 [(aView _ ctrlr view textEditorView) ~~ nil
  15200.                     ifTrue:
  15201.                         [^ aView controller]]].
  15202.     ^ nil!
  15203. windowOriginsInUse
  15204.     "Answer a collection of the origins of windows currently on the screen in the current project.  5/21/96 sw"
  15205.  
  15206.     ^ self scheduledWindowControllers collect: [:aController | aController view displayBox origin].! !
  15207.  
  15208. !ControlManager methodsFor: 'scheduling'!
  15209. activateController: aController
  15210.     "Make aController, which must already be a scheduled controller, the active window.  5/8/96 sw"
  15211.  
  15212.     self activeController: aController.
  15213.     (activeController view labelDisplayBox
  15214.         intersect: Display boundingBox) area < 200
  15215.             ifTrue: [activeController move].
  15216.     Processor terminateActive!
  15217. activateTranscript
  15218.     "There is known to be a Transcript open in the current project; activate it.  2/5/96 sw"
  15219.  
  15220.     | itsController |
  15221.     itsController _ scheduledControllers detect:
  15222.             [:controller | controller model == Transcript]
  15223.         ifNone:
  15224.             [^ self].
  15225.  
  15226.     self activeController: itsController.
  15227.     (activeController view labelDisplayBox
  15228.             intersect: Display boundingBox) area < 200
  15229.                 ifTrue: [activeController move].
  15230.     Processor terminateActive!
  15231. findWindow
  15232.     "Present a menu of window titles, and activate the one that gets chosen.
  15233.     5/8/96 sw: use activateController:"
  15234.  
  15235.     | controllers labels index |
  15236.     controllers _ OrderedCollection new.
  15237.     labels _ String streamContents:
  15238.         [:strm |
  15239.         scheduledControllers do:
  15240.             [:controller | controller == screenController ifFalse:
  15241.                 [controllers addLast: controller.
  15242.                 strm nextPutAll: (controller view label contractTo: 40); cr]].
  15243.         strm skip: -1  "drop last cr"].
  15244.     index _ (PopUpMenu labels: labels) startUp.
  15245.     index > 0 ifTrue:
  15246.         [self activateController: (controllers at: index)]!
  15247. findWindowSatisfying: aBlock
  15248.     "Present a menu of window titles, and activate the one that gets chosen
  15249.      1/18/96 sw: Created this version with an argument for more general use, and also, as per Dan's request, modified so that windows whose topleft corners are beyond the lower-right screen corner get picked up by the window-rescue piece.
  15250.      5/8/96 sw: use activateController:"
  15251.  
  15252.     | controllers labels index |
  15253.     controllers _ OrderedCollection new.
  15254.     labels _ String streamContents:
  15255.         [:strm |
  15256.         scheduledControllers do:
  15257.             [:controller | controller == screenController ifFalse:
  15258.                 [(aBlock value: controller) ifTrue:
  15259.                     [controllers addLast: controller.
  15260.                     strm nextPutAll: (controller view label contractTo: 40); cr]]].
  15261.         strm position == 0 ifTrue: [^ self].  "Nothing satisfies"
  15262.         strm skip: -1  "drop last cr"].
  15263.  
  15264.     index _ (PopUpMenu labels: labels) startUp.
  15265.     index > 0 ifTrue:
  15266.         [self activateController: (controllers at: index)]!
  15267. inActiveControllerProcess
  15268.     "Answer whether the active scheduling process is the actual active 
  15269.     process in the system."
  15270.  
  15271.     ^activeControllerProcess == Processor activeProcess!
  15272. interruptName: title
  15273.     "Create a Notifier on the active scheduling process whose label is title 
  15274.     Make the Notifier the active controller."
  15275.  
  15276.     | newActiveController suspendingList |
  15277.     suspendingList _ activeControllerProcess suspendingList.
  15278.     suspendingList isNil
  15279.         ifTrue: [activeControllerProcess==Processor activeProcess
  15280.                         ifTrue: [activeControllerProcess suspend]]
  15281.         ifFalse: [suspendingList remove: activeControllerProcess.
  15282.                  activeControllerProcess offList].
  15283.     newActiveController _ 
  15284.         (DebuggerView openInterrupt: title
  15285.                       onProcess: activeControllerProcess)
  15286.                             controller.
  15287.     activeController ~~ nil
  15288.             ifTrue: [activeController controlTerminate].
  15289.     newActiveController centerCursorInView.
  15290.     self activeController: newActiveController
  15291. !
  15292. potentialController
  15293.     "Answer the controller of the window directly under the cursor.  Answer nil if the cursor is not over a window or the window is collapsed."
  15294.  
  15295.     | pt |
  15296.     pt _ Sensor cursorPoint.
  15297.     ^scheduledControllers detect: [:controller |
  15298.         (controller view insetDisplayBox containsPoint: pt)
  15299.         & (controller isKindOf: StandardSystemController)
  15300.         and: [controller view isCollapsed not]] ifNone: [screenController]!
  15301. promote: aController
  15302.     "Make aController be the first scheduled controller in the ordered 
  15303.     collection."
  15304.     
  15305.     scheduledControllers remove: aController.
  15306.     scheduledControllers addFirst: aController!
  15307. scheduleActive: aController 
  15308.     "Make aController be scheduled as the active controller. Presumably the 
  15309.     active scheduling process asked to schedule this controller and that a 
  15310.     new process associated this controller takes control. So this is the last act 
  15311.     of the active scheduling process."
  15312.  
  15313.     self scheduleActiveNoTerminate: aController.
  15314.     Processor terminateActive!
  15315. scheduleActiveNoTerminate: aController 
  15316.     "Make aController be the active controller. Presumably the process that 
  15317.     requested the new active controller wants to keep control to do more 
  15318.     activites before the new controller can take control. Therefore, do not 
  15319.     terminate the currently active process."
  15320.  
  15321.     self schedulePassive: aController.
  15322.     self scheduled: aController
  15323.         from: Processor activeProcess!
  15324. scheduleOnBottom: aController 
  15325.     "Make aController be scheduled as a scheduled controller, but not the 
  15326.     active one. Put it at the end of the ordered collection of controllers."
  15327.  
  15328.     scheduledControllers addLast: aController!
  15329. schedulePassive: aController 
  15330.     "Make aController be scheduled as a scheduled controller, but not the 
  15331.     active one. Put it at the beginning of the ordered collection of 
  15332.     controllers."
  15333.  
  15334.     scheduledControllers addFirst: aController!
  15335. searchForActiveController
  15336.     "Find a scheduled controller that wants control and give control to it. If 
  15337.     none wants control, then see if the System Menu has been requested."
  15338.     | aController |
  15339.     activeController _ nil.
  15340.     activeControllerProcess _ Processor activeProcess.
  15341.     self activeController: self nextActiveController.
  15342.     Processor terminateActive!
  15343. unschedule: aController
  15344.     "Remove the view, aController, from the collection of scheduled 
  15345.     controllers."
  15346.  
  15347.     scheduledControllers remove: aController ifAbsent: []!
  15348. windowFromUser
  15349.     "Present a menu of window titles, and returns the StandardSystemController belonging to the one that gets chosen, or nil if none"
  15350.     | controllers labels index |
  15351.     controllers _ OrderedCollection new.
  15352.     labels _ String streamContents:
  15353.         [:strm |
  15354.         scheduledControllers do:
  15355.             [:controller | controller == screenController ifFalse:
  15356.                 [controllers addLast: controller.
  15357.                 strm nextPutAll: (controller view label contractTo: 40); cr]].
  15358.         strm skip: -1  "drop last cr"].
  15359.     index _ (PopUpMenu labels: labels) startUp.
  15360.     ^ index > 0
  15361.         ifTrue:
  15362.             [controllers at: index]
  15363.         ifFalse:
  15364.             [nil]! !
  15365.  
  15366. !ControlManager methodsFor: 'displaying'!
  15367. backgroundForm: aForm
  15368.     screenController view model: aForm.
  15369.     ScheduledControllers restore
  15370. "
  15371.     QDPen new mandala: 30 diameter: 640.
  15372.     ScheduledControllers backgroundForm:
  15373.         (Form fromDisplay: Display boundingBox).
  15374.  
  15375.     ScheduledControllers backgroundForm:
  15376.         (InfiniteForm with: Form gray).
  15377. "!
  15378. bring: aController nextToTopFor: actionBlock
  15379.     "Allows transcript to display reasonably.  The transcript will
  15380.     appear on top during display.  Then by promoting it
  15381.     next to top, it will remain on top if at all possible - ie if it isnt
  15382.     under the active window.  If it is under the active window, it will
  15383.     still come to the top during display, and then drop back to second.
  15384.     Actually, it is promoted to top if necessary for the duration of the 
  15385.     action block so that things like label updating will work properly."
  15386.     | position value aPort aPortRect |
  15387.     position _ scheduledControllers indexOf: aController.
  15388.     position <= 1 ifTrue: [^ actionBlock value].
  15389.     self promote: aController.
  15390.     activeController == screenController ifFalse:
  15391.         [activeController view cacheBitsAsIs].
  15392.     aController controlInitialize.
  15393.     aPortRect _ aController view displayBox
  15394.                     merge: aController view labelDisplayBox.
  15395.     value _ actionBlock value.
  15396.     aController controlTerminate.
  15397.     self promote: (scheduledControllers at: 2).
  15398.     activeController == screenController ifFalse:
  15399.         [aPort _ (BitBlt toForm: Display) clipRect: aPortRect.
  15400.         activeController view displayOn: aPort]!
  15401. restore
  15402.     "Clear the screen to gray and then redisplay all the scheduled views.  Try to be a bit intelligent about the view that wants control and not display it twice if possible..
  15403.     1/24/96 sw: uncache bits of top view"
  15404.  
  15405.     scheduledControllers first view uncacheBits.  "assure refresh"
  15406.     self unschedule: screenController; scheduleOnBottom: screenController.
  15407.     screenController view window: Display boundingBox.
  15408.     scheduledControllers reverseDo:
  15409.         [:aController | aController view displayDeEmphasized].
  15410. !
  15411. restore: aRectangle
  15412.     "Restore all windows visible in aRectangle"
  15413.     ^ self restore: aRectangle below: 1 without: nil!
  15414. restore: aRectangle below: index without: aView
  15415.     "Restore all windows visible in aRectangle, but without aView"
  15416.     | view | 
  15417.     view _ (scheduledControllers at: index) view.
  15418.     view == aView ifTrue: 
  15419.         [index >= scheduledControllers size ifTrue: [^ self].
  15420.         ^ self restore: aRectangle below: index+1 without: aView].
  15421.     view displayOn: ((BitBlt toForm: Display) clipRect: aRectangle).
  15422.     index >= scheduledControllers size ifTrue: [^ self].
  15423.     (aRectangle areasOutside: view windowBox) do:
  15424.         [:rect | self restore: rect below: index + 1 without: aView]!
  15425. restore: aRectangle without: aView
  15426.     "Restore all windows visible in aRectangle"
  15427.     ^ self restore: aRectangle below: 1 without: aView!
  15428. updateGray
  15429.     (screenController view model isMemberOf: InfiniteForm)
  15430.         ifTrue: [screenController view model: (InfiniteForm with: Color gray)]! !
  15431.  
  15432. !ControlManager methodsFor: 'private'!
  15433. deactivate
  15434.     activeController _ nil.
  15435.     activeControllerProcess _ nil.    
  15436.     self unCacheWindows!
  15437. nextActiveController
  15438.     "Answer the controller that would like control.  
  15439.     If there was a click outside the active window, it's the top window
  15440.     that now has the mouse, otherwise it's just the top window."
  15441.  
  15442.     (newTopClicked notNil and: [newTopClicked])
  15443.         ifTrue: [newTopClicked _ false.
  15444.                 ^ scheduledControllers 
  15445.                     detect: [:aController | aController isControlWanted]
  15446.                     ifNone: [scheduledControllers first]]
  15447.         ifFalse: [^ scheduledControllers first]!
  15448. scheduled: aController from: aProcess
  15449.  
  15450.     activeControllerProcess==aProcess
  15451.         ifTrue: 
  15452.             [activeController ~~ nil
  15453.                     ifTrue: [activeController controlTerminate].
  15454.             aController centerCursorInView.
  15455.             self activeController: aController]!
  15456. unCacheWindows
  15457.     scheduledControllers do:
  15458.         [:aController | aController view uncacheBits]! !
  15459. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  15460.  
  15461. ControlManager class
  15462.     instanceVariableNames: ''!
  15463.  
  15464. !ControlManager class methodsFor: 'instance creation'!
  15465. new
  15466.     ^super new initialize! !
  15467.  
  15468. !ControlManager class methodsFor: 'exchange'!
  15469. newScheduler: controlManager
  15470.     "When switching projects, the control scheduler has to be exchanged. The 
  15471.     active one is the one associated with the current project."
  15472.  
  15473.     ScheduledControllers deactivate.
  15474.     Smalltalk at: #ScheduledControllers put: controlManager.
  15475.     ScheduledControllers restore.
  15476.     controlManager searchForActiveController! !
  15477.  
  15478. !ControlManager class methodsFor: 'snapshots'!
  15479. shutDown  "Saves space in snapshots"
  15480.     ScheduledControllers deactivate!
  15481. startUp
  15482.     ScheduledControllers restore! !FillInTheBlankController subclass: #CRFillInTheBlankController
  15483.     instanceVariableNames: ''
  15484.     classVariableNames: ''
  15485.     poolDictionaries: ''
  15486.     category: 'Interface-Menus'!
  15487. CRFillInTheBlankController comment:
  15488. 'I am a FillInTheBlankController that eliminates the yellow button menu options for paragraph editing and causes termination on a carriage return.'!
  15489.  
  15490. !CRFillInTheBlankController methodsFor: 'basic control sequence'!
  15491. controlInitialize
  15492.  
  15493.     startBlock _ paragraph characterBlockForIndex: startBlock stringIndex.
  15494.     stopBlock _ paragraph characterBlockForIndex: stopBlock stringIndex.
  15495.     self initializeSelection.
  15496.     beginTypeInBlock _ nil!
  15497. controlTerminate
  15498.  
  15499.     "self closeTypeIn ifTrue: [startBlock _ stopBlock copy]."
  15500.     "so leaving and entering window won't select last type-in"
  15501.     super controlTerminate! !
  15502.  
  15503. !CRFillInTheBlankController methodsFor: 'sensor access'!
  15504. dispatchOnCharacter: char with: typeAheadStream
  15505.     "Check for CR and cause an ACCEPT"
  15506.  
  15507.     (char = Character cr) | (char = Character enter)
  15508.         ifTrue: [sensor keyboard.     "gobble cr"
  15509.                 self replaceSelectionWith:
  15510.                     (Text string: typeAheadStream contents
  15511.                         emphasis: emphasisHere).
  15512.                 self accept.
  15513.                 ^ true]
  15514.         ifFalse: [^ super dispatchOnCharacter: char with: typeAheadStream]!
  15515. processYellowButton
  15516.  
  15517.     ^self! !Form subclass: #Cursor
  15518.     instanceVariableNames: ''
  15519.     classVariableNames: 'SquareCursor NormalCursor OriginCursor ReadCursor BlankCursor MenuCursor WaitCursor MoveCursor CurrentCursor XeqCursor WriteCursor MarkerCursor DownCursor RightArrowCursor CrossHairCursor UpCursor CornerCursor '
  15520.     poolDictionaries: ''
  15521.     category: 'Graphics-Display Objects'!
  15522. Cursor comment:
  15523. 'I am a 16 x 16 dot matrix suitable for use as the Alto hardware cursor.'!
  15524.  
  15525. !Cursor methodsFor: 'updating'!
  15526. changed: aParameter
  15527.  
  15528.     self == CurrentCursor ifTrue: [self beCursor].
  15529.     super changed: aParameter! !
  15530.  
  15531. !Cursor methodsFor: 'displaying'!
  15532. beCursor
  15533.     "Primitive. Tell the interpreter to use the receiver as the current cursor 
  15534.     image. Fail if the receiver does not match the size expected by the 
  15535.     hardware. Essential. See Object documentation whatIsAPrimitive."
  15536.  
  15537.     <primitive: 101>
  15538.     self primitiveFailed!
  15539. show
  15540.     "Make the current cursor shape be the receiver."
  15541.  
  15542.     Sensor currentCursor: self!
  15543. showGridded: gridPoint 
  15544.     "Make the current cursor shape be the receiver, forcing the location of the cursor to the point nearest gridPoint."
  15545.     
  15546.     Sensor cursorPoint: (Sensor cursorPoint grid: gridPoint).
  15547.     Sensor currentCursor: self!
  15548. showWhile: aBlock 
  15549.     "While evaluating the argument, aBlock, make the receiver be the cursor 
  15550.     shape."
  15551.  
  15552.     | oldcursor value |
  15553.     oldcursor _ Sensor currentCursor.
  15554.     self show.
  15555.     value _ aBlock value.
  15556.     oldcursor show.
  15557.     ^value! !
  15558.  
  15559. !Cursor methodsFor: 'printing'!
  15560. printOn: aStream
  15561.  
  15562.     self storeOn: aStream base: 2! !
  15563. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  15564.  
  15565. Cursor class
  15566.     instanceVariableNames: ''!
  15567.  
  15568. !Cursor class methodsFor: 'class initialization'!
  15569. initCorner
  15570.  
  15571.     CornerCursor _ 
  15572.         (Cursor 
  15573.             extent: 16@16
  15574.             fromArray: #(
  15575.         2r0000000000000011
  15576.         2r0000000000000011
  15577.         2r0000000000000011
  15578.         2r0000000000000011
  15579.         2r0000000000000011
  15580.         2r0000000000000011
  15581.         2r0000000000000011
  15582.         2r0000000000000011
  15583.         2r0000000000000011
  15584.         2r0000000000000011
  15585.         2r0000000000000011
  15586.         2r0000000000000011
  15587.         2r0000000000000011
  15588.         2r0000000000000011
  15589.         2r1111111111111111
  15590.         2r1111111111111111)
  15591.             offset: -16@-16).
  15592. !
  15593. initCrossHair
  15594.  
  15595.     CrossHairCursor _   
  15596.         (Cursor
  15597.             extent: 16@16
  15598.             fromArray: #(
  15599.         2r0000000100000000
  15600.         2r0000000100000000
  15601.         2r0000000100000000
  15602.         2r0000000100000000
  15603.         2r0000000100000000
  15604.         2r0000000100000000
  15605.         2r0000000100000000
  15606.         2r1111111111111110
  15607.         2r0000000100000000
  15608.         2r0000000100000000
  15609.         2r0000000100000000
  15610.         2r0000000100000000
  15611.         2r0000000100000000
  15612.         2r0000000100000000
  15613.         2r0000000100000000
  15614.         2r0)
  15615.             offset: -7@-7).
  15616.     
  15617.     !
  15618. initDown
  15619.  
  15620.     DownCursor  _
  15621.              (Cursor
  15622.     extent: 16@16
  15623.     fromArray: #(
  15624.         2r11000000000000
  15625.         2r11000000000000
  15626.         2r11000000000000
  15627.         2r11000000000000
  15628.         2r11000000000000
  15629.         2r11000000000000
  15630.         2r11000000000000
  15631.         2r1111110000000000
  15632.         2r111100000000000
  15633.         2r11000000000000
  15634.         2r0
  15635.         2r0
  15636.         2r0
  15637.         2r0
  15638.         2r0
  15639.         2r0)
  15640.     offset: 0@0).
  15641. !
  15642. initialize
  15643.     "Create all the standard cursors
  15644.         Cursor origin
  15645.         Cursor rightArrow
  15646.         Cursor menu
  15647.         Cursor corner
  15648.         Cursor read
  15649.         Cursor write
  15650.         Cursor wait
  15651.         Cursor blank
  15652.         Cursor xeq
  15653.         Cursor square
  15654.         Cursor normal
  15655.         Cursor crossHair
  15656.         Cursor marker
  15657.         Cursor up
  15658.         Cursor down
  15659.         Cursor move"
  15660.  
  15661.         self initOrigin.
  15662.         self initRightArrow.
  15663.         self initMenu.
  15664.         self initCorner.
  15665.         self initRead.
  15666.         self initWrite.
  15667.         self initWait.
  15668.         BlankCursor _ Cursor new.
  15669.         self initXeq.
  15670.         self initSquare.
  15671.         self initNormal.
  15672.         self initCrossHair.
  15673.         self initMarker.
  15674.         self initUp.
  15675.         self initDown.
  15676.         self initMove.
  15677.  
  15678.         "Cursor initialize"
  15679. !
  15680. initMarker
  15681.  
  15682.     MarkerCursor _ 
  15683.         Cursor
  15684.             extent: 16@16
  15685.             fromArray: #(
  15686.         2r0111000000000000
  15687.         2r1111100000000000
  15688.         2r1111100000000000
  15689.         2r0111000000000000
  15690.         2r0
  15691.         2r0
  15692.         2r0
  15693.         2r0
  15694.         2r0
  15695.         2r0
  15696.         2r0
  15697.         2r0
  15698.         2r0
  15699.         2r0
  15700.         2r0
  15701.         2r0)
  15702.             offset: 0@0.
  15703. !
  15704. initMenu 
  15705.  
  15706.     MenuCursor  _
  15707.                 (Cursor
  15708.     extent: 16@16
  15709.     fromArray: #(
  15710.         2r1111111111100000
  15711.         2r1000000000100000
  15712.         2r1010011000100000
  15713.         2r1000000000100000
  15714.         2r1011001010100000
  15715.         2r1000000000100000
  15716.         2r1010110010100000
  15717.         2r1000000000100000
  15718.         2r1010010100100000
  15719.         2r1000000000100000
  15720.         2r1111111111100000
  15721.         2r1101001101100000
  15722.         2r1111111111100000
  15723.         2r1000000000100000
  15724.         2r1010101100100000
  15725.         2r1111111111100000)
  15726.     offset: 0@0).
  15727. !
  15728. initMove
  15729.  
  15730.     MoveCursor _ 
  15731.         Cursor 
  15732.             extent: 16@16
  15733.             fromArray: #(
  15734.         2r1111111111111111
  15735.         2r1111111111111111
  15736.         2r1100000110000011
  15737.         2r1100000110000011
  15738.         2r1100000110000011
  15739.         2r1100000110000011
  15740.         2r1100000110000011
  15741.         2r1111111111111111
  15742.         2r1111111111111111
  15743.         2r1100000110000011
  15744.         2r1100000110000011
  15745.         2r1100000110000011
  15746.         2r1100000110000011
  15747.         2r1100000110000011
  15748.         2r1111111111111111
  15749.         2r1111111111111111)
  15750.             offset: 0@0.
  15751. !
  15752. initNormal
  15753.  
  15754.     NormalCursor _   
  15755.         (Cursor
  15756.             extent: 16@16
  15757.             fromArray: #(
  15758.         2r1000000000000000
  15759.         2r1100000000000000
  15760.         2r1110000000000000
  15761.         2r1111000000000000
  15762.         2r1111100000000000
  15763.         2r1111110000000000
  15764.         2r1111111000000000
  15765.         2r1111100000000000
  15766.         2r1111100000000000
  15767.         2r1001100000000000
  15768.         2r0000110000000000
  15769.         2r0000110000000000
  15770.         2r0000011000000000
  15771.         2r0000011000000000
  15772.         2r0000001100000000
  15773.         2r0000001100000000)
  15774.     offset: 0@0).
  15775.  
  15776.     
  15777.     !
  15778. initOrigin
  15779.  
  15780.     OriginCursor _   
  15781.         (Cursor
  15782.             extent: 16@16
  15783.             fromArray: #(
  15784.         2r1111111111111111
  15785.         2r1111111111111111
  15786.         2r1100000000000000
  15787.         2r1100000000000000
  15788.         2r1100000000000000
  15789.         2r1100000000000000
  15790.         2r1100000000000000
  15791.         2r1100000000000000
  15792.         2r1100000000000000
  15793.         2r1100000000000000
  15794.         2r1100000000000000
  15795.         2r1100000000000000
  15796.         2r1100000000000000
  15797.         2r1100000000000000
  15798.         2r1100000000000000
  15799.         2r1100000000000000)
  15800.             offset: 0@0).
  15801. !
  15802. initRead
  15803.  
  15804.     ReadCursor _  
  15805.         (Cursor
  15806.             extent: 16@16
  15807.             fromArray: #(
  15808.         2r0000110000000110
  15809.         2r0001001000001001
  15810.         2r0001001000001001
  15811.         2r0010000000010000
  15812.         2r0100000000100000
  15813.         2r1111101111100000
  15814.         2r1000010000100000
  15815.         2r1000010000100000
  15816.         2r1011010110100000
  15817.         2r0111101111000000
  15818.         2r0
  15819.         2r0
  15820.         2r0
  15821.         2r0
  15822.         2r0
  15823.         2r0)
  15824.     offset: 0@0).
  15825. !
  15826. initRightArrow 
  15827.  
  15828.     RightArrowCursor  _
  15829.               (Cursor
  15830.     extent: 16@16
  15831.     fromArray: #(
  15832.         2r100000000000
  15833.         2r111000000000
  15834.         2r1111111110000000
  15835.         2r111000000000
  15836.         2r100000000000
  15837.         2r0
  15838.         2r0
  15839.         2r0
  15840.         2r0
  15841.         2r0
  15842.         2r0
  15843.         2r0
  15844.         2r0
  15845.         2r0
  15846.         2r0
  15847.         2r0)
  15848.     offset: 0@0).
  15849.     
  15850.     "Cursor initRightArrow"!
  15851. initSquare
  15852.  
  15853.     SquareCursor _ 
  15854.         (Cursor
  15855.             extent: 16@16
  15856.             fromArray: #(
  15857.         2r0
  15858.         2r0
  15859.         2r0
  15860.         2r0
  15861.         2r0
  15862.         2r0000001111000000
  15863.         2r0000001111000000
  15864.         2r0000001111000000
  15865.         2r0000001111000000
  15866.         2r0
  15867.         2r0
  15868.         2r0
  15869.         2r0
  15870.         2r0
  15871.         2r0
  15872.         2r0)
  15873.     offset: -8@-8).
  15874.  
  15875.     !
  15876. initUp
  15877.  
  15878.     UpCursor _ 
  15879.             (Cursor
  15880.     extent: 16@16
  15881.     fromArray: #(
  15882.         2r11000000000000
  15883.         2r111100000000000
  15884.         2r1111110000000000
  15885.         2r11000000000000
  15886.         2r11000000000000
  15887.         2r11000000000000
  15888.         2r11000000000000
  15889.         2r11000000000000
  15890.         2r11000000000000
  15891.         2r11000000000000
  15892.         2r0
  15893.         2r0
  15894.         2r0
  15895.         2r0
  15896.         2r0
  15897.         2r0)
  15898.     offset: 0@0).
  15899. !
  15900. initWait
  15901.  
  15902.     WaitCursor _ 
  15903.           (Cursor
  15904.             extent: 16@16
  15905.             fromArray: #(
  15906.         2r1111111111111111
  15907.         2r1000000000000001
  15908.         2r0100000000000010
  15909.         2r0010000000000100
  15910.         2r0001110000111000
  15911.         2r0000111101110000
  15912.         2r0000011011100000
  15913.         2r0000001111000000
  15914.         2r0000001111000000
  15915.         2r0000010110100000
  15916.         2r0000100010010000
  15917.         2r0001000110001000
  15918.         2r0010001101000100
  15919.         2r0100111111110010
  15920.         2r1011111111111101
  15921.         2r1111111111111111)
  15922.             offset: 0@0).
  15923. !
  15924. initWrite
  15925.  
  15926.     WriteCursor _ (Cursor
  15927.     extent: 16@16
  15928.     fromArray: #(
  15929.         2r0000000000000110
  15930.         2r0000000000001111
  15931.         2r0000000000010110
  15932.         2r0000000000100100
  15933.         2r0000000001001000
  15934.         2r0000000010010000
  15935.         2r0000000100100000
  15936.         2r0000001001000011
  15937.         2r0000010010000010
  15938.         2r0000100100000110
  15939.         2r0001001000001000
  15940.         2r0010010000001000
  15941.         2r0111100001001000
  15942.         2r0101000010111000
  15943.         2r0110000110000000
  15944.         2r1111111100000000)
  15945.     offset: 0@0).
  15946. !
  15947. initXeq
  15948.  
  15949.     XeqCursor _ 
  15950.         (Cursor
  15951.             extent: 16@16
  15952.             fromArray: #(
  15953.         2r1000000000010000
  15954.         2r1100000000010000
  15955.         2r1110000000111000
  15956.         2r1111000111111111
  15957.         2r1111100011000110
  15958.         2r1111110001000100
  15959.         2r1111111001111100
  15960.         2r1111000001101100
  15961.         2r1101100011000110
  15962.         2r1001100010000010
  15963.         2r0000110000000000
  15964.         2r0000110000000000
  15965.         2r0000011000000000
  15966.         2r0000011000000000
  15967.         2r0000001100000000
  15968.         2r0000001100000000)
  15969.     offset: 0@0).
  15970. !
  15971. startUp
  15972.     self currentCursor: self currentCursor! !
  15973.  
  15974. !Cursor class methodsFor: 'instance creation'!
  15975. extent: extentPoint fromArray: anArray offset: offsetPoint 
  15976.     "Answer a new instance of me with width and height specified by
  15977.     extentPoint, offset by offsetPoint, and bits from anArray.
  15978.     NOTE: This has been kluged to take an array of 16-bit constants,
  15979.     and shift them over so they are left-justified in a 32-bit bitmap"
  15980.  
  15981.     extentPoint = (16 @ 16)
  15982.         ifTrue: 
  15983.             [^ super
  15984.                 extent: extentPoint
  15985.                 fromArray: (anArray collect: [:bits | bits bitShift: 16])
  15986.                 offset: offsetPoint]
  15987.         ifFalse: [self error: 'cursors must be 16@16']!
  15988. new
  15989.  
  15990.     ^self
  15991.         extent: 16 @ 16
  15992.         fromArray: Array new
  15993.         offset: 0 @ 0
  15994.  
  15995.     "Cursor new bitEdit show"! !
  15996.  
  15997. !Cursor class methodsFor: 'current cursor'!
  15998. currentCursor
  15999.     "Answer the instance of Cursor that is the one currently displayed."
  16000.  
  16001.     ^CurrentCursor!
  16002. currentCursor: aCursor 
  16003.     "Make the instance of cursor, aCursor, be the current cursor. Display it. 
  16004.     Create an error if the argument is not a Cursor."
  16005.  
  16006.     aCursor class == self
  16007.         ifTrue: 
  16008.             [CurrentCursor _ aCursor.
  16009.             aCursor beCursor]
  16010.         ifFalse: [self error: 'The new cursor must be an instance of class Cursor']! !
  16011.  
  16012. !Cursor class methodsFor: 'constants'!
  16013. blank
  16014.     "Answer the instance of me that is all white."
  16015.  
  16016.     ^BlankCursor!
  16017. bottomLeft
  16018.     "Cursor bottomLeft showWhile: [Sensor waitButton]"
  16019.     ^ (Cursor extent: 16@16
  16020.             fromArray: #(
  16021.         2r1100000000000000
  16022.         2r1100000000000000
  16023.         2r1100000000000000
  16024.         2r1100000000000000
  16025.         2r1100000000000000
  16026.         2r1100000000000000
  16027.         2r1100000000000000
  16028.         2r1100000000000000
  16029.         2r1100000000000000
  16030.         2r1100000000000000
  16031.         2r1100000000000000
  16032.         2r1100000000000000
  16033.         2r1100000000000000
  16034.         2r1100000000000000
  16035.         2r1111111111111111
  16036.         2r1111111111111111)
  16037.             offset: 0@-16).
  16038. !
  16039. bottomRight
  16040.     "Cursor bottomRight showWhile: [Sensor waitButton]"
  16041.     ^ (Cursor extent: 16@16
  16042.             fromArray: #(
  16043.         2r0000000000000011
  16044.         2r0000000000000011
  16045.         2r0000000000000011
  16046.         2r0000000000000011
  16047.         2r0000000000000011
  16048.         2r0000000000000011
  16049.         2r0000000000000011
  16050.         2r0000000000000011
  16051.         2r0000000000000011
  16052.         2r0000000000000011
  16053.         2r0000000000000011
  16054.         2r0000000000000011
  16055.         2r0000000000000011
  16056.         2r0000000000000011
  16057.         2r1111111111111111
  16058.         2r1111111111111111)
  16059.             offset: -16@-16).
  16060. !
  16061. corner
  16062.     "Answer the instance of me that is the shape of the bottom right corner 
  16063.     of a rectangle."
  16064.  
  16065.     ^CornerCursor!
  16066. crossHair
  16067.     "Answer the instance of me that is the shape of a cross."
  16068.  
  16069.     ^CrossHairCursor!
  16070. down
  16071.     "Answer the instance of me that is the shape of an arrow facing 
  16072.     downward."
  16073.  
  16074.     ^DownCursor!
  16075. execute
  16076.     "Answer the instance of me that is the shape of an arrow slanted left 
  16077.     with a star next to it."
  16078.  
  16079.     ^XeqCursor!
  16080. marker
  16081.     "Answer the instance of me that is the shape of a small ball."
  16082.  
  16083.     ^MarkerCursor!
  16084. menu 
  16085.     "Answer the instance of me that is the shape of a menu."
  16086.  
  16087.     ^MenuCursor!
  16088. move
  16089.     "Answer the instance of me that is the shape of a cross inside a square."
  16090.  
  16091.     ^MoveCursor!
  16092. normal
  16093.     "Answer the instance of me that is the shape of an arrow slanted left."
  16094.  
  16095.     ^NormalCursor!
  16096. origin
  16097.     "Answer the instance of me that is the shape of the top left corner of a 
  16098.     rectangle."
  16099.  
  16100.     ^OriginCursor!
  16101. read
  16102.     "Answer the instance of me that is the shape of eyeglasses."
  16103.  
  16104.     ^ReadCursor!
  16105. rightArrow 
  16106.     "Answer the instance of me that is the shape of an arrow pointing to the right."
  16107.  
  16108.     ^RightArrowCursor!
  16109. square
  16110.     "Answer the instance of me that is the shape of a square."
  16111.  
  16112.     ^SquareCursor!
  16113. topLeft
  16114.     "Cursor topLeft showWhile: [Sensor waitButton]"
  16115.     ^ (Cursor extent: 16@16
  16116.             fromArray: #(
  16117.         2r1111111111111111
  16118.         2r1111111111111111
  16119.         2r1100000000000000
  16120.         2r1100000000000000
  16121.         2r1100000000000000
  16122.         2r1100000000000000
  16123.         2r1100000000000000
  16124.         2r1100000000000000
  16125.         2r1100000000000000
  16126.         2r1100000000000000
  16127.         2r1100000000000000
  16128.         2r1100000000000000
  16129.         2r1100000000000000
  16130.         2r1100000000000000
  16131.         2r1100000000000000
  16132.         2r1100000000000000)
  16133.             offset: 0@0).
  16134. !
  16135. topRight
  16136.     "Cursor topRight showWhile: [Sensor waitButton]"
  16137.     ^ (Cursor extent: 16@16
  16138.             fromArray: #(
  16139.         2r1111111111111111
  16140.         2r1111111111111111
  16141.         2r0000000000000011
  16142.         2r0000000000000011
  16143.         2r0000000000000011
  16144.         2r0000000000000011
  16145.         2r0000000000000011
  16146.         2r0000000000000011
  16147.         2r0000000000000011
  16148.         2r0000000000000011
  16149.         2r0000000000000011
  16150.         2r0000000000000011
  16151.         2r0000000000000011
  16152.         2r0000000000000011
  16153.         2r0000000000000011
  16154.         2r0000000000000011)
  16155.             offset: -16@0).
  16156. !
  16157. up
  16158.     "Answer the instance of me that is the shape of an arrow facing upward."
  16159.  
  16160.     ^UpCursor!
  16161. wait
  16162.     "Answer the instance of me that is the shape of an Hourglass (was in the 
  16163.     shape of three small balls)."
  16164.  
  16165.     ^WaitCursor!
  16166. write
  16167.     "Answer the instance of me that is the shape of a pen writing."
  16168.  
  16169.     ^WriteCursor! !
  16170.  
  16171. Cursor initialize!
  16172. Path subclass: #Curve
  16173.     instanceVariableNames: ''
  16174.     classVariableNames: ''
  16175.     poolDictionaries: ''
  16176.     category: 'Graphics-Paths'!
  16177. Curve comment:
  16178. 'I represent a conic section determined by three points p1,p2 and p3. I interpolate p1 and p3 and am tangent to line p1,p2 at p1 and line p3,p2 at p3.'!
  16179.  
  16180. !Curve methodsFor: 'displaying'!
  16181. displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
  16182.  
  16183.     | pa pb k s p1 p2 p3 line |
  16184.     line _ Line new.
  16185.     line form: self form.
  16186.     collectionOfPoints size < 3 ifTrue: [self error: 'Curve must have three points'].
  16187.     p1 _ self firstPoint.
  16188.     p2 _ self secondPoint.
  16189.     p3 _ self thirdPoint.
  16190.     s _ Path new.
  16191.     s add: p1.
  16192.     pa _ p2 - p1.
  16193.     pb _ p3 - p2.
  16194.     k _ 5 max: pa x abs + pa y abs + pb x abs + pb y abs // 20.
  16195.     "k is a guess as to how many line segments to use to approximate 
  16196.     the curve."
  16197.     1 to: k do: 
  16198.         [:i | 
  16199.         s add: pa * i // k + p1 * (k - i) + (pb * (i - 1) // k + p2 * (i - 1)) // (k - 1)].
  16200.     s add: p3.
  16201.     1 to: s size - 1 do: 
  16202.         [:i | 
  16203.         line beginPoint: (s at: i).
  16204.         line endPoint: (s at: i + 1).
  16205.         line displayOn: aDisplayMedium
  16206.             at: aPoint
  16207.             clippingBox: clipRect
  16208.             rule: anInteger
  16209.             fillColor: aForm]!
  16210. displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
  16211.  
  16212.     | transformedPath newCurve |
  16213.     transformedPath _ aTransformation applyTo: self.
  16214.     newCurve _ Curve new.
  16215.     newCurve firstPoint: transformedPath firstPoint.
  16216.     newCurve secondPoint: transformedPath secondPoint.
  16217.     newCurve thirdPoint: transformedPath thirdPoint.
  16218.     newCurve form: self form.
  16219.     newCurve
  16220.         displayOn: aDisplayMedium
  16221.         at: 0 @ 0
  16222.         clippingBox: clipRect
  16223.         rule: anInteger
  16224.         fillColor: aForm! !
  16225. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  16226.  
  16227. Curve class
  16228.     instanceVariableNames: ''!
  16229.  
  16230. !Curve class methodsFor: 'instance creation'!
  16231. new
  16232.  
  16233.     | newSelf | 
  16234.     newSelf _ super new: 3.
  16235.     newSelf add: 0@0.
  16236.     newSelf add: 0@0.
  16237.     newSelf add: 0@0.
  16238.     ^newSelf! !
  16239.  
  16240. !Curve class methodsFor: 'examples'!
  16241. example
  16242.     "Designate three locations on the screen by clicking any button. The
  16243.     curve determined by the points will be displayed with a long black form."
  16244.  
  16245.     | aCurve aForm |  
  16246.     aForm _ Form extent: 1@30.            "make a long thin Form for display "
  16247.     aForm fillBlack.                            "turn it black"
  16248.     aCurve _ Curve new.
  16249.     aCurve form: aForm.                        "set the form for display"
  16250.                 "collect three Points and show them on the dispaly"
  16251.     aCurve firstPoint: Sensor waitButton. Sensor waitNoButton.
  16252.     aForm displayOn: Display at: aCurve firstPoint.
  16253.     aCurve secondPoint: Sensor waitButton. Sensor waitNoButton.
  16254.     aForm displayOn: Display at: aCurve secondPoint.
  16255.     aCurve thirdPoint: Sensor waitButton. Sensor waitNoButton.
  16256.     aForm displayOn: Display at: aCurve thirdPoint.
  16257.  
  16258.     aCurve displayOn: Display                    "display the Curve"
  16259.  
  16260.     "Curve example"! !Stream subclass: #DataStream
  16261.     instanceVariableNames: 'byteStream '
  16262.     classVariableNames: 'TypeMap '
  16263.     poolDictionaries: ''
  16264.     category: 'Object Storage'!
  16265. DataStream comment:
  16266. 'This is an interim save-to-disk facility. A DataStream can store one
  16267. or more objects in a persistent form.
  16268.  
  16269. To handle objects with sharing and cycles, you must use a
  16270. ReferenceStream instead of a DataStream. ReferenceStream is typically
  16271. faster and produces smaller files because it doesn''t repeatedly write
  16272. the same class Symbols.
  16273.  
  16274. Here is the way to use DataStream and ReferenceStream:
  16275.     rr _ ReferenceStream fileNamed: ''test.obj''.
  16276.     rr nextPut: <your object>.
  16277.     rr close.
  16278.  
  16279. To get it back:
  16280.     rr _ ReferenceStream fileNamed: ''test.obj''.
  16281.     <your object> _ rr next.
  16282.     rr close.
  16283.  
  16284. Each object to be stored has two opportunities to control what gets stored. The high level, more useful hook is objectToStoreOnDataStream [externalize]. The low level hook is storeDataOn:. The read-in counterparts to these messages are comeFullyUpOnReload [internalize] and (class) readDataFrom:size:. See these methods, the class DiskProxy, and the class IOWeakArray for more information about externalizing and internalizing.
  16285.  
  16286. Public messages:
  16287.     (class) on:
  16288.     (class) fileNamed:
  16289.     (class) fileTypeCode
  16290.     atEnd
  16291.     beginInstance:size: (for use by storeDataOn: methods)
  16292.     beginReference: (for use by readDataFrom:size: methods)
  16293.     close
  16294.     next
  16295.     next:
  16296.     nextPut:
  16297.     nextPutAll:
  16298.     reset
  16299.     setType:
  16300.     size
  16301.  
  16302. NOTE: A DataStream should be treated as a read-stream *or* as a
  16303. write-stream, *not* as a read/write-stream.
  16304.  
  16305. [TBD] We should be able to make this much faster via tight-loop
  16306. byte-string I/O. It looks like FileStream (and WriteStream)
  16307. nextPutAll: do a reasonable job *if* it doesn''t have to push the
  16308. writeLimit, in which case it iterates with nextPut:. It could in many
  16309. cases set the writeLimit and then use the fast case
  16310. (replaceFrom:to:with:startingAt:), or fill a buffer at at time via
  16311. the fast case working on a substring.
  16312.     This approach would handle Strings, ByteArrays, and all other
  16313. variable-byte classes. If(nextPutAll: aCollection) in some cases
  16314. still reverts to (aCollection do: [:e | self nextPut: e]), then we''d
  16315. want to make Obj respond to do:. Then we could speed up inner
  16316. loop activities like nextPutInt32:.
  16317.  
  16318. [TBD] Every DataStream should begin with 4 signature bytes.
  16319. "on:" should emit or check the signature. But the current mechanism doesn''t always
  16320. know when the stream is started or ended.
  16321.  
  16322. [TBD] Cf. notes in DataStream>>beginInstance:size: and
  16323. Object>>readDataFrom:size:.
  16324.  
  16325. [TBD] We could save disk space & I/O time by using short, 1-byte size
  16326. fields whenever possible. E.g. almost all Symbols are shorter than
  16327. 256 chars. We could do this either by (1) using different typeID codes
  16328. to indicate when a 1-byte length follows, a scheme which could still
  16329. read all the old files but would take more code, or (2) a
  16330. variable-length code for sizes.
  16331.     -- 11/15/92 jhm'!
  16332.  
  16333. !DataStream methodsFor: 'as yet unclassified'!
  16334. atEnd
  16335.     "Answer true if the stream is at the end."
  16336.  
  16337.     ^ byteStream atEnd!
  16338. beginInstance: aClass size: anInteger
  16339.     "This is for use by storeDataOn: methods.
  16340.      Cf. Object>>storeDataOn:."
  16341.  
  16342.         "Addition of 1 seems to make extra work, since readInstance
  16343.         has to compensate.  Here for historical reasons dating back
  16344.         to Kent Beck's original implementation in late 1988.
  16345.  
  16346.         Also, we could save 5 bytes per instance by putting a Str255
  16347.         on byteStream instead of putting a Symbol on self (which
  16348.         entails a 1-byte type tag and a 4-byte length count).
  16349.  
  16350.         Also, we could be more robust by emitting info indicating
  16351.         whether aClass is fixed or variable, pointer or bytes, and
  16352.         how many instance vars it has."
  16353.  
  16354.     byteStream nextNumber: 4 put: anInteger + 1.
  16355.  
  16356.     self nextPut: aClass name!
  16357. beginReference: anObject
  16358.     "We╒re starting to read anObject. Remember it and its reference
  16359.      position (if we care; ReferenceStream cares). Answer the
  16360.      reference position."
  16361.  
  16362.     ^ 0!
  16363. errorWriteReference: anInteger
  16364.     "PRIVATE -- Raise an error because this case of nextPut:╒s perform:
  16365.      shouldn't be called. -- 11/15/92 jhm"
  16366.  
  16367.     self error: 'This should never be called'!
  16368. flush
  16369.     "Guarantee that any writes to me are actually recorded on disk. -- 11/17/92 jhm"
  16370.  
  16371.     ^ byteStream flush!
  16372. getCurrentReference
  16373.     "PRIVATE -- Return the currentReference posn.
  16374.      Overridden by ReferenceStream."
  16375.  
  16376.     ^ 0!
  16377. internalize: externalObject
  16378.     "PRIVATE -- We just read externalObject. Give it a chance to
  16379.         internalize. Return the internalized object."
  16380.  
  16381.     ^ externalObject comeFullyUpOnReload!
  16382. next: anInteger
  16383.     "Answer an Array of the next anInteger objects in the stream."
  16384.     | array |
  16385.  
  16386.     array _ Array new: anInteger.
  16387.     1 to: anInteger do: [:i |
  16388.         array at: i put: self next].
  16389.     ^ array!
  16390. nextPutAll: aCollection
  16391.     "Write each of the objects in aCollection to the
  16392.      receiver stream. Answer aCollection."
  16393.  
  16394.     ^ aCollection do: [:each | self nextPut: each]!
  16395. noteCurrentReference: typeID
  16396.     "PRIVATE -- If we support references for type typeID, remember
  16397.      the current byteStream position so we can add the next object to
  16398.      the ╘objects╒ dictionary, and return true. Else return false.
  16399.      This method is here to be overridden by ReferenceStream"
  16400.  
  16401.     ^ false!
  16402. objectAt: anInteger
  16403.     "PRIVATE -- Read & return the object at a given stream position.
  16404.      11/16/92 jhm: Renamed local variable to not clash with an instance variable."
  16405.     | savedPosn anObject refPosn |
  16406.  
  16407.     savedPosn _ byteStream position.
  16408.     refPosn _ self getCurrentReference.
  16409.  
  16410.     byteStream position: anInteger.
  16411.     anObject _ self next.
  16412.  
  16413.     self setCurrentReference: refPosn.
  16414.     byteStream position: savedPosn.
  16415.     ^ anObject!
  16416. outputReference: referencePosn
  16417.     "PRIVATE -- Output a reference to the object at integer stream position
  16418.      referencePosn. To output a weak reference to an object not yet written, supply
  16419.      (self vacantRef) for referencePosn. -- 11/15/92 jhm"
  16420.  
  16421.     byteStream nextPut: 10. "reference typeID"
  16422.     byteStream nextNumber: 4 put: referencePosn!
  16423. readArray
  16424.     "PRIVATE -- Read the contents of an Array.
  16425.      We must do beginReference: here after instantiating the Array
  16426.      but before reading its contents, in case the contents reference
  16427.      the Array. beginReference: will be sent again when we return to
  16428.      next, but that╒s ok as long as we save and restore the current
  16429.      reference position over recursive calls to next."
  16430.     | count array refPosn |
  16431.  
  16432.     count _ byteStream nextNumber: 4.
  16433.  
  16434.     refPosn _ self beginReference: (array _ Array new: count).
  16435.     1 to: count do: [:i |
  16436.         array at: i put: self next].
  16437.     self setCurrentReference: refPosn.
  16438.     ^ array!
  16439. readBitmap
  16440.     "PRIVATE -- Read the contents of a Bitmap."
  16441.  
  16442.     ^ Bitmap newFromStream: byteStream
  16443.     "Note that the reader knows that the size is in long words, but the data is in bytes."!
  16444. readBoolean
  16445.     "PRIVATE -- Read the contents of a Boolean.
  16446.      This is here only for compatibility with old data files."
  16447.  
  16448.     ^ byteStream next ~= 0!
  16449. readByteArray
  16450.     "PRIVATE -- Read the contents of a ByteArray."
  16451.     | count buffer |
  16452.  
  16453.     count _ byteStream nextNumber: 4.
  16454.     ^ (ByteArray new: count)
  16455.         replaceFrom: 1 to: count with: (byteStream next: count)!
  16456. readFalse
  16457.     "PRIVATE -- Read the contents of a False."
  16458.  
  16459.     ^ false!
  16460. readFloat
  16461.     "PRIVATE -- Read the contents of a Float.
  16462.      This is the fast way to read a Float.
  16463.      We support 8-byte Floats here.  Non-IEEE"
  16464.  
  16465.     | new |
  16466.     new _ Float new: 2.        "To get an instance"
  16467.     new at: 1 put: (byteStream nextNumber: 4).
  16468.     new at: 2 put: (byteStream nextNumber: 4).
  16469.     ^ new!
  16470. readFloatString
  16471.     "PRIVATE -- Read the contents of a Float string.
  16472.      This is the slow way to read a Float--via its string rep╒n.
  16473.      It's here for compatibility with old data files."
  16474.  
  16475.     ^ Float readFrom: (byteStream next: (byteStream nextNumber: 4))!
  16476. readInteger
  16477.     "PRIVATE -- Read the contents of a SmallInteger."
  16478.  
  16479.     ^ byteStream nextInt32    "signed!!!!!!"!
  16480. readNil
  16481.     "PRIVATE -- Read the contents of an UndefinedObject."
  16482.  
  16483.     ^ nil!
  16484. readReference
  16485.     "PRIVATE -- Read the contents of an object reference. Cf. outputReference:.
  16486.      11/15/92 jhm: Support weak references."
  16487.     | referencePosition |
  16488.  
  16489.     ^ (referencePosition _ (byteStream nextNumber: 4)) = self vacantRef
  16490.         ifTrue:  [nil]
  16491.         ifFalse: [self objectAt: referencePosition]!
  16492. readString
  16493.     "PRIVATE -- Read the contents of a String."
  16494.  
  16495.     ^ byteStream nextString!
  16496. readSymbol
  16497.     "PRIVATE -- Read the contents of a Symbol."
  16498.  
  16499.     ^ self readString asSymbol!
  16500. readTrue
  16501.     "PRIVATE -- Read the contents of a True."
  16502.  
  16503.     ^ true!
  16504. reset
  16505.     "Reset the stream."
  16506.  
  16507.     byteStream reset!
  16508. setCurrentReference: refPosn
  16509.     "PRIVATE -- Set currentReference to refPosn.
  16510.      Noop here. Cf. ReferenceStream."!
  16511. setStream: aStream
  16512.     "PRIVATE -- Initialization method."
  16513.  
  16514.     byteStream _ aStream!
  16515. setType
  16516.     "Set my backing stream's file type code to my default file type code.
  16517.      ASSUMES: My backing stream is a file stream. -- 11/13/92 jhm
  16518.     For now, we do not control the Mac type and creator of the file  7/26/96 tk"
  16519.  
  16520.    " self setType: self class fileTypeCode"!
  16521. setType: typeString
  16522.     "Set my backing stream's file type code.
  16523.      ASSUMES: My backing stream is a file stream. -- 11/13/92 jhm"
  16524.  
  16525.     byteStream setType: typeString!
  16526. size
  16527.     "Answer the stream's size."
  16528.  
  16529.     ^ byteStream size!
  16530. tryToPutReference: anObject typeID: typeID
  16531.     "PRIVATE -- If we support references for type typeID, and if
  16532.        anObject already appears in my output stream, then put a
  16533.        reference to the place where anObject already appears. If we
  16534.        support references for typeID but didn╒t already put anObject,
  16535.        then associate the current stream position with anObject in
  16536.        case one wants to nextPut: it again.
  16537.      Return true after putting a reference; false if the object still
  16538.        needs to be put.
  16539.      For DataStream this is trivial. ReferenceStream overrides this."
  16540.  
  16541.     ^ false!
  16542. vacantRef
  16543.     "Answer the magic 32-bit constant we use ***ON DISK*** as a stream ╥reference
  16544.      position╙ to identify a reference that╒s not yet filled in. This must be a
  16545.      value that won╒t be used as an ordinary reference. Cf. outputReference: and
  16546.      readReference. -- 11/15/92 jhm
  16547.      NOTE: We could use a different type ID for vacant-refs rather than writing
  16548.         object-references with a magic value. (The type ID and value are
  16549.         overwritten by ordinary object-references when weak refs are fullfilled.)
  16550.         The current approach is convenient but wouldn't work if we changed object-
  16551.         references to relative positions."
  16552.  
  16553.     ^ -1!
  16554. writeArray: anArray
  16555.     "PRIVATE -- Write the contents of an Array."
  16556.  
  16557.     byteStream nextNumber: 4 put: anArray size.
  16558.     self nextPutAll: anArray.!
  16559. writeBitmap: aBitmap
  16560.     "PRIVATE -- Write the contents of a Bitmap."
  16561.  
  16562.     aBitmap writeOn: byteStream
  16563.     "Note that this calls (byteStream nextPutAll: aBitmap) which knows enough to put 4-byte quantities on the stream!!  Reader must know that size is in long words."!
  16564. writeBoolean: aBoolean
  16565.     "PRIVATE -- Write the contents of a Boolean.
  16566.      This method is now obsolete."
  16567.  
  16568.     byteStream nextPut: (aBoolean ifTrue: [1] ifFalse: [0])!
  16569. writeByteArray: aByteArray
  16570.     "PRIVATE -- Write the contents of a ByteArray."
  16571.  
  16572.     byteStream nextNumber: 4 put: aByteArray size.
  16573.     "May have to convert types here..."
  16574.     byteStream nextPutAll: aByteArray.!
  16575. writeFalse: aFalse
  16576.     "PRIVATE -- Write the contents of a False."!
  16577. writeFloat: aFloat
  16578.     "PRIVATE -- Write the contents of a Float.
  16579.       We support 8-byte Floats here."
  16580.  
  16581.     byteStream nextNumber: 4 put: (aFloat at: 1).
  16582.     byteStream nextNumber: 4 put: (aFloat at: 2).
  16583. !
  16584. writeFloatString: aFloat
  16585.     "PRIVATE -- Write the contents of a Float string.
  16586.      This is the slow way to write a Float--via its string rep╒n."
  16587.  
  16588.     self writeByteArray: (aFloat printString)!
  16589. writeInstance: anObject
  16590.     "PRIVATE -- Write the contents of an arbitrary instance."
  16591.  
  16592.     ^ anObject storeDataOn: self!
  16593. writeInteger: anInteger
  16594.     "PRIVATE -- Write the contents of a SmallInteger."
  16595.  
  16596.     byteStream nextInt32Put: anInteger    "signed!!!!!!!!!!"!
  16597. writeNil: anUndefinedObject
  16598.     "PRIVATE -- Write the contents of an UndefinedObject."!
  16599. writeString: aString
  16600.     "PRIVATE -- Write the contents of a String."
  16601.  
  16602.     aString size < 16384 
  16603.         ifTrue: [byteStream nextStringPut: aString]
  16604.         ifFalse: [self writeByteArray: aString].    "takes more space"!
  16605. writeSymbol: aSymbol
  16606.     "PRIVATE -- Write the contents of a Symbol."
  16607.  
  16608.     self writeString: aSymbol!
  16609. writeTrue: aTrue
  16610.     "PRIVATE -- Write the contents of a True."! !
  16611.  
  16612. !DataStream methodsFor: 'imported from V'!
  16613. checkForPaths: anObject
  16614.     "After an object is fully internalized, it should have no PathFromHome in it.    The only exceptiuon in Array, as pointed to by an IncomingObjects.  8/16/96 tk"
  16615.  
  16616.     1 to: anObject class instSize do:
  16617.         [:i | (anObject instVarAt: i) class == PathFromHome ifTrue: [
  16618.             self error: 'Unresolved Path']].
  16619. !
  16620. close
  16621.     "Close the stream."
  16622.  
  16623.     | bytes |
  16624.     bytes _ byteStream position.
  16625.     byteStream close.
  16626.     ^ bytes!
  16627. next
  16628.     "Answer the next object in the stream."
  16629.     | type selector anObject isARefType |
  16630.  
  16631.     type _ byteStream next.
  16632.     isARefType _ self noteCurrentReference: type.
  16633.     selector _ #(readNil readTrue readFalse readInteger
  16634.             readString readSymbol readByteArray
  16635.             readArray readInstance readReference readBitmap
  16636.             readClass readUser readFloat) at: type.
  16637.     anObject _ self perform: selector. "A method that recursively
  16638.         calls next (readArray, readInstance, objectAt:) must save &
  16639.         restore the current reference position."
  16640.     isARefType ifTrue: [self beginReference: anObject].
  16641.  
  16642.     "After reading the externalObject, internalize it.
  16643.      #readReference is a special case. Either:
  16644.        (1) We actually have to read the object, recursively calling
  16645.            next, which internalizes the object.
  16646.        (2) We just read a reference to an object already read and
  16647.            thus already interalized.
  16648.      Either way, we must not re-internalize the object here."
  16649.     selector == #readReference ifFalse:
  16650.         [anObject _ self internalize: anObject.
  16651.         self checkForPaths: anObject].
  16652.     ^ anObject!
  16653. nextPut: anObject
  16654.     "Write anObject to the receiver stream. Answer anObject.
  16655.      NOTE: If anObject is a reference type (one that we write cross-references to) but its externalized form (result of objectToStoreOnDataStream) isn╒t (e.g. CompiledMethod and ViewState), then we should remember its externalized form
  16656.  but not add to ╘references╒. Putting that object again should just put its
  16657.  external form again. That╒s more compact and avoids seeks when reading.
  16658.  But we just do the simple thing here, allowing backward-references for
  16659.  non-reference types like nil. So objectAt: has to compensate. Objects that
  16660.  externalize nicely won╒t contain the likes of ViewStates, so this shouldn╒t
  16661.  hurt much.
  16662.      11/15/92 jhm: writeReference: -> errorWriteReference:."
  16663.     | typeID selector objectToStore |
  16664.  
  16665.     typeID _ self typeIDFor: anObject.
  16666.     (self tryToPutReference: anObject typeID: typeID)
  16667.         ifTrue: [^ anObject].
  16668.  
  16669.     (objectToStore _ anObject objectToStoreOnDataStream) == anObject
  16670.         ifFalse: [typeID _ self typeIDFor: objectToStore].
  16671.  
  16672.     byteStream nextPut: typeID.
  16673.     selector _ #(writeNil: writeTrue: writeFalse: writeInteger: 
  16674.         writeString: writeSymbol: writeByteArray:
  16675.         writeArray: writeInstance: errorWriteReference: writeBitmap:
  16676.         writeClass: writeUser: writeFloat:) at: typeID.
  16677.     self perform: selector with: objectToStore.
  16678.  
  16679.     ^ anObject!
  16680. readClass
  16681.     "PRIVATE -- For now, no classes may be written.  HyperSqueak user unique classes have not state other than methods and should be reconstructed.  Could read standard fileOut code here if necessary.  7/29/96 tk."
  16682.  
  16683.     "do nothing"!
  16684. readInstance
  16685.     "PRIVATE -- Read the contents of an arbitrary instance.
  16686.      ASSUMES: readDataFrom:size: sends me beginReference: after it
  16687.        instantiates the new object but before reading nested objects.
  16688.      NOTE: We must restore the current reference position after
  16689.        recursive calls to next."
  16690.     | instSize aSymbol refPosn anObject |
  16691.  
  16692.     instSize _ (byteStream nextNumber: 4) - 1.
  16693.     refPosn _ self getCurrentReference.
  16694.     aSymbol _ self next.
  16695.     self setCurrentReference: refPosn.  "before readDataFrom:size:"
  16696.     aSymbol endsWithDigit ifTrue: [
  16697.         self flag: #hot.
  16698.         "Remove this once we know no Alias123 are written"
  16699.         aSymbol _ aSymbol stemAndNumericSuffix at: 1].
  16700.     anObject _ (Smalltalk at: aSymbol asSymbol)
  16701.         readDataFrom: self size: instSize.
  16702.     self setCurrentReference: refPosn.  "before returning to next"
  16703.     ^ anObject!
  16704. readUser
  16705.     "Reconstruct both the private class and the instance.  7/29/96 tk"
  16706.     | instSize aSymbol refPosn anObject |
  16707.  
  16708.     anObject _ self readInstance.        "Will create new unique class"
  16709.     ^ anObject!
  16710. typeIDFor: anObject
  16711.     "Return the typeID for anObject's class."
  16712.  
  16713.     | tt |
  16714.     tt _ anObject ioType.
  16715.     tt == #User ifTrue: [^ 13].    "User Object whose class must be reconstructed"
  16716.     (anObject isKindOf: View) ifTrue: [^ 1 "nil"].    "blocked"
  16717.     (anObject isKindOf: Controller) ifTrue: [^ 1 "nil"].
  16718.     (anObject isKindOf: CompiledMethod) ifTrue: [self halt.  ^ 1 "nil"].
  16719.     
  16720.     ^ TypeMap at: anObject class ifAbsent: [9 "instance"]!
  16721. writeClass: aClass
  16722.     "PRIVATE -- For now, no classes may be written.  HyperSqueak user unique classes have not state other than methods and should be reconstructed.  Could put standard fileOut code here is necessary.  7/29/96 tk."
  16723.  
  16724.     Obj classPool at: #ErrorHolder put: aClass.
  16725.     Transcript cr; show: 'The class ', aClass printString,' is trying to be written out.  See Obj class variable ErrorHolder.'.
  16726.     "do nothing"!
  16727. writeUser: anObject
  16728.     "Write the contents of an arbitrary User instance (and its devoted class)."
  16729.     " 7/29/96 tk"
  16730.  
  16731.     "If anObject is an instance of a unique user class, will lie and say it has a generic class"
  16732.     ^ anObject storeDataOn: self! !
  16733. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  16734.  
  16735. DataStream class
  16736.     instanceVariableNames: ''!
  16737. DataStream class comment:
  16738. 'See comment in DataStream itself'!
  16739.  
  16740. !DataStream class methodsFor: 'imported from V'!
  16741. example
  16742.     "An example and test of DataStream/ReferenceStream.
  16743.      11/19/92 jhm: Use self testWith:."
  16744.     "DataStream example"
  16745.     "ReferenceStream example"
  16746.     | input sharedPoint |
  16747.  
  16748.     "Construct the test data."
  16749.     input _ Array new: 9.
  16750.     input at: 1 put: nil.
  16751.     input at: 2 put: true.
  16752.     input at: 3 put: (Form extent: 63 @ 50 depth: 8).
  16753.         (input at: 3) fillWithColor: Color lightBlue.
  16754.     input at: 4 put: #(3 3.0 'three').
  16755.     input at: 5 put: false.
  16756.     input at: 6 put: 1024 @ -2048.
  16757.     input at: 7 put: #x.
  16758.     input at: 8 put: (Array with: (sharedPoint _ 0 @ -30000)).
  16759.     input at: 9 put: sharedPoint.
  16760.  
  16761.     "Write it out, read it back, and return it for inspection."
  16762.     ^ self testWith: input!
  16763. exampleWithPictures
  16764.     "DataStream exampleWithPictures"
  16765.     | file result |
  16766.     file _ FileStream fileNamed: 'Test-Picture'.
  16767.     file binary.
  16768.     (DataStream on: file) nextPut: (Form fromUser).
  16769.     file close.
  16770.  
  16771.     file _ FileStream fileNamed: 'Test-Picture'.
  16772.     file binary.
  16773.     result _ (DataStream on: file) next.
  16774.     file close.
  16775.     result display.
  16776.     ^ result!
  16777. fileNamed: aString
  16778.     "Here is the way to use DataStream and ReferenceStream:
  16779. rr _ ReferenceStream fileNamed: 'test.obj'.
  16780. rr nextPut: <your object>.
  16781. rr close.
  16782. "
  16783.  
  16784.     ^ self on: ((FileStream fileNamed: aString) binary)!
  16785. fileTypeCode
  16786.     "Answer a default file type code to use for DataStream files. -- 11/13/92 jhm"
  16787.  
  16788.     ^ 'DatS'!
  16789. incomingObjectsClass
  16790.     "Rather HyperSqueak-specific:  Answer class that handles Incoming Objects, if present, else answer nil.  9/19/96 sw"
  16791.  
  16792.     | aClass |
  16793.     ^ ((aClass _ Smalltalk at: #IncomingObjects ifAbsent: [nil]) isKindOf: Class)
  16794.         ifTrue:
  16795.             [aClass]
  16796.         ifFalse:
  16797.             [nil]!
  16798. initialize
  16799.     "TypeMap maps Smalltalk classes to type ID numbers which identify the data stream primitive formats.  nextPut: writes these IDs to the data stream.  NOTE: Changing these type ID numbers will invalidate all extant data stream files.  Adding new ones is OK.
  16800.      See nextPut:, next, typeIDFor:, & ReferenceStream>>isAReferenceType:"
  16801.     "DataStream initialize"
  16802.  
  16803.     | refTypes t |
  16804.     refTypes _ OrderedCollection new.
  16805.     t _ TypeMap _ Dictionary new: 30. "sparse for fast hashing"
  16806.  
  16807.     t at: UndefinedObject put: 1.   refTypes add: 0.
  16808.     t at: True put: 2.   refTypes add: 0.
  16809.     t at: False put: 3.   refTypes add: 0.
  16810.     t at: SmallInteger put: 4.     refTypes add: 0.
  16811.     t at: String put: 5.   refTypes add: 1.
  16812.     t at: Symbol put: 6.   refTypes add: 1.
  16813.     t at: ByteArray put: 7.   refTypes add: 1.
  16814.         "Does anything use this?"
  16815.     t at: Array put: 8.   refTypes add: 1.
  16816.     "(type ID 9 is for arbitrary instances, cf. typeIDFor:)"
  16817.         refTypes add: 1.
  16818.     "(type ID 10 is for references, cf. ReferenceStream>>tryToPutReference:)"
  16819.         refTypes add: 0.
  16820.     t at: Bitmap put: 11.   refTypes add: 1.
  16821.     t at: Metaclass put: 12.   refTypes add: 0.
  16822.     "Type ID 13 is used for HyperSqueak User classes that must be reconstructed."
  16823.         refTypes add: 1.
  16824.     t at: Float put: 14.  refTypes add: 1.
  16825.     "t at:  put: 15.  refTypes add: 0."
  16826.     ReferenceStream refTypes: refTypes.    "save it"!
  16827. newFileNamed: aString
  16828.     "Here is the way to use DataStream and ReferenceStream:
  16829. rr _ ReferenceStream fileNamed: 'test.obj'.
  16830. rr nextPut: <your object>.
  16831. rr close.
  16832. "
  16833.  
  16834.     ^ self on: ((FileStream newFileNamed: aString) binary)!
  16835. on: aStream
  16836.     "Open a new DataStream onto a low-level I/O stream.
  16837.      11/19/92 jhm: Use new, not basicNew."
  16838.  
  16839.     | aClass |
  16840.     (aClass _ Smalltalk hyperSqueakSupportClass) == nil
  16841.         ifFalse:
  16842.             [aClass initSysLib].    "Get current sys globals"
  16843.     aStream binary.
  16844.     ^ self basicNew setStream: aStream!
  16845. testWith: anObject
  16846.     "As a test of DataStream/ReferenceStream, write out anObject and read it back.
  16847.     11/19/92 jhm: Set the file type. More informative file name."
  16848.     "DataStream testWith: 'hi'"
  16849.     "ReferenceStream testWith: 'hi'"
  16850.     | file result |
  16851.  
  16852.     file _ FileStream fileNamed: (self name, ' test').
  16853.     file binary.
  16854.     (self on: file) nextPut: anObject; setType.
  16855.     file close.
  16856.  
  16857.     file _ FileStream fileNamed: (self name, ' test').
  16858.     file binary.
  16859.     result _ (self on: file) next.
  16860.     file close.
  16861.     ^ result! !
  16862.  
  16863. DataStream initialize!
  16864. Magnitude subclass: #Date
  16865.     instanceVariableNames: 'day year '
  16866.     classVariableNames: 'SecondsInDay MonthNames FirstDayOfMonth DaysInMonth WeekDayNames '
  16867.     poolDictionaries: ''
  16868.     category: 'Numeric-Magnitudes'!
  16869. Date comment:
  16870. 'I represent a date. My printing format consists of an array of six elements.
  16871.     
  16872. The first three elements contain the numbers 1, 2, 3, in any order. 1 indicates that the day appears in this position, 2 indicates that the month appears in this position, and 3 indicates that the year appears in this position.
  16873.     
  16874. The fourth element is the ascii value of the character separator or the character itself.
  16875.     
  16876. The fifth element is the month format, where 1 indicates print as a number, 2 indicates print the first three characters, and 3 indicates print the entire name.
  16877.     
  16878. The six element is the year format, where 1 indicates print as a number, and 2 indicates print the number modulo 100.
  16879.     
  16880. Examples:
  16881.     #(1 2 3 32 2 1) prints as 12 Dec 1981
  16882.     #(2 1 3 $/ 1 2) prints as 12/12/81'!
  16883.  
  16884. !Date methodsFor: 'accessing'!
  16885. day
  16886.     "Answer the day of the year represented by the receiver."
  16887.  
  16888.     ^day!
  16889. leap
  16890.     "Answer whether the receiver's year is a leap year."
  16891.  
  16892.     ^Date leapYear: year!
  16893. monthIndex
  16894.     "Answer the index of the month in which the receiver falls."
  16895.  
  16896.     | leap firstDay |
  16897.     leap _ self leap.
  16898.     12 to: 1 by: -1 do: 
  16899.         [ :monthIndex | 
  16900.             firstDay _ (FirstDayOfMonth at: monthIndex)
  16901.                             + (monthIndex > 2 ifTrue: [leap] ifFalse: [0]).
  16902.             firstDay<= day
  16903.                 ifTrue: [^monthIndex]].
  16904.     self error: 'illegal month'!
  16905. monthName
  16906.     "Answer the name of the month in which the receiver falls."
  16907.  
  16908.     ^MonthNames at: self monthIndex!
  16909. weekday
  16910.     "Answer the name of the day of the week on which the receiver falls."
  16911.  
  16912.     ^WeekDayNames at: self weekdayIndex!
  16913. year
  16914.     "Answer the year in which the receiver falls."
  16915.  
  16916.     ^year! !
  16917.  
  16918. !Date methodsFor: 'arithmetic'!
  16919. addDays: dayCount 
  16920.     "Answer a Date that is dayCount days after the receiver."
  16921.  
  16922.     ^Date newDay: day + dayCount
  16923.           year: year!
  16924. subtractDate: aDate 
  16925.     "Answer the number of days between the receiver and aDate."
  16926.  
  16927.     year = aDate year
  16928.         ifTrue: [^day - aDate day]
  16929.         ifFalse: [^year - 1 // 4 - (aDate year // 4) + day 
  16930.                         + aDate daysLeftInYear + (year - 1 - aDate year * 365)]!
  16931. subtractDays: dayCount 
  16932.     "Answer a Date that is dayCount days before the receiver."
  16933.  
  16934.     ^Date newDay: day - dayCount year: year! !
  16935.  
  16936. !Date methodsFor: 'comparing'!
  16937. < aDate 
  16938.     "Answer whether aDate precedes the date of the receiver." 
  16939.  
  16940.     year = aDate year
  16941.         ifTrue: [^day < aDate day]
  16942.         ifFalse: [^year < aDate year]!
  16943. = aDate 
  16944.     "Answer whether aDate is the same day as the receiver."
  16945.  
  16946.     self species = aDate species
  16947.         ifTrue: [^day = aDate day & (year = aDate year)]
  16948.         ifFalse: [^false]!
  16949. hash
  16950.     "Hash is reimplemented because = is implemented."
  16951.  
  16952.     ^(year hash bitShift: 3) bitXor: day! !
  16953.  
  16954. !Date methodsFor: 'inquiries'!
  16955. dayOfMonth
  16956.     "Answer which day of the month is represented by the receiver."
  16957.  
  16958.     ^day - (self firstDayOfMonthIndex: self monthIndex) + 1!
  16959. daysInMonth
  16960.     "Answer the number of days in the month represented by the receiver."
  16961.  
  16962.     ^(DaysInMonth at: self monthIndex)
  16963.         + (self monthIndex = 2
  16964.                 ifTrue: [self leap]
  16965.                 ifFalse: [0])!
  16966. daysInYear
  16967.     "Answer the number of days in the year represented by the receiver."
  16968.  
  16969.     ^Date daysInYear: self year!
  16970. daysLeftInYear
  16971.     "Answer the number of days in the year after the date of the receiver."
  16972.  
  16973.     ^self daysInYear - self day!
  16974. firstDayOfMonth
  16975.     "Answer the index of the day of the year that is the first day of the 
  16976.     receiver's month."
  16977.  
  16978.     ^self firstDayOfMonthIndex: self monthIndex!
  16979. previous: dayName 
  16980.     "Answer the previous date whose weekday name is dayName."
  16981.  
  16982.     ^self subtractDays: 7 + self weekdayIndex - (Date dayOfWeek: dayName) \\ 7! !
  16983.  
  16984. !Date methodsFor: 'converting'!
  16985. asSeconds
  16986.     "Answer the seconds between a time on 1 January 1901 and the same 
  16987.     time in the receiver's day."
  16988.  
  16989.     ^SecondsInDay * (self subtractDate: (Date newDay: 1 year: 1901))! !
  16990.  
  16991. !Date methodsFor: 'printing'!
  16992. mmddyy
  16993.     "Answer the receiver rendered in standard fmt mm/dd/yy. 1/17/96 sw.  2/1/96 sw Fixed to show day of month, not day.  Note that the name here is slightly misleading -- the month and day numbers don't show leading zeros, so that for example feb 1 1996 is 2/1/96"
  16994.  
  16995.     "Date today mmddyy"
  16996.  
  16997.     ^ self printFormat: #(2 1 3 $/ 1 99)!
  16998. printFormat: formatArray 
  16999.     "Answer a String describing the receiver using the format denoted by the 
  17000.     argument, formatArray."
  17001.  
  17002.     | aStream |
  17003.     aStream _ WriteStream on: (String new: 16).
  17004.     self printOn: aStream format: formatArray.
  17005.     ^aStream contents!
  17006. printOn: aStream
  17007.  
  17008.     self printOn: aStream format: #(1 2 3 $  3 1 )!
  17009. printOn: aStream format: formatArray 
  17010.     "Print a description of the receiver on aStream using the format denoted 
  17011.     by the argument, formatArray:
  17012.         #(item item item sep monthfmt yearfmt twoDigits)
  17013.         items:  1=day  2=month  3=year  will appear in the order given,
  17014.         separated by sep which is eaither an ascii code or character.
  17015.         monthFmt:  1=09  2=Sep  3=September
  17016.         yearFmt:  1=1996  2=96
  17017.         digits:  (missing or)1=9  2=09.
  17018.     See the examples in printOn: and mmddyy"
  17019.     | monthIndex element monthFormat twoDigits monthDay |
  17020.     twoDigits _ formatArray size > 6 and: [(formatArray at: 7) > 1].
  17021.     monthIndex _ self monthIndex.
  17022.     1 to: 3 do: 
  17023.         [:elementIndex | 
  17024.         element _ formatArray at: elementIndex.
  17025.         element = 1 ifTrue:
  17026.             [monthDay _ day - self firstDayOfMonth + 1.
  17027.             twoDigits & (monthDay < 10) ifTrue: [aStream nextPutAll: '0'].
  17028.                 monthDay printOn: aStream].
  17029.         element = 2 ifTrue: 
  17030.             [monthFormat _ formatArray at: 5.
  17031.             monthFormat = 1 ifTrue:
  17032.                 [twoDigits & (monthIndex < 10) ifTrue: [aStream nextPutAll: '0'].
  17033.                 monthIndex printOn: aStream].
  17034.             monthFormat = 2 ifTrue:
  17035.                 [aStream nextPutAll: ((MonthNames at: monthIndex)
  17036.                                                 copyFrom: 1 to: 3)].
  17037.             monthFormat = 3 ifTrue:
  17038.                 [aStream nextPutAll: (MonthNames at: monthIndex)]].
  17039.         element = 3 ifTrue: 
  17040.             [(formatArray at: 6) = 1
  17041.                 ifTrue: [year printOn: aStream]
  17042.                 ifFalse: [twoDigits & ((year \\ 100) < 10)
  17043.                             ifTrue: [aStream nextPutAll: '0'].
  17044.                         (year \\ 100) printOn: aStream]].
  17045.         elementIndex < 3 ifTrue: 
  17046.             [(formatArray at: 4) ~= 0 
  17047.                 ifTrue: [aStream nextPut: (formatArray at: 4) asCharacter]]]!
  17048. storeOn: aStream
  17049.  
  17050.     aStream nextPutAll: '(', self class name, ' readFromString: ';
  17051.         print: self printString;
  17052.         nextPut: $)! !
  17053.  
  17054. !Date methodsFor: 'private'!
  17055. day: dayInteger year: yearInteger
  17056.  
  17057.     day _ dayInteger.
  17058.     year _ yearInteger!
  17059. firstDayOfMonthIndex: monthIndex 
  17060.     "Answer the day of the year (an Integer) that is the first day of my month"
  17061.  
  17062.     ^(FirstDayOfMonth at: monthIndex)
  17063.         + (monthIndex > 2
  17064.                 ifTrue: [self leap]
  17065.                 ifFalse: [0])!
  17066. weekdayIndex
  17067.     "Sunday=1, ... , Saturday=7"
  17068.  
  17069.     | yearIndex dayIndex |  
  17070.     day < (self firstDayOfMonthIndex: 3)
  17071.         ifTrue: 
  17072.             [yearIndex _ year - 1.
  17073.             dayIndex _ 307]
  17074.         ifFalse: 
  17075.             [yearIndex _ year.
  17076.             dayIndex _ -58 - self leap].  
  17077.     
  17078.     ^dayIndex + day + yearIndex + (yearIndex // 4) 
  17079.                 + (yearIndex // 400) - (yearIndex // 100) \\ 7 + 1! !
  17080. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  17081.  
  17082. Date class
  17083.     instanceVariableNames: ''!
  17084.  
  17085. !Date class methodsFor: 'class initialization'!
  17086. initialize
  17087.     "Initialize class variables representing the names of the months and days and
  17088.     the number of seconds, days in each month, and first day of each month."
  17089.  
  17090.     MonthNames _ 
  17091.         #(January February March April May June 
  17092.             July August September October November December ).
  17093.     SecondsInDay _ 24 * 60 * 60.
  17094.     DaysInMonth _ #(31 28 31 30 31 30 31 31 30 31 30 31 ).
  17095.     FirstDayOfMonth _ #(1 32 60 91 121 152 182 213 244 274 305 335 ).
  17096.     WeekDayNames _ 
  17097.         #(Monday Tuesday Wednesday Thursday Friday Saturday Sunday )
  17098.  
  17099.     "Date initialize."
  17100. ! !
  17101.  
  17102. !Date class methodsFor: 'instance creation'!
  17103. fromDays: dayCount
  17104.     "Answer an instance of me which is dayCount days after January 1, 
  17105.     1901."
  17106.  
  17107.     ^self
  17108.         newDay: 1 + (dayCount asInteger rem: 1461)
  17109.                             "There are 1461 days in a 4-year cycle. 
  17110.                              2000 is a leap year, so no extra correction is necessary. "
  17111.         year: 1901 + ((dayCount asInteger quo: 1461) * 4)!
  17112. newDay: day month: monthName year: year 
  17113.     "Answer an instance of me which is the day'th day of the month named 
  17114.     monthName in the year'th year. The year may be specified as the actual 
  17115.     number of years since the beginning of the Roman calendar or the 
  17116.     number of years since the beginning of the century."
  17117.  
  17118.     | monthIndex daysInMonth firstDayOfMonth |
  17119.     year < 100 ifTrue: [^self
  17120.             newDay: day
  17121.             month: monthName
  17122.             year: 1900 + year].
  17123.     monthIndex _ self indexOfMonth: monthName.
  17124.     monthIndex = 2
  17125.         ifTrue: [daysInMonth _ (DaysInMonth at: monthIndex)
  17126.                         + (self leapYear: year)]
  17127.         ifFalse: [daysInMonth _ DaysInMonth at: monthIndex].
  17128.     monthIndex > 2
  17129.         ifTrue: [firstDayOfMonth _ (FirstDayOfMonth at: monthIndex)
  17130.                         + (self leapYear: year)]
  17131.         ifFalse: [firstDayOfMonth _ FirstDayOfMonth at: monthIndex].
  17132.     (day < 1 or: [day > daysInMonth])
  17133.         ifTrue: [self error: 'illegal day in month']
  17134.         ifFalse: [^self new day: day - 1 + firstDayOfMonth year: year]!
  17135. newDay: dayCount year: referenceYear 
  17136.     "Answer an instance of me which is dayCount days after the beginning 
  17137.     of the year referenceYear."
  17138.  
  17139.     | day year daysInYear |
  17140.     day _ dayCount.
  17141.     year _ referenceYear.
  17142.     [day > (daysInYear _ self daysInYear: year)]
  17143.         whileTrue: 
  17144.             [year _ year + 1.
  17145.              day _ day - daysInYear].
  17146.     [day <= 0]
  17147.         whileTrue: 
  17148.             [year _ year - 1.
  17149.              day _ day + (self daysInYear: year)].
  17150.     ^self new day: day year: year!
  17151. readFrom: aStream
  17152.     "Read a Date from the stream in any of the forms:
  17153.         <day> <monthName> <year>        (5 April 1982; 5-APR-82)
  17154.         <monthName> <day> <year>        (April 5, 1982)
  17155.         <monthNumber> <day> <year>    (4/5/82)"
  17156.  
  17157.     | day month |
  17158.     aStream peek isDigit ifTrue: [day _ Integer readFrom: aStream].
  17159.     [aStream peek isAlphaNumeric] whileFalse: [aStream skip: 1].
  17160.     aStream peek isLetter
  17161.         ifTrue:        "number/name... or name..."
  17162.             [month _ WriteStream on: (String new: 10).
  17163.             [aStream peek isLetter] whileTrue: [month nextPut: aStream next].
  17164.             month _ month contents.
  17165.             day isNil ifTrue:        "name/number..."
  17166.                 [[aStream peek isAlphaNumeric] whileFalse: [aStream skip: 1].
  17167.                 day _ Integer readFrom: aStream]]
  17168.         ifFalse:        "number/number..."
  17169.             [month _ Date nameOfMonth: day.
  17170.             day _ Integer readFrom: aStream].
  17171.     [aStream peek isAlphaNumeric] whileFalse: [aStream skip: 1].
  17172.     ^self newDay: day month: month year: (Integer readFrom: aStream)
  17173.  
  17174.     "Date readFrom: (ReadStream on: '5APR82')"
  17175. !
  17176. today
  17177.     "Answer an instance of me representing the day and year right now."
  17178.  
  17179.     ^self dateAndTimeNow at: 1! !
  17180.  
  17181. !Date class methodsFor: 'general inquiries'!
  17182. dateAndTimeNow
  17183.     "Answer an Array whose first element is Date today and second element 
  17184.     is Time now."
  17185.  
  17186.     ^Time dateAndTimeNow!
  17187. dayOfWeek: dayName 
  17188.     "Answer the index in a week, 1-7, of the day named dayName. Create an 
  17189.     error notification if no such day exists."
  17190.  
  17191.     1 to: 7 do: [:index | (WeekDayNames at: index)
  17192.             = dayName ifTrue: [^index]].
  17193.     self error: dayName asString , ' is not a day of the week'!
  17194. daysInMonth: monthName forYear: yearInteger 
  17195.     "Answer the number of days in the month named monthName in the 
  17196.     year yearInteger."
  17197.  
  17198.     ^(self newDay: 1
  17199.           month: monthName
  17200.           year: yearInteger) daysInMonth!
  17201. daysInYear: yearInteger 
  17202.     "Answer the number of days in the year, yearInteger."
  17203.  
  17204.     ^365 + (self leapYear: yearInteger)!
  17205. firstWeekdayOfMonth: mn year: yr
  17206.     "Answer the weekday index (Sunday=1, etc) of the first day in the month named mn in the year yr."
  17207.  
  17208.     ^(self newDay: 1 month: mn year: yr) weekdayIndex + 7 \\ 7 + 1!
  17209. indexOfMonth: monthName 
  17210.     "Answer the index, 1-12, of the month monthName. Create an error 
  17211.     notification if no such month exists."
  17212.  
  17213.     1 to: 12 do: 
  17214.         [ :index | 
  17215.             (monthName , '*' match: (MonthNames at: index))
  17216.                         ifTrue: [^index]].
  17217.     self error: monthName , ' is not a recognized month name'!
  17218. leapYear: yearInteger 
  17219.     "Answer 1 if the year yearInteger is a leap year; answer 0 if it is not."
  17220.  
  17221.     (yearInteger \\ 4 ~= 0 or: [yearInteger \\ 100 = 0 and: [yearInteger \\ 400 ~= 0]])
  17222.         ifTrue: [^0]
  17223.         ifFalse: [^1]!
  17224. nameOfDay: dayIndex 
  17225.     "Answer a symbol representing the name of the day indexed by 
  17226.     dayIndex, 1-7."
  17227.  
  17228.     ^WeekDayNames at: dayIndex!
  17229. nameOfMonth: monthIndex 
  17230.     "Answer a String representing the name of the month indexed by 
  17231.     monthIndex, 1-12."
  17232.  
  17233.     ^MonthNames at: monthIndex! !
  17234.  
  17235. Date initialize!
  17236. StringHolder subclass: #Debugger
  17237.     instanceVariableNames: 'interruptedProcess interruptedController contextStack contextStackTop contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC sourceMap tempNames '
  17238.     classVariableNames: ''
  17239.     poolDictionaries: ''
  17240.     category: 'Interface-Debugger'!
  17241. Debugger comment:
  17242. 'I represent the machine state at the time of an interrupted process. I also represent a query path into the state of the process. As a StringHolder, the string to be viewed is the interrupted method at some point in the sequence of message-sends that have been initiated but not completed.'!
  17243.  
  17244. !Debugger methodsFor: 'initialize-release'!
  17245. defaultBackgroundColor
  17246.     ^ #lightRed!
  17247. expandStack
  17248.     "This initialization occurs when the interrupted context is to modelled by 
  17249.     a DebuggerView, rather than a NotifierView (which can not display 
  17250.     more than five message-sends."
  17251.  
  17252.     self newStack: (contextStackTop stackOfSize: 7).
  17253.     contextStackIndex _ 0.
  17254.     receiverInspector _ Inspector inspect: nil.
  17255.     contextVariablesInspector _ ContextVariablesInspector inspect: nil.
  17256.     proceedValue _ nil!
  17257. release
  17258.  
  17259.     interruptedProcess ~~ nil ifTrue: [interruptedProcess terminate].
  17260.     interruptedProcess _ nil.
  17261.     interruptedController _ nil.
  17262.     contextStack _ nil.
  17263.     contextStackTop _ nil.
  17264.     receiverInspector _ nil.
  17265.     contextVariablesInspector _ nil.
  17266.     Smalltalk installLowSpaceWatcher.  "restart low space handler"
  17267.     super release.! !
  17268.  
  17269. !Debugger methodsFor: 'accessing'!
  17270. contents 
  17271.     "Depending on the current selection, different information is retrieved.
  17272.     Answer a string description of that information.  This information is the
  17273.     method in the currently selected context."
  17274.  
  17275.     contents == nil ifTrue: [^''].
  17276.     ^contents!
  17277. contents: aString notifying: aController 
  17278.     "The retrieved information has changed and its source must now be 
  17279.     updated. In this case, the retrieved information is the method of the 
  17280.     selected context."
  17281.     | selector classOfMethod methodNode category method priorMethod |
  17282.     contextStackIndex = 0 ifTrue: [^self].
  17283.     (self selectedContext isKindOf: MethodContext)
  17284.         ifFalse:
  17285.             [(self confirm:
  17286. 'I will have to revert to the method from
  17287. which this block originated.  Is that OK?')
  17288.                 ifTrue: [self resetContext: self selectedContext home]
  17289.                 ifFalse: [^self]].
  17290.     classOfMethod _ self selectedClass.
  17291.     category _ self selectedMessageCategoryName.
  17292.     Cursor execute showWhile:
  17293.         [method _ classOfMethod
  17294.         compile: aString
  17295.         notifying: aController
  17296.         trailer: #(0 0 0 )
  17297.         ifFail: [^ false]
  17298.         elseSetSelectorAndNode: 
  17299.             [:sel :methodNode | selector _ sel.
  17300.             selector == self selectedMessageName
  17301.                 ifFalse: [self notify: 'can''t change selector'. ^ false].
  17302.             priorMethod _ (classOfMethod includesSelector: selector)
  17303.                 ifTrue: [classOfMethod compiledMethodAt: selector]
  17304.                 ifFalse: [nil].
  17305.             sourceMap _ methodNode sourceMap.
  17306.             tempNames _ methodNode tempNames].
  17307.         method cacheTempNames: tempNames].
  17308.     category isNil ifFalse: "Skip this for DoIts"
  17309.         [(SourceFiles isNil or: [(SourceFiles at: 2) == nil]) ifFalse:
  17310.             [method
  17311.                 putSource: aString asString
  17312.                 class: classOfMethod
  17313.                 category: category
  17314.                 inFile: 2 priorMethod: priorMethod].
  17315.         classOfMethod organization classify: selector under: category].
  17316.     contents _ aString copy.
  17317.     self selectedContext restartWith: method.
  17318.     contextVariablesInspector object: nil.
  17319.     self resetContext: self selectedContext.
  17320.     ^true!
  17321. contextVariablesInspector
  17322.     "Answer the instance of Inspector that is providing a view of the 
  17323.     variables of the selected context."
  17324.  
  17325.     ^contextVariablesInspector!
  17326. interruptedContext
  17327.     "Answer the suspended context of the interrupted process."
  17328.  
  17329.     ^contextStackTop!
  17330. interruptedProcess
  17331.     "Answer the interrupted process."
  17332.  
  17333.     ^interruptedProcess!
  17334. proceedValue
  17335.     "Answer the value to return to the selected context when the interrupted 
  17336.     process proceeds."
  17337.  
  17338.     ^proceedValue!
  17339. proceedValue: anObject 
  17340.     "Set the value to be returned to the selected context when the interrupted 
  17341.     process proceeds."
  17342.  
  17343.     proceedValue _ anObject!
  17344. receiver
  17345.     "Answer the receiver of the selected context, if any. Answer nil 
  17346.     otherwise."
  17347.  
  17348.     contextStackIndex = 0
  17349.         ifTrue: [^nil]
  17350.         ifFalse: [^self selectedContext receiver]!
  17351. receiverInspector
  17352.     "Answer the instance of Inspector that is providing a view of the 
  17353.     variables of the selected context's receiver."
  17354.  
  17355.     ^receiverInspector! !
  17356.  
  17357. !Debugger methodsFor: 'code'!
  17358. doItContext
  17359.     "Answer the context in which a text selection can be evaluated."
  17360.  
  17361.     contextStackIndex = 0
  17362.         ifTrue: [^super doItContext]
  17363.         ifFalse: [^self selectedContext]!
  17364. doItReceiver
  17365.     "Answer the object that should be informed of the result of evaluating a
  17366.     text selection."
  17367.  
  17368.     ^self receiver! !
  17369.  
  17370. !Debugger methodsFor: 'context stack'!
  17371. contextStackIndex
  17372.     "Answer the index of the selected context."
  17373.  
  17374.     ^contextStackIndex!
  17375. contextStackList
  17376.     "Answer the array of contexts."
  17377.  
  17378.     ^contextStackList!
  17379. fullyExpandStack
  17380.     "Expand the stack to include all of it, rather than the first four or five
  17381.     contexts."
  17382.  
  17383.     self okToChange ifFalse: [^ self].
  17384.     self newStack: contextStackTop stack.
  17385.     self changed: #contextStackList!
  17386. toggleContextStackIndex: anInteger 
  17387.     "If anInteger is the same as the index of the selected context, deselect it. 
  17388.     Otherwise, the context whose index is anInteger becomes the selected 
  17389.     context."
  17390.  
  17391.     self contextStackIndex: 
  17392.         (contextStackIndex = anInteger
  17393.             ifTrue: [0]
  17394.             ifFalse: [anInteger])
  17395.         oldContextWas:
  17396.         (contextStackIndex = 0
  17397.             ifTrue: [nil]
  17398.             ifFalse: [contextStack at: contextStackIndex])! !
  17399.  
  17400. !Debugger methodsFor: 'menu messages'!
  17401. close: aScheduledController 
  17402.     "The argument is a controller on a view of the receiver.
  17403.     That view is closed."
  17404.  
  17405.     aScheduledController close
  17406. !
  17407. proceed: aScheduledController 
  17408.     "Proceed from the interrupted state of the currently selected context. The 
  17409.     argument is a controller on a view of the receiver. That view is closed."
  17410.  
  17411.     self okToChange ifFalse: [^ self].
  17412.     self checkContextSelection.
  17413.     contextStackIndex > 1 | externalInterrupt not 
  17414.         ifTrue: [self selectedContext push: proceedValue].
  17415.     self resumeProcess: aScheduledController!
  17416. restart: aScheduledController 
  17417.     "Proceed from the initial state of the currently selected context. The 
  17418.     argument is a controller on a view of the receiver. That view is closed."
  17419.  
  17420.     self okToChange ifFalse: [^ self].
  17421.     self checkContextSelection.
  17422.     (self selectedContext isKindOf: MethodContext)
  17423.         ifFalse:
  17424.             [(self confirm:
  17425. 'I will have to revert to the method from
  17426. which this block originated.  Is that OK?')
  17427.                 ifTrue: [self resetContext: self selectedContext home]
  17428.                 ifFalse: [^self]].
  17429.     self selectedContext restart.
  17430.     self resumeProcess: aScheduledController!
  17431. selectPC
  17432.     "Toggle the flag telling whether to automatically select the expression 
  17433.     currently being executed by the selected context."
  17434.  
  17435.     selectingPC _ selectingPC not! !
  17436.  
  17437. !Debugger methodsFor: 'message list'!
  17438. messageListIndex
  17439.     "Answer the index of the currently selected context."
  17440.  
  17441.     ^contextStackIndex!
  17442. selectedMessage
  17443.     "Answer the source code of the currently selected context."
  17444.  
  17445.     contents == nil ifTrue: [contents _ self selectedContext sourceCode].
  17446.     ^contents!
  17447. selectedMessageName
  17448.     "Answer the message selector of the currently selected context."
  17449.  
  17450.     ^self selectedContext selector!
  17451. spawn: aString 
  17452.     "Create and schedule a message browser on the message, aString. Any 
  17453.     edits already made are retained."
  17454.  
  17455.     self messageListIndex > 0
  17456.         ifTrue: 
  17457.             [^BrowserView
  17458.                 openMessageBrowserForClass: self selectedClass
  17459.                 selector: self selectedMessageName
  17460.                 editString: aString]! !
  17461.  
  17462. !Debugger methodsFor: 'message category list'!
  17463. selectedMessageCategoryName
  17464.     "Answer the name of the message category of the message of the 
  17465.     currently selected context."
  17466.  
  17467.     ^self selectedClass organization categoryOfElement: self selectedMessageName! !
  17468.  
  17469. !Debugger methodsFor: 'message functions'!
  17470. browseImplementors
  17471.     "Create and schedule a message set browser on all implementors of the
  17472.     currently selected message selector. Do nothing if no message is selected."
  17473.  
  17474.     contextStackIndex ~= 0 
  17475.         ifTrue: [Smalltalk browseAllImplementorsOf: self selectedMessageName]!
  17476. browseMessages
  17477.     "Show a menu of all messages sent by the currently selected message.
  17478.     Create and schedule a message set browser of all implementors of the 
  17479.     message chosen. Do nothing if no message is chosen."
  17480.  
  17481.     contextStackIndex = 0 ifTrue: [^self].
  17482.     Smalltalk showMenuThenBrowse:
  17483.         (self selectedClassOrMetaClass compiledMethodAt: self selectedMessageName)
  17484.             messages asSortedCollection!
  17485. browseSenders
  17486.     "Show a menu of all messages that send the currently selected message.
  17487.     Create and schedule a message set browser of of the chosen message. Do
  17488.     nothing if no message is chosen."
  17489.  
  17490.     contextStackIndex ~= 0 
  17491.         ifTrue: [Smalltalk browseAllCallsOn: self selectedMessageName]!
  17492. browseSendersOf
  17493.     "Show a menu of all messages sent by the currently selected message. 
  17494.     Create and schedule a message set browser of all senders of the 
  17495.     message chosen. Do nothing if no message is chosen.  Derived from
  17496.     browseMessages, 1/8/96 sw"
  17497.  
  17498.     contextStackIndex = 0 ifTrue: [^self].
  17499.     Smalltalk showMenuThenBrowseSenders:
  17500.         (self selectedClassOrMetaClass compiledMethodAt: self selectedMessageName)
  17501.             messages asSortedCollection!
  17502. browseSendersOfMessages
  17503.     "Show a menu of all messages sent by the currently selected message. 
  17504.     Create and schedule a message set browser of all senders of the 
  17505.     message chosen. Do nothing if no message is chosen.  Derived from
  17506.     browseMessages, 1/8/96 sw"
  17507.  
  17508.     contextStackIndex = 0 ifTrue: [^self].
  17509.     Smalltalk showMenuThenBrowseSendersOf:
  17510.         (self selectedClassOrMetaClass compiledMethodAt: self selectedMessageName)
  17511.             messages asSortedCollection! !
  17512.  
  17513. !Debugger methodsFor: 'class list'!
  17514. selectedClass
  17515.     "Answer the class in which the currently selected context's method was 
  17516.     found."
  17517.  
  17518.     ^self selectedContext mclass!
  17519. selectedClassOrMetaClass
  17520.     "Answer the class in which the currently selected context's method was 
  17521.     found."
  17522.  
  17523.     ^self selectedContext mclass! !
  17524.  
  17525. !Debugger methodsFor: 'dependents access'!
  17526. removeDependent: aDependent
  17527.  
  17528.     super removeDependent: aDependent.
  17529.     self dependents isEmpty ifTrue: [self release]!
  17530. updateInspectors 
  17531.     "Update the inspectors on the receiver's variables."
  17532.  
  17533.     receiverInspector update.
  17534.     contextVariablesInspector update! !
  17535.  
  17536. !Debugger methodsFor: 'pc selection'!
  17537. pcRange
  17538.     "Answer the indices in the source code for the method corresponding to 
  17539.     the selected context's program counter value."
  17540.  
  17541.     | i methodNode pc end |
  17542.     (selectingPC and: [contextStackIndex ~= 0])
  17543.         ifFalse: [^1 to: 0].
  17544.     sourceMap == nil ifTrue:
  17545.         [methodNode _ self selectedClass compilerClass new
  17546.             parse: self selectedMessage
  17547.             in: self selectedClass
  17548.             notifying: nil.
  17549.         sourceMap _ methodNode sourceMap.
  17550.         tempNames _ methodNode tempNames.
  17551.         self selectedContext method cacheTempNames: tempNames].
  17552.     sourceMap size = 0 ifTrue: [^1 to: 0].
  17553.     pc_ self selectedContext pc -
  17554.         ((externalInterrupt and: [contextStackIndex=1])
  17555.             ifTrue: [1]
  17556.             ifFalse: [2]).
  17557.     i _ sourceMap indexForInserting: (Association key: pc value: nil).
  17558.     i < 1 ifTrue: [^1 to: 0].
  17559.     i > sourceMap size
  17560.         ifTrue:
  17561.             [end _ sourceMap inject: 0 into:
  17562.                 [:prev :this | prev max: this value last].
  17563.             ^ end+1 to: end].
  17564.     ^(sourceMap at: i) value! !
  17565.  
  17566. !Debugger methodsFor: 'code execution'!
  17567. send
  17568.     "Send the selected message in the accessed method, and take control in 
  17569.     the method invoked to allow further step or send."
  17570.  
  17571.     | currentContext |
  17572.     self okToChange ifFalse: [^ self].
  17573.     self checkContextSelection.
  17574.     externalInterrupt ifFalse: [contextStackTop push: proceedValue].
  17575.     externalInterrupt _ true. "simulation leaves same state as interrupting"
  17576.     currentContext _ self selectedContext.
  17577.     currentContext stepToSendOrReturn.
  17578.     self contextStackIndex > 1 | currentContext willReturn
  17579.         ifTrue: 
  17580.             [self changed: #notChanged]
  17581.         ifFalse: 
  17582.             [currentContext _ currentContext step.
  17583.             self resetContext: currentContext]!
  17584. step
  17585.     "Send the selected message in the accessed method, and regain control 
  17586.     after the invoked method returns."
  17587.     
  17588.     | currentContext oldMethod |
  17589.     self okToChange ifFalse: [^ self].
  17590.     self checkContextSelection.
  17591.     externalInterrupt ifFalse: [contextStackTop push: proceedValue].
  17592.     externalInterrupt _ true. "simulation leaves same state as interrupting"
  17593.     currentContext _ self selectedContext.
  17594.     self contextStackIndex > 1
  17595.         ifTrue: 
  17596.             [currentContext completeCallee: contextStackTop.
  17597.             self resetContext: currentContext]
  17598.         ifFalse: 
  17599.             [currentContext stepToSendOrReturn.
  17600.             currentContext willReturn
  17601.                 ifTrue: 
  17602.                     [oldMethod _ currentContext method.
  17603.                     currentContext _ currentContext step.
  17604.                     self resetContext: currentContext.
  17605.                     oldMethod == currentContext method "didnt used to update pc here"
  17606.                         ifTrue: [self changed: #pc]]
  17607.                 ifFalse: 
  17608.                     [currentContext completeCallee: currentContext step.
  17609.                     self changed: #pc.
  17610.                     self updateInspectors]]! !
  17611.  
  17612. !Debugger methodsFor: 'private'!
  17613. checkContextSelection
  17614.  
  17615.     contextStackIndex = 0 ifTrue: [contextStackIndex _ 1]!
  17616. contextStackIndex: anInteger oldContextWas: oldContext
  17617.  
  17618.     | newMethod |
  17619.     contextStackIndex _ anInteger.
  17620.     anInteger = 0
  17621.         ifTrue:
  17622.             [tempNames _ sourceMap _ contents _ nil.
  17623.             self changed: #contextStackIndex.
  17624.             self changed: #contents.
  17625.             contextVariablesInspector object: nil.
  17626.             receiverInspector object: self receiver.
  17627.             ^self].
  17628.     (newMethod _ oldContext == nil or:
  17629.         [oldContext method ~~ self selectedContext method])
  17630.         ifTrue:
  17631.             [tempNames _ sourceMap _ nil.
  17632.             contents _ self selectedContext sourceCode.
  17633.             self changed: #contents.
  17634.             self pcRange "will compute tempNamesunless noFrills"].
  17635.     self changed: #contextStackIndex.
  17636.     tempNames == nil
  17637.         ifTrue: [tempNames _ 
  17638.                     self selectedClassOrMetaClass parserClass new parseArgsAndTemps: contents notifying: nil].
  17639.     contextVariablesInspector object: self selectedContext.
  17640.     receiverInspector object: self receiver.
  17641.     newMethod ifFalse: [self changed: #pc]!
  17642. externalInterrupt: aBoolean
  17643.  
  17644.     externalInterrupt _ aBoolean !
  17645. newStack: stack
  17646.     | oldStack diff |
  17647.     oldStack _ contextStack.
  17648.     contextStack _ stack.
  17649.     (oldStack == nil or: [oldStack last ~~ stack last])
  17650.         ifTrue: [contextStackList _ contextStack collect: [:ctx | ctx printString].
  17651.                 ^ self].
  17652.     "May be able to re-use some of previous list"
  17653.     diff _ stack size - oldStack size.
  17654.     contextStackList _ diff <= 0
  17655.         ifTrue: [contextStackList copyFrom: 1-diff to: oldStack size]
  17656.         ifFalse: [diff > 1
  17657.                 ifTrue: [contextStack collect: [:ctx | ctx printString]]
  17658.                 ifFalse: [(Array with: stack first printString) , contextStackList]]!
  17659. process: aProcess controller: aController context: aContext
  17660.  
  17661.     super initialize.
  17662.     contents _ nil. 
  17663.     interruptedProcess _ aProcess.
  17664.     interruptedController _ aController.
  17665.     contextStackTop _ aContext.
  17666.     self newStack: (contextStackTop stackOfSize: 1).
  17667.     contextStackIndex _ 1.
  17668.     externalInterrupt _ false.
  17669.     selectingPC _ true!
  17670. resetContext: aContext 
  17671.     "Used when a new context becomes top-of-stack, for instance when the
  17672.     method of the selected context is re-compiled, or the simulator steps or
  17673.     returns to a new method. There is room for much optimization here, first
  17674.     to save recomputing the whole stack list (and text), and secondly to avoid
  17675.     recomposing all that text (by editing the paragraph instead of recreating it)."
  17676.  
  17677.     | oldContext |
  17678.     oldContext _ self selectedContext.
  17679.     contextStackTop _ aContext.
  17680.     self newStack: contextStackTop stack.
  17681.     self changed: #contextStackList.
  17682.     self contextStackIndex: 1 oldContextWas: oldContext!
  17683. resumeProcess: aScheduledController
  17684.     aScheduledController view erase.
  17685.     interruptedProcess suspendedContext method
  17686.             == (Process compiledMethodAt: #terminate) ifFalse:
  17687.         [contextStackIndex > 1
  17688.             ifTrue: [interruptedProcess popTo: self selectedContext]
  17689.             ifFalse: [interruptedProcess install: self selectedContext].
  17690.         ScheduledControllers
  17691.                         activeControllerNoTerminate: interruptedController
  17692.                         andProcess: interruptedProcess].
  17693.     "if old process was terminated, just terminate current one"
  17694.     interruptedProcess _ nil. 
  17695.     aScheduledController closeAndUnscheduleNoErase.
  17696.     Processor terminateActive
  17697. !
  17698. selectedContext
  17699.  
  17700.     contextStackIndex = 0
  17701.         ifTrue: [^contextStackTop]
  17702.         ifFalse: [^contextStack at: contextStackIndex]! !
  17703. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  17704.  
  17705. Debugger class
  17706.     instanceVariableNames: ''!
  17707.  
  17708. !Debugger class methodsFor: 'instance creation'!
  17709. context: aContext 
  17710.     "Answer an instance of me that models the current state of the system. 
  17711.     The active process has determined that a debugger should be set up 
  17712.     (often by the user issuing the command debug)."
  17713.     | aDebugger |
  17714.     aDebugger _ self new.
  17715.     aDebugger
  17716.         process: Processor activeProcess
  17717.         controller: (ScheduledControllers inActiveControllerProcess
  17718.                     ifTrue: [ScheduledControllers activeController])
  17719.         context: aContext.
  17720.     ^aDebugger!
  17721. interruptProcess: interruptedProcess 
  17722.     "Answer an instance of me that models the current state of the system. 
  17723.     The active process has decided to provide a debugger on an interrupted 
  17724.     process. This message is called if the user types the ctrl c interrupt, or a 
  17725.     low space notification occurs."
  17726.  
  17727.     | debugger |
  17728.     debugger _ self new.
  17729.     debugger
  17730.         process: interruptedProcess
  17731.         controller: (ScheduledControllers activeControllerProcess == interruptedProcess
  17732.                         ifTrue: [ScheduledControllers activeController])
  17733.         context: interruptedProcess suspendedContext.
  17734.     debugger externalInterrupt: true.
  17735.     ^debugger! !StandardSystemView subclass: #DebuggerView
  17736.     instanceVariableNames: ''
  17737.     classVariableNames: ''
  17738.     poolDictionaries: ''
  17739.     category: 'Interface-Debugger'!
  17740. DebuggerView comment:
  17741. 'I am a StandardSystemView that provides initialization methods (messages to myself) to create and schedule the interface to an interrupted process, a Debugger.'!
  17742.  
  17743. !DebuggerView methodsFor: 'no messages'! !
  17744. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  17745.  
  17746. DebuggerView class
  17747.     instanceVariableNames: ''!
  17748.  
  17749. !DebuggerView class methodsFor: 'instance creation'!
  17750. debugger: aDebugger 
  17751.     "Answer a DebuggerView whose model is aDebugger. It consists of three 
  17752.     subviews, a ContextStackView (the ContextStackListView and 
  17753.     ContextStackCodeView), an InspectView of aDebugger's variables, and an 
  17754.     InspectView of the variables of the currently selected method context."
  17755.  
  17756.     | debuggerView contextStackView contextVariablesView receiverVariablesView |
  17757.     aDebugger expandStack.
  17758.     debuggerView _ self new model: aDebugger.
  17759.     contextStackView _ self buildContextStackView: aDebugger.
  17760.     receiverVariablesView _ self buildReceiverVariablesView: aDebugger.
  17761.     contextVariablesView _ self buildContextVariablesView: aDebugger.
  17762.     debuggerView addSubView: contextStackView.
  17763.     debuggerView
  17764.         addSubView: receiverVariablesView
  17765.         align: receiverVariablesView viewport topLeft
  17766.         with: contextStackView viewport bottomLeft.
  17767.     debuggerView
  17768.         addSubView: contextVariablesView
  17769.         align: contextVariablesView viewport topLeft
  17770.         with: receiverVariablesView viewport topRight.
  17771.     ^debuggerView!
  17772. openContext: aContext label: aString 
  17773.     "Create and schedule an instance of me on a Debugger for the method 
  17774.     context, aContext. The label of the standard system view is aString."
  17775.  
  17776.     self openDebugger: (Debugger context: aContext)
  17777.         label: aString!
  17778. openContext: haltContext label: aString contents: contentsString
  17779.     "Create and schedule a simple view on a Debugger on haltContext.
  17780.     The view is labeled with aString and shows a short sender stack."
  17781.     ErrorRecursion
  17782.         ifTrue: 
  17783.             [ErrorRecursion _ false.
  17784.             self primitiveError: aString].
  17785.     ErrorRecursion _ true.
  17786.     self openNotifier: (Debugger context: haltContext)
  17787.         contents: contentsString
  17788.         label: aString.
  17789.     ErrorRecursion _ false.
  17790.     Processor activeProcess suspend
  17791. !
  17792. openDebugger: aDebugger label: aString 
  17793.     "Create and schedule an instance of me on the model, aDebugger. The 
  17794.     label is aString."
  17795.  
  17796.     self openNoSuspendDebugger: aDebugger label: aString.
  17797.     Processor activeProcess suspend!
  17798. openInterrupt: aString onProcess: interruptedProcess 
  17799.     "Create and schedule a simple view with a debugger which can be opened later."
  17800.  
  17801.     | aDebugger |
  17802.     aDebugger _ Debugger interruptProcess: interruptedProcess.
  17803.     ^ self openNotifier: aDebugger
  17804.         contents: aDebugger interruptedContext shortStack
  17805.         label: aString!
  17806. openNoSuspendDebugger: aDebugger label: aString 
  17807.     "Answer a standard system view containing an instance of me on the model, aDebugger. The label is aString. Do not terminate the current active process. "
  17808.     | debuggerView |
  17809.     debuggerView _ self debugger: aDebugger.
  17810.     debuggerView label: aString.
  17811.     debuggerView minimumSize: 300 @ 200.
  17812.     debuggerView controller openNoTerminate.
  17813.     ^ debuggerView!
  17814. openNotifier: aDebugger contents: msgString label: label
  17815.     "Create and schedule a simple view with a debugger which can be opened later."
  17816.     | aStringHolderView topView displayPoint nLines |
  17817.     self flag: #developmentNote.
  17818.     Cursor normal show.
  17819.     aStringHolderView _ StringHolderView container:
  17820.         (StringHolder new contents: msgString).
  17821.     aStringHolderView controller: (NotifyStringHolderController debugger: aDebugger).
  17822.     topView _ StandardSystemView new.
  17823.     topView model: aStringHolderView model.
  17824.     topView addSubView: aStringHolderView.
  17825.     topView label: label.
  17826.     nLines _ 1 + (msgString occurrencesOf: Character cr).
  17827.     topView minimumSize: 350 @ (14*nLines + 6).
  17828.     displayPoint _ 
  17829.         ScheduledControllers activeController == nil
  17830.             ifTrue: [Display boundingBox center]
  17831.             ifFalse: [ScheduledControllers activeController view displayBox center].
  17832.     topView controller openNoTerminateDisplayAt: displayPoint.
  17833.     ^ topView! !
  17834.  
  17835. !DebuggerView class methodsFor: 'private'!
  17836. buildContextStackView: aDebugger
  17837.  
  17838.     | topView bottomView contextStackView |
  17839.     topView _ ContextStackListView new.
  17840.     topView model: aDebugger.
  17841.     topView window: (0 @ 0 extent: self contextStackLeftSize).
  17842.     topView borderWidthLeft: 2 right: 2 top: 2 bottom: 0.
  17843.     bottomView _ ContextStackCodeView new.
  17844.     bottomView model: aDebugger.
  17845.     bottomView controller: ContextStackCodeController new.
  17846.     bottomView window: (0 @ 0 extent: self contextStackRightSize).
  17847.     bottomView borderWidthLeft: 2 right: 2 top: 2 bottom: 0.
  17848.     contextStackView _ View new.
  17849.     contextStackView addSubView: topView.
  17850.     contextStackView
  17851.         addSubView: bottomView
  17852.         align: bottomView viewport topLeft
  17853.         with: topView viewport bottomLeft.
  17854.     ^contextStackView!
  17855. buildContextVariablesView: aDebugger
  17856.  
  17857.     | contextVariablesView leftView rightView |
  17858.     contextVariablesView _ 
  17859.         InspectorView inspector: aDebugger contextVariablesInspector.
  17860.     contextVariablesView controller: Controller new.
  17861.     leftView _ contextVariablesView firstSubView.
  17862.     rightView _ contextVariablesView lastSubView.
  17863.     leftView window: (0 @ 0 extent: self contextVariablesLeftSize).
  17864.     leftView borderWidthLeft: 2 right: 0 top: 2 bottom: 2.
  17865.     rightView window: (0 @ 0 extent: self contextVariablesRightSize).
  17866.     rightView borderWidthLeft: 2 right: 2 top: 2 bottom: 2.
  17867.     rightView transformation: View identityTransformation.
  17868.     rightView align: rightView viewport topLeft with: leftView viewport topRight.
  17869.     contextVariablesView window: contextVariablesView defaultWindow.
  17870.     ^contextVariablesView!
  17871. buildReceiverVariablesView: aDebugger
  17872.  
  17873.     | receiverVariablesView leftView rightView |
  17874.     receiverVariablesView _ InspectorView inspector: aDebugger receiverInspector.
  17875.     receiverVariablesView controller: Controller new.
  17876.     leftView _ receiverVariablesView firstSubView.
  17877.     rightView _ receiverVariablesView lastSubView.
  17878.     leftView window: (0 @ 0 extent: self receiverVariablesLeftSize).
  17879.     leftView borderWidthLeft: 2 right: 0 top: 2 bottom: 2.
  17880.     rightView window: (0 @ 0 extent: self receiverVariablesRightSize).
  17881.     rightView borderWidthLeft: 2 right: 0 top: 2 bottom: 2.
  17882.     rightView transformation: View identityTransformation.
  17883.     rightView align: rightView viewport topLeft with: leftView viewport topRight.
  17884.     receiverVariablesView window: receiverVariablesView defaultWindow.
  17885.     ^receiverVariablesView!
  17886. contextStackLeftSize
  17887.  
  17888.     ^150 @ 50!
  17889. contextStackRightSize
  17890.     ^150 @ 75!
  17891. contextVariablesLeftSize
  17892.  
  17893.     ^25 @ 50!
  17894. contextVariablesRightSize
  17895.  
  17896.     ^50 @ 50!
  17897. proceedValueLeftSize
  17898.  
  17899.     ^50 @ 10!
  17900. proceedValueRightSize
  17901.  
  17902.     ^100 @ 10!
  17903. receiverVariablesLeftSize
  17904.  
  17905.     ^25 @ 50!
  17906. receiverVariablesRightSize
  17907.  
  17908.     ^50 @ 50! !InstructionStream subclass: #Decompiler
  17909.     instanceVariableNames: 'constructor method instVars tempVars constTable stack statements lastPc exit lastJumpPc lastReturnPc limit hasValue blockStackBase '
  17910.     classVariableNames: 'ArgumentFlag CascadeFlag '
  17911.     poolDictionaries: ''
  17912.     category: 'System-Compiler'!
  17913. Decompiler comment:
  17914. 'I decompile a method in three phases:
  17915.     Reverser: postfix byte codes -> prefix symbolic codes (nodes and atoms)
  17916.     Parser: prefix symbolic codes -> node tree (same as the compiler)
  17917.     Printer: node tree -> text (done by the nodes)'!
  17918.  
  17919. !Decompiler methodsFor: 'initialize-release'!
  17920. initSymbols: aClass
  17921.  
  17922.     | nTemps |
  17923.     constructor
  17924.         method: method
  17925.         class: aClass
  17926.         literals: method literals.
  17927.     constTable _ constructor codeConstants.
  17928.     instVars _ Array new: aClass instSize.
  17929.     "parse the header"
  17930.     nTemps _ method numTemps.
  17931.     tempVars _ Array new: nTemps.
  17932.     1 to: nTemps do: [:i | tempVars at: i put: (constructor codeTemp: i - 1)]! !
  17933.  
  17934. !Decompiler methodsFor: 'control'!
  17935. blockTo: end
  17936.     "Decompile a range of code as in statementsTo:, but return a block node."
  17937.     | exprs block oldBase |
  17938.     oldBase _ blockStackBase.
  17939.     blockStackBase _ stack size.
  17940.     exprs _ self statementsTo: end.
  17941.     block _ constructor codeBlock: exprs returns: lastReturnPc = lastPc.
  17942.     blockStackBase _ oldBase.
  17943.     lastReturnPc _ -1.  "So as not to mislead outer calls"
  17944.     ^block!
  17945. checkForBlock: receiver
  17946.     "We just saw a blockCopy: message. Check for a following block."
  17947.  
  17948.     | savePc jump args argPos block |
  17949.     receiver == constructor codeThisContext ifFalse: [^false].
  17950.     savePc _ pc.
  17951.     (jump _ self interpretJump) notNil
  17952.         ifFalse:
  17953.             [pc _ savePc.  ^nil].
  17954.     "Definitely a block"
  17955.     jump _ jump + pc.
  17956.     argPos _ statements size.
  17957.     [self willStorePop]
  17958.         whileTrue:
  17959.             [stack addLast: ArgumentFlag.  "Flag for doStore:"
  17960.             self interpretNextInstructionFor: self].
  17961.     args _ Array new: statements size - argPos.
  17962.     1 to: args size do: [:i | args at: i put: statements removeLast].  "Retrieve args"
  17963.     block _ self blockTo: jump.
  17964.     stack addLast: (constructor codeArguments: args block: block).
  17965.     ^true!
  17966. statementsTo: end
  17967.     "Decompile the method from pc up to end and return an array of
  17968.     expressions. If at run time this block will leave a value on the stack,
  17969.     set hasValue to true. If the block ends with a jump or return, set exit
  17970.     to the destination of the jump, or the end of the method; otherwise, set
  17971.     exit = end. Leave pc = end."
  17972.  
  17973.     | blockPos stackPos t |
  17974.     blockPos _ statements size.
  17975.     stackPos _ stack size.
  17976.     [pc < end]
  17977.         whileTrue:
  17978.             [lastPc _ pc.  limit _ end.  "for performs"
  17979.             self interpretNextInstructionFor: self].
  17980.     "If there is an additional item on the stack, it will be the value
  17981.     of this block."
  17982.     (hasValue _ stack size > stackPos)
  17983.         ifTrue:
  17984.             [statements addLast: stack removeLast].
  17985.     lastJumpPc = lastPc ifFalse: [exit _ pc].
  17986.     ^self popTo: blockPos! !
  17987.  
  17988. !Decompiler methodsFor: 'instruction decoding'!
  17989. blockReturnTop
  17990.     "No action needed"!
  17991. case: dist
  17992.     "statements = keyStmts CascadeFlag keyValueBlock ... keyStmts"
  17993.  
  17994.     | nextCase end thenJump stmtStream elements b node cases otherBlock |
  17995.     nextCase _ pc + dist.
  17996.     end _ limit.
  17997.     "Now add CascadeFlag & keyValueBlock to statements"
  17998.     statements addLast: stack removeLast; addLast: (self blockTo: nextCase).
  17999.     stack last == CascadeFlag
  18000.         ifFalse: "Last case"
  18001.             ["ensure jump is within block (in case thenExpr returns wierdly I guess)"
  18002.             thenJump _ exit <= end ifTrue: [exit] ifFalse: [nextCase].
  18003.             stmtStream _ ReadStream on: (self popTo: stack removeLast).
  18004.             elements _ OrderedCollection new.
  18005.             b _ OrderedCollection new.
  18006.             [stmtStream atEnd] whileFalse:
  18007.                 [(node _ stmtStream next) == CascadeFlag
  18008.                     ifTrue:
  18009.                         [elements addLast: (constructor
  18010.                             codeMessage: (constructor codeBlock: b returns: false)
  18011.                             selector: (constructor codeSelector: #-> code: #macro)
  18012.                             arguments: (Array with: stmtStream next)).
  18013.                          b _ OrderedCollection new]
  18014.                     ifFalse: [b addLast: node]].
  18015.             b size > 0 ifTrue: [self error: 'Bad cases'].
  18016.             cases _ constructor codeBrace: elements.
  18017.             otherBlock _ self blockTo: thenJump.
  18018.             stack addLast:
  18019.                 (constructor
  18020.                     codeMessage: stack removeLast
  18021.                     selector: (constructor codeSelector: #caseOf:otherwise: code: #macro)
  18022.                     arguments: (Array with: cases with: otherBlock))]!
  18023. doDup
  18024.  
  18025.     stack last == CascadeFlag
  18026.         ifFalse:
  18027.             ["Save position and mark cascade"
  18028.             stack addLast: statements size.
  18029.             stack addLast: CascadeFlag].
  18030.     stack addLast: CascadeFlag!
  18031. doPop
  18032.  
  18033.     statements addLast: stack removeLast!
  18034. doStore: stackOrBlock
  18035.     "Only called internally, not from InstructionStream. StackOrBlock is stack
  18036.     for store, statements for storePop."
  18037.  
  18038.     | var expr |
  18039.     var _ stack removeLast.
  18040.     expr _ stack removeLast.
  18041.     stackOrBlock addLast: (expr == ArgumentFlag
  18042.         ifTrue: [var]
  18043.         ifFalse: [constructor codeAssignTo: var value: expr])!
  18044. jump: dist
  18045.  
  18046.     exit _ pc + dist.
  18047.     lastJumpPc _ lastPc!
  18048. jump: dist if: condition
  18049.  
  18050.     | savePc elseDist sign elsePc elseStart end cond ifExpr thenBlock elseBlock thenJump
  18051.         elseJump condHasValue n b |
  18052.     stack last == CascadeFlag ifTrue: [^self case: dist].
  18053.     elsePc _ lastPc.
  18054.     elseStart _ pc + dist.
  18055.     end _ limit.
  18056.     "Check for bfp-jmp to invert condition.
  18057.     Don't be fooled by a loop with a null body."
  18058.     sign _ condition.
  18059.     savePc _ pc.
  18060.     ((elseDist _ self interpretJump) notNil and: [elseDist >= 0 and: [elseStart = pc]])
  18061.         ifTrue: [sign _ sign not.  elseStart _ pc + elseDist]
  18062.         ifFalse: [pc _ savePc].
  18063.     ifExpr _ stack removeLast.
  18064.     thenBlock _ self blockTo: elseStart.
  18065.     condHasValue _ hasValue.
  18066.     "ensure jump is within block (in case thenExpr returns)"
  18067.     thenJump _ exit <= end ifTrue: [exit] ifFalse: [elseStart].
  18068.     "if jump goes back, then it's a loop"
  18069.     thenJump < elseStart
  18070.         ifTrue:
  18071.             ["thenJump will jump to the beginning of the while expr.  In the case of
  18072.             while's with a block in the condition, the while expr
  18073.             should include more than just the last expression: find all the
  18074.             statements needed by re-decompiling."
  18075.             pc _ thenJump.
  18076.             b _ self statementsTo: elsePc.
  18077.             "discard unwanted statements from block"
  18078.             b size - 1 timesRepeat: [statements removeLast].
  18079.             statements addLast: (constructor
  18080.                     codeMessage: (constructor codeBlock: b returns: false)
  18081.                     selector: (constructor codeSelector: (sign ifTrue: [#whileFalse:] ifFalse: [#whileTrue:]) code: #macro)
  18082.                     arguments: (Array with: thenBlock)).
  18083.             pc _ elseStart]
  18084.         ifFalse:
  18085.             [elseBlock _ self blockTo: thenJump.
  18086.             elseJump _ exit.
  18087.             "if elseJump is backwards, it is not part of the elseExpr"
  18088.             elseJump < elsePc
  18089.                 ifTrue: [pc _ lastPc].
  18090.             cond _ constructor
  18091.                         codeMessage: ifExpr
  18092.                         selector: (constructor codeSelector: #ifTrue:ifFalse: code: #macro)
  18093.                         arguments:
  18094.                             (sign
  18095.                                 ifTrue: [Array with: elseBlock with: thenBlock]
  18096.                                 ifFalse: [Array with: thenBlock with: elseBlock]).
  18097.             condHasValue
  18098.                 ifTrue: [stack addLast: cond]
  18099.                 ifFalse: [statements addLast: cond]]!
  18100. methodReturnConstant: value
  18101.  
  18102.     self pushConstant: value; methodReturnTop!
  18103. methodReturnReceiver
  18104.  
  18105.     self pushReceiver; methodReturnTop!
  18106. methodReturnTop
  18107.     | last |
  18108.     last _ stack removeLast.
  18109.     stack size > blockStackBase  "get effect of elided pop before return"
  18110.         ifTrue: [statements addLast: stack removeLast].
  18111.     exit _ method size + 1.
  18112.     lastJumpPc _ lastReturnPc _ lastPc.
  18113.     statements addLast: last!
  18114. popIntoLiteralVariable: value
  18115.  
  18116.     self pushLiteralVariable: value; doStore: statements!
  18117. popIntoReceiverVariable: offset
  18118.  
  18119.     self pushReceiverVariable: offset; doStore: statements!
  18120. popIntoTemporaryVariable: offset
  18121.  
  18122.     self pushTemporaryVariable: offset; doStore: statements!
  18123. pushActiveContext
  18124.  
  18125.     stack addLast: constructor codeThisContext!
  18126. pushConstant: value
  18127.  
  18128.     | node |
  18129.     node _ value == true ifTrue: [constTable at: 2]
  18130.         ifFalse: [value == false ifTrue: [constTable at: 3]
  18131.         ifFalse: [value == nil ifTrue: [constTable at: 4]
  18132.         ifFalse: [constructor codeAnyLiteral: value]]].
  18133.     stack addLast: node!
  18134. pushLiteralVariable: assoc
  18135.  
  18136.     stack addLast: (constructor codeAnyLitInd: assoc)!
  18137. pushReceiver
  18138.  
  18139.     stack addLast: (constTable at: 1)!
  18140. pushReceiverVariable: offset
  18141.  
  18142.     | var |
  18143.     (var _ instVars at: offset + 1) == nil
  18144.         ifTrue:
  18145.             ["Not set up yet"
  18146.             instVars at: offset + 1 put: (var _ constructor codeInst: offset)].
  18147.     stack addLast: var!
  18148. pushTemporaryVariable: offset
  18149.  
  18150.     stack addLast: (tempVars at: offset + 1)!
  18151. send: selector super: superFlag numArgs: numArgs
  18152.  
  18153.     | args rcvr selNode msgNode elements numElements messages |
  18154.     selector == #toBraceStack:
  18155.         ifTrue: [^self formBrace].
  18156.     args _ Array new: numArgs.
  18157.     (numArgs to: 1 by: -1) do:
  18158.         [:i | args at: i put: stack removeLast].
  18159.     rcvr _ stack removeLast.
  18160.     superFlag ifTrue: [rcvr _ constructor codeSuper].
  18161.     (selector == #blockCopy: and: [self checkForBlock: rcvr])
  18162.         ifFalse:
  18163.             [selNode _ constructor codeAnySelector: selector.
  18164.             rcvr == CascadeFlag
  18165.                 ifTrue:
  18166.                     [self willJumpIfFalse
  18167.                         ifTrue: "= generated by a case macro"
  18168.                             [selector ~= #= ifTrue: [self error: 'bad case: ', selector].
  18169.                              statements addLast: args first.
  18170.                              stack addLast: rcvr. "restore CascadeFlag"
  18171.                              ^self]
  18172.                         ifFalse:
  18173.                             [msgNode _ constructor codeCascadedMessage: selNode arguments: args].
  18174.                     stack last == CascadeFlag
  18175.                         ifFalse:
  18176.                             ["Last message of a cascade"
  18177.                             statements addLast: msgNode.
  18178.                             messages _ self popTo: stack removeLast.  "Depth saved by first dup"
  18179.                             msgNode _ constructor
  18180.                                 codeCascade: stack removeLast
  18181.                                 messages: messages]]
  18182.                 ifFalse:
  18183.                     [msgNode _ selector == #fromBraceStack:
  18184.                         ifTrue:
  18185.                             [numElements _ args first literalValue.
  18186.                              elements _ Array new: numElements.
  18187.                              numElements to: 1 by: -1 do:
  18188.                                 [:i | elements at: i put: stack removeLast].
  18189.                              constructor codeBrace: elements as: rcvr]
  18190.                         ifFalse:
  18191.                             [constructor
  18192.                                 codeMessage: rcvr
  18193.                                 selector: selNode
  18194.                                 arguments: args]].
  18195.             stack addLast: msgNode]!
  18196. storeIntoLiteralVariable: assoc
  18197.  
  18198.     self pushLiteralVariable: assoc; doStore: stack!
  18199. storeIntoReceiverVariable: offset
  18200.  
  18201.     self pushReceiverVariable: offset; doStore: stack!
  18202. storeIntoTemporaryVariable: offset
  18203.  
  18204.     self pushTemporaryVariable: offset; doStore: stack! !
  18205.  
  18206. !Decompiler methodsFor: 'public access'!
  18207. decompile: aSelector in: aClass 
  18208.     "See Decompiler|decompile:in:method:. The method is found by looking up 
  18209.     the message, aSelector, in the method dictionary of the class, aClass."
  18210.  
  18211.     ^self
  18212.         decompile: aSelector
  18213.         in: aClass
  18214.         method: (aClass compiledMethodAt: aSelector)!
  18215. decompile: aSelector in: aClass method: aMethod
  18216.     "Answer a MethodNode that is the root of the parse tree for the 
  18217.     argument, aMethod, which is the CompiledMethod associated with the 
  18218.     message, aSelector. Variables are determined with respect to the 
  18219.     argument, aClass."
  18220.  
  18221.     ^self
  18222.         decompile: aSelector
  18223.         in: aClass
  18224.         method: aMethod
  18225.         using: DecompilerConstructor new!
  18226. tempAt: offset
  18227.     "Needed by BraceConstructor<PopIntoTemporaryVariable"
  18228.  
  18229.     ^tempVars at: offset + 1! !
  18230.  
  18231. !Decompiler methodsFor: 'private'!
  18232. convertToDoLoop
  18233.     "If statements contains the pattern
  18234.         var _ startConst.
  18235.         [var <= limit] whileTrue: [...statements... var _ var + incConst]
  18236.     then replace this by
  18237.         startConst to: limit by: incConst do: [:var | ...statements...]"
  18238.     | initStmt toDoStmt |
  18239.     statements size < 2 ifTrue: [^ self].
  18240.     initStmt _ statements at: statements size-1.
  18241.     (initStmt isMemberOf: AssignmentNode) ifTrue:
  18242.         [toDoStmt _ statements last whileAsToDo: initStmt.
  18243.         toDoStmt notNil ifTrue:
  18244.             [statements removeLast; removeLast; addLast: toDoStmt]]!
  18245. decompile: aSelector in: aClass method: aMethod using: aConstructor
  18246.  
  18247.     | block |
  18248.     constructor _ aConstructor.
  18249.     method _ aMethod.
  18250.     self initSymbols: aClass.  "create symbol tables"
  18251.     method isQuick
  18252.         ifTrue: [block _ self quickMethod]
  18253.         ifFalse: 
  18254.             [stack _ OrderedCollection new: method frameSize.
  18255.             statements _ OrderedCollection new: 20.
  18256.             super method: method pc: method initialPC.
  18257.             block _ self blockTo: method endPC + 1.
  18258.             stack isEmpty ifFalse: [self error: 'stack not empty']].
  18259.     ^constructor
  18260.         codeMethod: aSelector
  18261.         block: block
  18262.         tempVars: tempVars
  18263.         primitive: method primitive
  18264.         class: aClass!
  18265. formBrace
  18266.     "A #toBraceStream: selector has been encountered as part of a sequence:
  18267.         <Literal n> <Send toBraceStream:> <Pop> <Store#n> ... <Store#1>
  18268.      where <Store#i> is either a <StorePop> or a sequence like the above.
  18269.      The top of the stack must therefore be a LiteralNode with the key n.
  18270.      Beneath that is usually the right-hand side of the assignment.
  18271.      However, there may be an intervening pair of CascadeFlags and a number
  18272.      beneath them.
  18273.  
  18274.      Create a BraceNode and let it consume the pop & stores to determine its variables.
  18275.      Create an AssignmentNode with the BraceNode as its variable and the
  18276.      right-hand-side as its value.  Add the AssignmentNode to statements.
  18277.  
  18278.      If two CascadeFlags are encountered instead of the right-hand-side, pop them
  18279.      and the number beneath them to find the right-hand-side, and leave the
  18280.      Assignment node on the stack instead of adding it to statements
  18281.      (this happens in cases like  x _ {a. b} _ ...)."
  18282.  
  18283.     | var expr dest |
  18284.     var _ constructor codeBrace: stack removeLast literalValue fromBytes: self.
  18285.     (expr _ stack removeLast) == CascadeFlag
  18286.         ifTrue: "multiple assignment, more to come"
  18287.             [stack removeLast; removeLast. "CascadeFlag, number"
  18288.             expr _ stack removeLast.
  18289.             dest _ stack]
  18290.         ifFalse: "store and pop"
  18291.             [dest _ statements].
  18292.     dest addLast: (constructor codeAssignTo: var value: expr)!
  18293. popTo: oldPos
  18294.  
  18295.     | t |
  18296.     t _ Array new: statements size - oldPos.
  18297.     (t size to: 1 by: -1) do:
  18298.         [:i | t at: i put: statements removeLast].
  18299.     ^t!
  18300. quickMethod
  18301.     ^ method isReturnSpecial
  18302.         ifTrue: [constructor codeBlock:
  18303.                 (Array with: (constTable at: method primitive - 255)) returns: true]
  18304.         ifFalse: [method isReturnField
  18305.             ifTrue: [constructor codeBlock:
  18306.                 (Array with: (constructor codeInst: method returnField)) returns: true]
  18307.             ifFalse: [self error: 'improper short method']]! !
  18308. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  18309.  
  18310. Decompiler class
  18311.     instanceVariableNames: ''!
  18312.  
  18313. !Decompiler class methodsFor: 'class initialization'!
  18314. initialize
  18315.  
  18316.     CascadeFlag _ 'cascade'.  "A unique object"
  18317.     ArgumentFlag _ 'argument'.  "Ditto"
  18318.  
  18319.     "Decompiler initialize"! !
  18320.  
  18321. Decompiler initialize!
  18322. ParseNode subclass: #DecompilerConstructor
  18323.     instanceVariableNames: 'method instVars nArgs literalValues tempVars '
  18324.     classVariableNames: ''
  18325.     poolDictionaries: ''
  18326.     category: 'System-Compiler'!
  18327. DecompilerConstructor comment:
  18328. 'I construct the node tree for a Decompiler.'!
  18329.  
  18330. !DecompilerConstructor methodsFor: 'initialize-release'!
  18331. method: aMethod class: aClass literals: literals
  18332.  
  18333.     method _ aMethod.
  18334.     instVars _ aClass allInstVarNames.
  18335.     nArgs _ method numArgs.
  18336.     literalValues _ literals! !
  18337.  
  18338. !DecompilerConstructor methodsFor: 'constructor'!
  18339. codeAnyLiteral: value
  18340.  
  18341.     ^LiteralNode new
  18342.         key: value
  18343.         index: 0
  18344.         type: LdLitType!
  18345. codeAnyLitInd: association
  18346.  
  18347.     ^VariableNode new
  18348.         name: association key
  18349.         key: association
  18350.         index: 0
  18351.         type: LdLitIndType!
  18352. codeAnySelector: selector
  18353.  
  18354.     ^SelectorNode new
  18355.         key: selector
  18356.         index: 0
  18357.         type: SendType!
  18358. codeArguments: args block: block
  18359.  
  18360.     ^block arguments: args!
  18361. codeAssignTo: variable value: expression
  18362.  
  18363.     ^AssignmentNode new variable: variable value: expression!
  18364. codeBlock: statements returns: returns
  18365.  
  18366.     ^BlockNode new statements: statements returns: returns!
  18367. codeBrace: elements
  18368.  
  18369.     ^BraceNode new elements: elements!
  18370. codeBrace: elements as: receiver
  18371.  
  18372.     | braceNode |
  18373.     braceNode _ self codeBrace: elements.
  18374.     ^(receiver isVariableReference and: [receiver key key == #Array])
  18375.         ifTrue: [braceNode]
  18376.         ifFalse:
  18377.             [self codeMessage: (braceNode collClass: receiver)
  18378.                     selector: (self codeSelector: #as: code: -1)
  18379.                     arguments: (Array with: receiver)]!
  18380. codeBrace: numElements fromBytes: anInstructionStream
  18381.  
  18382.     ^BraceConstructor new
  18383.         codeBrace: numElements
  18384.         fromBytes: anInstructionStream
  18385.         withConstructor: self!
  18386. codeCascade: receiver messages: messages
  18387.  
  18388.     ^CascadeNode new receiver: receiver messages: messages!
  18389. codeCascadedMessage: selector arguments: arguments
  18390.  
  18391.     ^self
  18392.         codeMessage: nil
  18393.         selector: selector
  18394.         arguments: arguments!
  18395. codeConstants
  18396.     "Answer with an array of the objects representing self, true, false, nil,
  18397.     -1, 0, 1, 2."
  18398.  
  18399.     | i |
  18400.     ^(Array with: NodeSelf with: NodeTrue with: NodeFalse with: NodeNil)
  18401.         , ((-1 to: 2) collect: [:i | LiteralNode new key: i code: LdMinus1 + i + 1])!
  18402. codeEmptyBlock
  18403.  
  18404.     ^BlockNode withJust: NodeNil!
  18405. codeInst: index
  18406.  
  18407.     ^VariableNode new
  18408.         name: (instVars at: index + 1)
  18409.         index: index
  18410.         type: LdInstType!
  18411. codeMessage: receiver selector: selector arguments: arguments
  18412.  
  18413.     | symbol |
  18414.     symbol _ selector key.
  18415.     ^MessageNode new
  18416.         receiver: receiver
  18417.         selector: selector
  18418.         arguments: arguments
  18419.         precedence:
  18420.             (symbol isInfix
  18421.                 ifTrue: [2]
  18422.                 ifFalse: [symbol isKeyword ifTrue: [3] ifFalse: [1]])!
  18423. codeMethod: selector block: block tempVars: vars primitive: primitive class: class
  18424.  
  18425.     | node precedence |
  18426.     node _ self codeSelector: selector code: nil.
  18427.     precedence _ selector isInfix
  18428.                 ifTrue: [2]
  18429.                 ifFalse: [selector isKeyword ifTrue: [3] ifFalse: [1]].
  18430.     tempVars _ vars.
  18431.     ^MethodNode new
  18432.         selector: node
  18433.         arguments: (tempVars copyFrom: 1 to: nArgs)
  18434.         precedence: precedence
  18435.         temporaries: (tempVars copyFrom: nArgs + 1 to: tempVars size)
  18436.         block: block
  18437.         encoder: (Encoder new initScopeAndLiteralTables
  18438.                     nTemps: tempVars size
  18439.                     literals: literalValues
  18440.                     class: class)
  18441.         primitive: primitive!
  18442. codeSelector: sel code: code
  18443.  
  18444.     ^SelectorNode new key: sel code: code!
  18445. codeSuper
  18446.  
  18447.     ^NodeSuper!
  18448. codeTemp: index
  18449.  
  18450.     ^VariableNode new
  18451.         name: 't' , (index + 1) printString
  18452.         index: index
  18453.         type: LdTempType!
  18454. codeThisContext
  18455.  
  18456.     ^NodeThisContext! !Object subclass: #Delay
  18457.     instanceVariableNames: 'delayDuration resumptionTime delaySemaphore beingWaitedOn '
  18458.     classVariableNames: 'ActiveDelayStartTime SuspendedDelays ActiveDelay AccessProtect TimingSemaphore '
  18459.     poolDictionaries: ''
  18460.     category: 'Kernel-Processes'!
  18461.  
  18462. !Delay methodsFor: 'delaying'!
  18463. wait
  18464.     "Suspend the process of the caller for the amount of time specified
  18465.      when the receiver was created."
  18466.  
  18467.     beingWaitedOn ifTrue: [ self error: 'A process is already waiting on this Delay' ].
  18468.     AccessProtect critical: [
  18469.         beingWaitedOn _ true.
  18470.         resumptionTime _ Time millisecondClockValue + delayDuration.
  18471.         ActiveDelay == nil
  18472.             ifTrue: [ self activate ]
  18473.             ifFalse: [
  18474.                 resumptionTime < ActiveDelay resumptionTime
  18475.                     ifTrue: [
  18476.                         SuspendedDelays add: ActiveDelay.
  18477.                         self activate ]
  18478.                     ifFalse: [ SuspendedDelays add: self ].
  18479.             ].
  18480.     ].
  18481.     delaySemaphore wait.! !
  18482.  
  18483. !Delay methodsFor: 'private'!
  18484. activate
  18485.     "Make the receiver the Delay to be signalled when the next timer
  18486.     interrupt occurs. This method should only be called from a block
  18487.     protected by the AccessProtect semaphore."
  18488.  
  18489.     ActiveDelay _ self.
  18490.     ActiveDelayStartTime _ Time millisecondClockValue.
  18491.     TimingSemaphore initSignals.
  18492.     Processor signal: TimingSemaphore atTime: resumptionTime.!
  18493. continueAfterSnapshot
  18494.     "Continue the active delay after resuming a snapshot."
  18495.     "Note: During a snapshot, the resumptionTime variable is used to record
  18496.     the time remaining on the active duration."
  18497.  
  18498.     resumptionTime _ Time millisecondClockValue + resumptionTime.
  18499.     ActiveDelayStartTime _ Time millisecondClockValue.
  18500.     TimingSemaphore initSignals.
  18501.     Processor signal: TimingSemaphore atTime: resumptionTime.!
  18502. delay: millisecondCount
  18503.     "Initialize this delay for the given number of milliseconds."
  18504.  
  18505.     delayDuration _ millisecondCount.
  18506.     delaySemaphore _ Semaphore new.
  18507.     beingWaitedOn _ false.!
  18508. recordTimeRemaining
  18509.     "Record (in resumptionTime) the amount of time remaining for the active
  18510.     delay (the receiver) just before a snapshot. The delay will be resumed
  18511.     when the snapshot resumes."
  18512.  
  18513.     | timeSoFar |
  18514.     timeSoFar _ Time millisecondClockValue - ActiveDelayStartTime.
  18515.     resumptionTime _ delayDuration - timeSoFar.
  18516. !
  18517. resumptionTime
  18518.     "Answer the value of the system's millisecondClock at which the 
  18519.     receiver's suspended Process will resume."
  18520.  
  18521.     ^ resumptionTime!
  18522. signalWaitingProcess
  18523.     "The delay time has elapsed; signal the waiting process."
  18524.  
  18525.     beingWaitedOn _ false.
  18526.     delaySemaphore signal.! !
  18527. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  18528.  
  18529. Delay class
  18530.     instanceVariableNames: ''!
  18531.  
  18532. !Delay class methodsFor: 'initialization'!
  18533. initialize
  18534.     "Initialize the class variables that keep track of active Delays."
  18535.     "Delay initialize"
  18536.  
  18537.     TimingSemaphore == nil ifFalse: [ TimingSemaphore terminateProcess ].
  18538.     TimingSemaphore _ Semaphore new.
  18539.     AccessProtect _ Semaphore forMutualExclusion.
  18540.     SuspendedDelays _ 
  18541.         SortedCollection sortBlock: 
  18542.             [ :d1 :d2 | d1 resumptionTime <= d2 resumptionTime].
  18543.     ActiveDelay _ nil.
  18544.     [self timerInterruptWatcher] forkAt: Processor timingPriority.!
  18545. timerInterruptWatcher
  18546.     "This loop runs in its own process. It waits for a timer interrupt and
  18547.     wakes up the active delay. Note that timer interrupts are only scheduled
  18548.     when there are active delays."
  18549.  
  18550.     [true] whileTrue: [
  18551.         TimingSemaphore wait.
  18552.         AccessProtect critical: [
  18553.             ActiveDelay signalWaitingProcess.
  18554.             SuspendedDelays isEmpty
  18555.                 ifTrue: [
  18556.                     ActiveDelay _ nil.
  18557.                     ActiveDelayStartTime _ nil.
  18558.                 ] ifFalse: [ SuspendedDelays removeFirst activate ].
  18559.         ].
  18560.     ].
  18561. ! !
  18562.  
  18563. !Delay class methodsFor: 'instance creation'!
  18564. forMilliseconds: t1 
  18565. ^ self new delay: t1!
  18566. forSeconds: t1 
  18567. ^ self new delay: t1 * 1000!
  18568. howToUse
  18569.     "An instance of Delay responds to the message wait by suspending the
  18570.     caller's process for a certain amount of time. The duration of the pause
  18571.     is specified when the Delay is created with the message forMilliseconds: or
  18572.     forSeconds:. A Delay can be used again when the current wait has finished.
  18573.     For example, a clock process might repeatedly wait on a one-second Delay."! !
  18574.  
  18575. !Delay class methodsFor: 'snapshotting'!
  18576. shutDown
  18577.     "Suspend the active delay, if any, before snapshotting. It will be reactived
  18578.     when the snapshot is resumed."
  18579.     "Details: This prevents a timer interrupt from waking up the active
  18580.     delay in the midst snapshoting, since the active delay will be
  18581.     restarted when resuming the snapshot and we don't want to process
  18582.     the delay twice."
  18583.  
  18584.     Processor signal: nil atTime: 0.
  18585.     AccessProtect wait.
  18586.     ActiveDelay == nil ifFalse: [ ActiveDelay recordTimeRemaining ].
  18587. !
  18588. startUp
  18589.     "Restart active delay, if any, when resuming a snapshot."
  18590.  
  18591.     ActiveDelay == nil ifFalse: [ ActiveDelay continueAfterSnapshot ].
  18592.     AccessProtect signal.
  18593. ! !
  18594.  
  18595. !Delay class methodsFor: 'testing'!
  18596. test2DelayOf: delay for: testCount label: label
  18597.     "Transcript cr. 
  18598.      Delay testDelayOf: 1000 for: 10 label: 'A'. 
  18599.      Delay testDelayOf: 2000 for: 10 label: 'B'"
  18600.  
  18601.     | myDelay |
  18602.     myDelay _ Delay forMilliseconds: delay.
  18603.     [    1 to: testCount do: [ :i |
  18604.             myDelay wait.
  18605.             Transcript show: label, i printString; cr.
  18606.         ].
  18607.     ] forkAt: Processor userInterruptPriority.
  18608. !
  18609. test2DelayOf: delay for: testCount rect: r
  18610.     "Transcript cr. 
  18611.      Delay test2DelayOf: 100 for: 20 rect: (10@10 extent: 10@10).
  18612.      Delay test2DelayOf: 400 for: 20 rect: (25@10 extent: 10@10)."
  18613.  
  18614.     | myDelay pauseDelay |
  18615.     myDelay    _ Delay forMilliseconds: delay - 50.
  18616.     pauseDelay _ Delay forMilliseconds: 50.
  18617.     Display fillBlack: r.
  18618.     [    1 to: testCount do: [ :i |
  18619.             Display fillWhite: r.
  18620.             pauseDelay wait.
  18621.             Display reverse: r.
  18622.             myDelay wait.
  18623.         ].
  18624.     ] forkAt: Processor userInterruptPriority.
  18625. !
  18626. testDelayOf: delay for: testCount label: label
  18627.     "Transcript cr. 
  18628.      Delay testDelayOf: 1000 for: 10 label: 'A'. 
  18629.      Delay testDelayOf: 2000 for: 10 label: 'B'"
  18630.  
  18631.     | myDelay |
  18632.     myDelay _ Delay forMilliseconds: delay.
  18633.     [    1 to: testCount do: [ :i |
  18634.             myDelay wait.
  18635.             Transcript show: label, i printString; cr.
  18636.         ].
  18637.     ] forkAt: Processor userInterruptPriority.
  18638. ! !
  18639.  
  18640. Delay initialize!
  18641. Object subclass: #DevelopmentSupport
  18642.     instanceVariableNames: ''
  18643.     classVariableNames: ''
  18644.     poolDictionaries: ''
  18645.     category: 'System-Support'!
  18646.  
  18647. !DevelopmentSupport methodsFor: 'no messages'! !
  18648. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  18649.  
  18650. DevelopmentSupport class
  18651.     instanceVariableNames: ''!
  18652. DevelopmentSupport class comment:
  18653. 'A place where to-do lists, notes to one another, etc., can be centralized.  1/27/96 sw'!
  18654.  
  18655. !DevelopmentSupport class methodsFor: 'scott's notes'!
  18656. changeSorterToDoList
  18657.     "Last changed: 2/7/96 sw"
  18658.  
  18659. "Need some relief for the property that when you reactivate a ChangeSorter, all unsubmitted edits in either text pane are summarily discarded (and also, it can take a long time to activate because the changesets are being updated
  18660.  
  18661. The menus are not necessarily up to date with other code-browsing menus.
  18662.  
  18663. Make sure the initial size/shape will fit okay on the current screen.
  18664.  
  18665. No protection against duplicate changeset names
  18666.  
  18667. No guarding against empty reply to changeset name.
  18668.  
  18669. Nice to have a single-change-sorter as well as Ted's Dual one.
  18670. "
  18671.  
  18672. !
  18673. filesToDo
  18674.     "2/3/96 sw
  18675.  
  18676. The file browser sucks in numerous ways.
  18677.  
  18678. One totally brain-damaged thing is that when you try to dismiss it, if there have been edits, you're asked 'is it okay to cancel changes', and when you say yes, it reads in the entire damned file again, just in time to close it.
  18679.  
  18680. Upgrade its menus.
  18681.  
  18682. Don't read in the entire damned file every time you move the window!!
  18683.  
  18684. "!
  18685. scottsToDoList
  18686.     "Last changed: 2/7/96 sw"
  18687.  
  18688. "Force popup menus onto screen.  Somehow they aren't protected from going off the bottom.
  18689. Open new windows properly stacked and never off-screen
  18690. Close all unchanged windows. (fix the sucker)
  18691. Sys browser window titles change with selected class
  18692. Dan's pane resizers
  18693. References in inspectListController.
  18694. Fix the indent/outdent
  18695. Remove Mac stuff and generally Toolbox access, or at least flag it.
  18696. When you remove a method, it shows up in change sorter as a removal, but versions doesn't work.  Might be nice to stash the version backpointer in the change token so that versions could be made to work...
  18697. Resolution about mac scrollbars
  18698. Fix weirdo behavior in scrollbars mentioned by Ted.
  18699. Ted's look back for uppercase pair at word start
  18700. "! !Set subclass: #Dictionary
  18701.     instanceVariableNames: ''
  18702.     classVariableNames: ''
  18703.     poolDictionaries: ''
  18704.     category: 'Collections-Unordered'!
  18705. NewDictionary comment:
  18706. 'I represent a set of elements that can be viewed from one of two perspectives: a set of associations, or a set of values that are externally named where the name can be any object that responds to =. The external name is referred to as the key.'!
  18707.  
  18708. !Dictionary methodsFor: 'accessing'!
  18709. associationAt: key 
  18710.     ^ self associationAt: key ifAbsent: [self errorKeyNotFound]!
  18711. associationAt: key ifAbsent: aBlock 
  18712.     "Answer the association with the given key.
  18713.     If key is not found, return the result of evaluating aBlock."
  18714.  
  18715.     | index assoc |
  18716.     index _ self findElementOrNil: key.
  18717.     assoc _ array at: index.
  18718.     nil == assoc ifTrue: [ ^ aBlock value ].
  18719.     ^ assoc!
  18720. at: key 
  18721.     "Answer the value associated with the key."
  18722.  
  18723.     ^ self at: key ifAbsent: [self errorKeyNotFound]!
  18724. at: key ifAbsent: aBlock 
  18725.  
  18726.     | index assoc |
  18727.     index _ self findElementOrNil: key.
  18728.     assoc _ array at: index.
  18729.     nil == assoc ifTrue: [ ^ aBlock value ].
  18730.     ^ assoc value!
  18731. at: key put: anObject 
  18732.     "Set the value at key to be anObject.  If key is not found, create a new
  18733.     entry for key and set is value to anObject. Answer anObject."
  18734.     | index element |
  18735.     index _ self findElementOrNil: key.
  18736.     element _ array at: index.
  18737.     element == nil
  18738.         ifTrue: [self atNewIndex: index put: (Association key: key value: anObject)]
  18739.         ifFalse: [element value: anObject].
  18740.     ^ anObject!
  18741. keyAtValue: value 
  18742.     "Answer the key that is the external name for the argument, value. If 
  18743.     there is none, answer nil."
  18744.  
  18745.     ^self keyAtValue: value ifAbsent: [self errorValueNotFound]!
  18746. keyAtValue: value ifAbsent: exceptionBlock
  18747.     "Answer the key that is the external name for the argument, value. If 
  18748.     there is none, answer the result of evaluating exceptionBlock."
  18749.  
  18750.     self associationsDo: 
  18751.         [:association | value == association value ifTrue: [^association key]].
  18752.     ^exceptionBlock value!
  18753. keys
  18754.     "Answer a Set containing the receiver's keys."
  18755.     | aSet key |
  18756.     aSet _ Set new: self size.
  18757.     self keysDo: [:key | aSet add: key].
  18758.     ^ aSet! !
  18759.  
  18760. !Dictionary methodsFor: 'testing'!
  18761. includes: anObject
  18762.  
  18763.     self do: [:each | anObject = each ifTrue: [^true]].
  18764.     ^false!
  18765. includesKey: key 
  18766.     "Answer whether the receiver has a key equal to the argument, key."
  18767.     | index |
  18768.     index _ self findElementOrNil: key.
  18769.     (array at: index) == nil    
  18770.         ifTrue: [^ false]
  18771.         ifFalse: [^ true]!
  18772. includesKey: aKey ifTrue: trueBlock ifFalse: falseBlock
  18773.     "If the receiver includes the given key, evaluate trueBlock, else evaluate falseBlock.  6/7/96 sw"
  18774.  
  18775.     self noteToDan.  "After the three hundredth time I submitted a method as if this glue existed, and then had to put parentheses around the includesKey: clause, I though it might be expedient to have this crutch available.  However, perhaps one could think of it as damaging because it would tempt people to assume you could do this elsewhere?!!  What do you think?"
  18776.  
  18777.     ^ (self includesKey: aKey)
  18778.         ifTrue:
  18779.             [trueBlock value]
  18780.         ifFalse:
  18781.             [falseBlock value]!
  18782. occurrencesOf: anObject 
  18783.     "Answer how many of the receiver's elements are equal to anObject."
  18784.  
  18785.     | count |
  18786.     count _ 0.
  18787.     self do: [:each | anObject = each ifTrue: [count _ count + 1]].
  18788.     ^count! !
  18789.  
  18790. !Dictionary methodsFor: 'adding'!
  18791. add: anAssociation
  18792.     | index element |
  18793.     index _ self findElementOrNil: anAssociation key.
  18794.     element _ array at: index.
  18795.     element == nil
  18796.         ifTrue: [self atNewIndex: index put: anAssociation]
  18797.         ifFalse: [element value: anAssociation value].
  18798.     ^ anAssociation!
  18799. declare: key from: aDictionary 
  18800.     "Add key to the receiver. If key already exists, do nothing. If aDictionary 
  18801.     includes key, then remove it from aDictionary and use its association as 
  18802.     the element of the receiver."
  18803.  
  18804.     (self includesKey: key) ifTrue: [^ self].
  18805.     (aDictionary includesKey: key)
  18806.         ifTrue: 
  18807.             [self add: (aDictionary associationAt: key).
  18808.             aDictionary removeKey: key]
  18809.         ifFalse: 
  18810.             [self add: key -> nil]! !
  18811.  
  18812. !Dictionary methodsFor: 'removing'!
  18813. remove: anObject
  18814.  
  18815.     self shouldNotImplement!
  18816. remove: anObject ifAbsent: exceptionBlock
  18817.  
  18818.     self shouldNotImplement!
  18819. removeKey: key 
  18820.     "Remove key from the receiver.
  18821.     If key is not in the receiver, notify an error."
  18822.  
  18823.     ^ self removeKey: key ifAbsent: [self errorKeyNotFound]!
  18824. removeKey: key ifAbsent: aBlock 
  18825.     "Remove key (and its associated value) from the receiver. If key is not in 
  18826.     the receiver, answer the result of evaluating aBlock. Otherwise, answer 
  18827.     the value externally named by key."
  18828.  
  18829.     | index assoc |
  18830.     index _ self findElementOrNil: key.
  18831.     assoc _ array at: index.
  18832.     assoc == nil ifTrue: [ ^ aBlock value ].
  18833.     array at: index put: nil.
  18834.     tally _ tally - 1.
  18835.     self fixCollisionsFrom: index.
  18836.     ^ assoc value! !
  18837.  
  18838. !Dictionary methodsFor: 'enumerating'!
  18839. associationsDo: aBlock 
  18840.     "Evaluate aBlock for each of the receiver's elements (key/value 
  18841.     associations)."
  18842.  
  18843.     super do: aBlock!
  18844. collect: aBlock 
  18845.     "Evaluate aBlock with each of my values as the argument.  Collect the
  18846.     resulting values into a collection that is like me. Answer with the new
  18847.     collection."
  18848.     | newCollection |
  18849.     newCollection _ OrderedCollection new: self size.
  18850.     self do: [:each | newCollection add: (aBlock value: each)].
  18851.     ^ newCollection!
  18852. do: aBlock
  18853.  
  18854.     super do: [:assoc | aBlock value: assoc value]!
  18855. keysDo: aBlock 
  18856.     "Evaluate aBlock for each of the receiver's keys."
  18857.  
  18858.     self associationsDo: [:association | aBlock value: association key]!
  18859. select: aBlock 
  18860.     "Evaluate aBlock with each of my values as the argument. Collect into a
  18861.     new dictionary, only those associations for which aBlock evaluates to
  18862.     true."
  18863.  
  18864.     | newCollection |
  18865.     newCollection _ self species new.
  18866.     self associationsDo: 
  18867.         [:each | 
  18868.         (aBlock value: each value) ifTrue: [newCollection add: each]].
  18869.     ^newCollection! !
  18870.  
  18871. !Dictionary methodsFor: 'printing'!
  18872. printOn: aStream
  18873.     | tooMany |
  18874.     tooMany _ self maxPrint.    
  18875.         "Need absolute limit, or infinite recursion will never 
  18876.         notice anything going wrong.  7/26/96 tk"
  18877.     aStream nextPutAll: self class name, ' ('.
  18878.     self associationsDo: 
  18879.         [:element | 
  18880.         aStream position > tooMany
  18881.             ifTrue: [aStream nextPutAll: '...etc...)'. ^ self].
  18882.         element printOn: aStream.
  18883.         aStream space].
  18884.     aStream nextPut: $)!
  18885. storeOn: aStream
  18886.     | noneYet |
  18887.     aStream nextPutAll: '(('.
  18888.     aStream nextPutAll: self class name.
  18889.     aStream nextPutAll: ' new)'.
  18890.     noneYet _ true.
  18891.     self associationsDo: 
  18892.             [:each | 
  18893.             noneYet
  18894.                 ifTrue: [noneYet _ false]
  18895.                 ifFalse: [aStream nextPut: $;].
  18896.             aStream nextPutAll: ' add: '.
  18897.             aStream store: each].
  18898.     noneYet ifFalse: [aStream nextPutAll: '; yourself'].
  18899.     aStream nextPut: $)! !
  18900.  
  18901. !Dictionary methodsFor: 'private'!
  18902. errorKeyNotFound
  18903.  
  18904.     self error: 'key not found'!
  18905. errorValueNotFound
  18906.  
  18907.     self error: 'value not found'!
  18908. keyAt: index
  18909.     "May be overridden by subclasses so that fixCollisions will work"
  18910.     | assn |
  18911.     assn _ array at: index.
  18912.     assn == nil ifTrue: [^ nil]
  18913.                 ifFalse: [^ assn key]!
  18914. noCheckAdd: anObject
  18915.     "Must be defined separately for Dictionary because (self findElementOrNil:) expects a key, not an association.  9/7/96 tk"
  18916.  
  18917.     array at: (self findElementOrNil: anObject key) put: anObject.
  18918.     tally _ tally + 1!
  18919. rehash
  18920.     "Smalltalk rehash."
  18921.     | newSelf |
  18922.     newSelf _ self species new: self size.
  18923.     self associationsDo: [:each | newSelf noCheckAdd: each].
  18924.     array _ newSelf array!
  18925. scanFor: key from: start to: finish
  18926.     "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches the key. Answer the index of that slot or zero if no slot is found within the given range of indices."
  18927.  
  18928.     | element |
  18929.     "this speeds up a common case: key is in the first slot"
  18930.     ((element _ array at: start) == nil or: [element key = key])
  18931.         ifTrue: [ ^ start ].
  18932.  
  18933.     start + 1 to: finish do: [ :index |
  18934.         ((element _ array at: index) == nil or: [element key = key])
  18935.             ifTrue: [ ^ index ].
  18936.     ].
  18937.     ^ 0!
  18938. valueAtNewKey: aKey put: anObject atIndex: index declareFrom: aDictionary 
  18939.     "Support for coordinating class variable and global declarations
  18940.     with variables that have been put in Undeclared so as to
  18941.     redirect all references to the undeclared variable."
  18942.  
  18943.     (aDictionary includesKey: aKey)
  18944.         ifTrue: 
  18945.             [self atNewIndex: index 
  18946.                 put: ((aDictionary associationAt: aKey) value: anObject).
  18947.             aDictionary removeKey: aKey]
  18948.         ifFalse: 
  18949.             [self atNewIndex: index put: (Association key: aKey value: anObject)]! !
  18950.  
  18951. !Dictionary methodsFor: 'user interface'!
  18952. inspect
  18953.     "Open a NewDictionaryInspector on the receiver.  N.B.: this is
  18954.     an inspector without trash, since InspectorTrash doesn't do the
  18955.     obvious thing right now.  Use basicInspect to get a normal
  18956.     (less useful) type of inspector."
  18957.  
  18958.     InspectorView open: (InspectorView dictionaryInspector:
  18959.         (DictionaryInspector inspect: self))!
  18960. inspectFormsWithLabel: aLabel
  18961.     "Open a Form Dictionary inspector on the receiver, with the given label.  6/28/96 sw"
  18962.  
  18963.     InspectorView open: (InspectorView formDictionaryInspector:
  18964.         (DictionaryInspector inspect: self)) withLabel: aLabel!
  18965. inspectWithLabel: aLabel
  18966.     "Open a NewDictionaryInspector on the receiver.  N.B.: this is
  18967.     an inspector without trash, since InspectorTrash doesn't do the
  18968.     obvious thing right now.  Use basicInspect to get a normal
  18969.     (less useful) type of inspector."
  18970.     InspectorView open: (InspectorView dictionaryInspector:
  18971.         (DictionaryInspector inspect: self)) withLabel: aLabel! !
  18972. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  18973.  
  18974. Dictionary class
  18975.     instanceVariableNames: ''!
  18976.  
  18977. !Dictionary class methodsFor: 'instance creation'!
  18978. fromBraceStack: itsSize 
  18979.     "Answer an instance of me with itsSize elements, popped in reverse order from
  18980.      the stack of thisContext sender.  Do not call directly: this is called by {1. 2. 3}
  18981.      constructs."
  18982.  
  18983.     ^ self newFrom: ((Array new: itsSize) fill: itsSize fromStack: thisContext sender)!
  18984. newFrom: aDict 
  18985.     "Answer an instance of me containing the same associations as aDict.
  18986.      Error if any key appears twice."
  18987.     | newDictionary |
  18988.     newDictionary _ self new: aDict size.
  18989.     aDict associationsDo:
  18990.         [:x |
  18991.         (newDictionary includesKey: x key)
  18992.             ifTrue: [self error: 'Duplicate key: ', x key printString]
  18993.             ifFalse: [newDictionary add: x]].
  18994.     ^ newDictionary
  18995.  
  18996. "    NewDictionary newFrom: {1->#a. 2->#b. 3->#c}
  18997.     {1->#a. 2->#b. 3->#c} as: NewDictionary
  18998.     NewDictionary newFrom: {1->#a. 2->#b. 1->#c}
  18999.     {1->#a. 2->#b. 1->#c} as: NewDictionary
  19000. "! !Inspector subclass: #DictionaryInspector
  19001.     instanceVariableNames: 'keyArray '
  19002.     classVariableNames: ''
  19003.     poolDictionaries: ''
  19004.     category: 'Interface-Inspector'!
  19005.  
  19006. !DictionaryInspector methodsFor: 'accessing'!
  19007. fieldList
  19008.     ^ keyArray collect: [ :key | key printString ]!
  19009. inspect: aDictionary
  19010.     "Initialize the receiver so that it is inspecting aDictionary. There is no 
  19011.     current selection."
  19012.  
  19013.     self initialize.
  19014.     (aDictionary isKindOf: Dictionary) ifFalse:
  19015.         [^ self error: 'DictionaryInspectors can only inspect dictionaries' ].
  19016.     object _ aDictionary.
  19017.     contents _ ''.
  19018.     self calculateKeyArray! !
  19019.  
  19020. !DictionaryInspector methodsFor: 'selecting'!
  19021. addEntry: aKey
  19022.     object at: aKey put: nil.
  19023.     self calculateKeyArray.
  19024.     selectionIndex _ keyArray indexOf: aKey.
  19025.     self changed: #inspectObject.
  19026.     self update!
  19027. calculateKeyArray
  19028.     "Recalculate the KeyArray from the object being inspected"
  19029.  
  19030.     | sortedKeys |
  19031.     sortedKeys _ SortedCollection new: object size.
  19032.     sortedKeys sortBlock: [ :x :y |
  19033.         (((x isKindOf: String) & (y isKindOf: String))
  19034.         or: [(x isKindOf: Number) & (y isKindOf: Number)])
  19035.             ifTrue: [ x < y]
  19036.             ifFalse: [ (x class = y class)
  19037.                 ifTrue: [ x printString < y printString]
  19038.                 ifFalse: [ x class name < y class name ] ] ].
  19039.     object keysDo:
  19040.         [ :aKey | sortedKeys add: aKey. ].
  19041.     keyArray _ sortedKeys asArray.
  19042.     selectionIndex _ 0.
  19043. !
  19044. removeSelection
  19045.     object removeKey: (keyArray at: selectionIndex).
  19046.     selectionIndex _ 0.
  19047.     contents _ ''.
  19048.     self calculateKeyArray.
  19049.     self changed: #inspectObject.
  19050.     self changed: #selection.!
  19051. replaceSelectionValue: anObject
  19052.     ^ object at: (keyArray at: selectionIndex) put: anObject!
  19053. selection
  19054.     ^ object at: (keyArray at: selectionIndex)!
  19055. selectionAssociation
  19056.     ^ object associationAt: (keyArray at: selectionIndex)!
  19057. selectionUnmodifiable
  19058.     "For dicionary inspectors, any selection is modifiable"
  19059.  
  19060.     ^ selectionIndex <= 0! !InspectListController subclass: #DictionaryListController
  19061.     instanceVariableNames: ''
  19062.     classVariableNames: 'DictionaryListYellowButtonMenu DictionaryListYellowButtonMessages '
  19063.     poolDictionaries: ''
  19064.     category: 'Interface-Inspector'!
  19065.  
  19066. !DictionaryListController methodsFor: 'menu messages'!
  19067. addEntry
  19068.     "Add a new Entry to the inspected object"
  19069.  
  19070.     | newKey |
  19071.     newKey _ FillInTheBlank request:
  19072. 'Enter new key, then type RETURN.
  19073. (Expression will be evaluated for value.)'.
  19074.     newKey _ Compiler evaluate: newKey.
  19075.     model addEntry: newKey!
  19076. removeSelection
  19077.     "Remove the current selection from the model"
  19078.  
  19079.     model selectionIndex = 0
  19080.         ifTrue: [^view flash].
  19081.     ^ model removeSelection!
  19082. selectionReferences
  19083.     "Create a browser on all references to the association of the current selection."
  19084.  
  19085.     model selectionIndex = 0
  19086.         ifTrue: [^view flash].
  19087.     self controlTerminate.
  19088.     Smalltalk browseAllCallsOn: model selectionAssociation.
  19089.     self startUp.! !
  19090.  
  19091. !DictionaryListController methodsFor: 'private'!
  19092. initializeYellowButtonMenu
  19093.  
  19094.     self 
  19095.         yellowButtonMenu: DictionaryListYellowButtonMenu
  19096.         yellowButtonMessages: DictionaryListYellowButtonMessages! !
  19097. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  19098.  
  19099. DictionaryListController class
  19100.     instanceVariableNames: ''!
  19101.  
  19102. !DictionaryListController class methodsFor: 'class initialization'!
  19103. initialize
  19104.  
  19105.     DictionaryListYellowButtonMenu _
  19106.         PopUpMenu labels:
  19107. 'inspect
  19108. references
  19109. add key
  19110. remove'
  19111.         lines: #( 2 ).
  19112.     DictionaryListYellowButtonMessages _
  19113.         #(inspectSelection selectionReferences addEntry removeSelection )
  19114.  
  19115.     "DictionaryListController initialize"! !
  19116.  
  19117. DictionaryListController initialize!
  19118. Object subclass: #DiskProxy
  19119.     instanceVariableNames: 'globalObjectName constructorSelector constructorArgs '
  19120.     classVariableNames: ''
  19121.     poolDictionaries: ''
  19122.     category: 'Object Storage'!
  19123.  
  19124. !DiskProxy methodsFor: 'as yet unclassified'!
  19125. comeFullyUpOnReload
  19126.     "Internalize myself into a fully alive object after raw loading
  19127.      from a DataStream. (See my class comment.)
  19128.      The sender (the DataStream facility) will substitute the answer
  19129.      for myself, even if that means doing ╘me become: myAnswer╒."
  19130.     | globalObj |
  19131.  
  19132.     globalObj _ Smalltalk at: globalObjectName
  19133.         ifAbsent: [^ self halt: 'can╒t internalize'].
  19134.     Symbol mustBeSymbol: constructorSelector.    
  19135.  
  19136.     ^ globalObj perform: constructorSelector
  19137.           withArguments: constructorArgs!
  19138. global: globalNameSymbol selector: selectorSymbol args: argArray
  19139.     "Initialize self as a DiskProxy constructor with the given
  19140.      globalNameSymbol, selectorSymbol, and argument Array.
  19141.      I will internalize by looking up the global object name in the
  19142.      SystemDictionary (Smalltalk) and sending it this message with
  19143.      these arguments."
  19144.  
  19145.     Symbol mustBeSymbol: (globalObjectName _ globalNameSymbol).
  19146.     Symbol mustBeSymbol: (constructorSelector _ selectorSymbol).
  19147.     constructorArgs _ argArray!
  19148. objectToStoreOnDataStream
  19149.     "A DiskProxy proxies for some object put on a DataStream. When
  19150.      loaded back, the DiskProxy internalizes (comeFullyUpOnReload)
  19151.      by turning into the original object (we hope).
  19152.      Trying to put a *DiskProxy* on a DataStream won╒t work since the
  19153.      loaded result will internalize itself into something else.
  19154.      Hence sending objectToStoreOnDataStream to a DataStream is
  19155.      a bug (or else a request to built a ╘quoter╒ that will turn
  19156.      itself back into this DiskProxy object╔)."
  19157.  
  19158.     self halt: 'redundant objectToStoreOnDataStream message'! !
  19159. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  19160.  
  19161. DiskProxy class
  19162.     instanceVariableNames: ''!
  19163.  
  19164. !DiskProxy class methodsFor: 'imported from V'!
  19165. classComment
  19166. "A DiskProxy is an externalized form of an object to write on a
  19167. DataStream. It contains a ╘constructor╒ message to regenerate
  19168. the object, in context, when sent a comeFullyUpOnReload message
  19169. (i.e. ╘internalize╒).
  19170.  
  19171. Constructing a new object is good for any object that (1) can╒t be
  19172. externalized simply by snapshotting and reloading its instance
  19173. variables (like a CompiledMethod or a Picture), or (2) wants to be
  19174. free to evolve its internal representation without making stored
  19175. instances obsolete (and dangerous). Snapshotting and reloading an
  19176. object╒s instance variables is a dangerous breach of encapsulation.
  19177.  
  19178. The idea is to define, for each kind of object that needs special
  19179. externalization, a class method that will internalize the object by
  19180. reconstructing it from its defining state. We call this a
  19181. ╘constructor╒ method. Then externalize such an object as a frozen
  19182. message that invokes this method--a DiskProxy.
  19183.  
  19184. The internal structure of the class is then free to evolve. All
  19185. externalized instances will be useful as long as the
  19186. constructor methods are maintained with the same semantics.
  19187.  
  19188. There may be several constructor methods for a particular class. This
  19189. is useful for (1) instances with characteristically different
  19190. defining state, and (2) newer, evolved forms of an object and its
  19191. constructors, with the old constructor methods kept around so old
  19192. data can still be properly loaded.
  19193.  
  19194. Create one like this example from class Picture
  19195.  
  19196.     DiskProxy global: #Picture
  19197.             selector: #fromByteArray:
  19198.                 args: (Array with: self storage asByteArray)
  19199.  
  19200. Ñ See also subclass DiskProxyQ that will construct an object in
  19201. the above manner and then send it a sequence of messages. This may save
  19202. creating a wide variety of constructor methods. It's also useful because
  19203. the newly read-in DiskProxyQ can catch messages like #objectContainedIn:
  19204. (via #doesNotUnderstand:) and add them to the queue of messages to
  19205. send to the new object.
  19206.  
  19207. Ñ We may also want a subclass of DiskProxy that evaluates a string
  19208. expression to compute the receiver of the constructor message.
  19209.  
  19210. My instance variables:
  19211. Ñ globalObjectName -- the Symbol name of a global object in the
  19212.     System dictionary (usually a class).
  19213. Ñ constructorSelector -- the constructor message selector Symbol to
  19214.     send to the global object (perform:withArguments:), typically a
  19215.     variation on ╘newFrom:╒.
  19216. Ñ constructorArgs -- the Array of arguments to pass in the
  19217.     constructor message.
  19218.  
  19219. -- 11/9/92 jhm
  19220. "!
  19221. global: globalNameSymbol selector: selectorSymbol args: argArray
  19222.     "Create a new DiskProxy constructor with the given
  19223.      globalNameSymbol, selectorSymbol, and argument Array.
  19224.      It will internalize itself by looking up the global object name
  19225.      in the SystemDictionary (Smalltalk) and sending it this message
  19226.      with these arguments."
  19227.  
  19228.     ^ self new global: globalNameSymbol
  19229.              selector: selectorSymbol
  19230.                  args: argArray! !DiskProxy subclass: #DiskProxyQ
  19231.     instanceVariableNames: 'messageQueue '
  19232.     classVariableNames: ''
  19233.     poolDictionaries: ''
  19234.     category: 'Object Storage'!
  19235.  
  19236. !DiskProxyQ methodsFor: 'as yet unclassified'!
  19237. comeFullyUpOnReload
  19238.     "Internalize myself into a fully alive object after raw loading
  19239.      from a DataStream/ReferenceStream.
  19240.      For DiskProxyQ: Invoke the constructor message and send my queue of messages to
  19241.      the result. (See my class comment.)
  19242.      The sender (the ReferenceStream facility) will substitute the answer
  19243.      for myself, even if that means asking me to ╘become: myAnswer╒. -- 11/9/92 jhm
  19244.      12/1/92 jhm: Remove the 1-element-array optimization."
  19245.     | answer |
  19246.  
  19247.     answer _ super comeFullyUpOnReload.
  19248.  
  19249.     messageQueue == nil ifFalse:
  19250.         [messageQueue do: [:msg | msg sendTo: answer]].
  19251.  
  19252.     ^ answer!
  19253. doesNotUnderstand: aMessage
  19254.     "Enqueue a message for the object that I will internalize to. Return self, which
  19255.      is the best I can do (sorry!!), noting that self will #become: the object I
  19256.      internalize to. See my class comment for more info and warnings. -- 11/9/92 jhm"
  19257.  
  19258.     self xxxQMessage: aMessage.
  19259.     ^ self!
  19260. global: globalNameSymbol selector: selectorSymbol args: argArray
  19261.     "Initialize self as a DiskProxyQ constructor with the given
  19262.      globalNameSymbol, selectorSymbol, and argument Array, and an
  19263.      empty message queue.
  19264.      I will internalize by looking up the global object name in the
  19265.      SystemDictionary (Smalltalk), sending it this message with
  19266.      these arguments, and then sending it all queued up messages.
  19267.      In the interim, I can enqueue messages. -- 11/9/92 jhm"
  19268.  
  19269.     messageQueue _ nil.
  19270.     ^ super global: globalNameSymbol selector: selectorSymbol args: argArray!
  19271. xxxQMessage: aMessage
  19272.     "Enqueue aMessage on the queue of messages that I will send the newly-created
  19273.      object at internalization time.
  19274.      IMPLEMENTATION: My instance variable messageQueue holds either nil or an Array
  19275.         of objects to sendTo: the object I'm internalizing to (generally of class
  19276.         Message or Symbol). -- 11/9/92 jhm
  19277.      12/1/92 jhm: Remove the 1-element-array optimization."
  19278.  
  19279.     messageQueue _ messageQueue == nil
  19280.         ifTrue:  [Array with: aMessage]
  19281.         ifFalse: [messageQueue,, aMessage]! !
  19282. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  19283.  
  19284. DiskProxyQ class
  19285.     instanceVariableNames: ''!
  19286.  
  19287. !DiskProxyQ class methodsFor: 'imported from V'!
  19288. classComment
  19289. "An extended version of DiskProxy (which see) whose internalize method will
  19290. construct an object like DiskProxy does and then send it a sequence of
  19291. messages from a message queue.
  19292.  
  19293. Messages may be enqueued before the DiskProxyQ is saved on the
  19294. ReferenceStream. Example: ╘(TopPane new) label: w; model: x; menu: y╒. This
  19295. saves creating a variety of highly specialized constructor methods.
  19296.  
  19297. Messages may also be enqueued by the DiskProxyQ between when its read from
  19298. disk and when it╒s internalized to the desired object. The newly
  19299. read-in DiskProxyQ can catch messages like #objectContainedIn: (via
  19300. doesNotUnderstand:) and add them to the queue of messages to send to the
  19301. new object at internalization time. This matters a great deal to a network
  19302. of objects being read in from a ReferenceStream, since some objects get
  19303. internalized before other objects that they know.
  19304.  
  19305. You create a DiskProxyQ just like a DiskProxy, and optionally send it
  19306. #xxxQMessage: messages.
  19307.  
  19308. WARNING: The use of doesNotUnderstand: won╒t work if you count on the not-understood
  19309. message╒s result!! DiskProxyQ>>doesNotUnderstand: cannot possibly return the
  19310. right result. It can╒t even return the ╘self╒ of the object being
  19311. internalized, since the whole point is that object hasn╒t been created yet.
  19312. As a best bet, DiskProxyQ>>doesNotUnderstand: returns itself, which will
  19313. eventually be asked to #become: the object it internalizes to.
  19314.  
  19315. WARNING: The use of doesNotUnderstand: won╒t work if ordinary DiskProxyQ
  19316. messages are mistaken for messages to enqueue for the proxied object, or
  19317. vice versa!! Adding methods to future implementations of DiskProxyQ may screw
  19318. up exisitng DiskProxyQ objects!! We might want to program specific DiskProxyQ
  19319. objects with message selectors to catch and enqueue when read in, but that
  19320. would be painful all around, and it╒s not clear how to do it.
  19321.     Because of this, we (a) minimize the number of messages that a DiskProxyQ
  19322. responds to, and (b) begin all DiskProxyQ message selector names with ╘xxx╒.
  19323. Still, DiskProxyQ inherits many methods from Object and a couple from APalObject!!
  19324.  
  19325. My instance variables:
  19326.   Ñ messageQueue -- either nil or an Array of objects to sendTo: the object I╒m
  19327.         internalizing to (they╒re generally of class Message or Symbol).
  19328.  
  19329. NOTE: The class method readDataFrom:size: anInteger deals with a subtle issue in
  19330. reading a network of objects. Recursively reading the a DiskProxyQ╒s parts will
  19331. internalize them (comeFullyUpOnReload), possibly sending messages to the nascent
  19332. DiskProxyQ. I.e. the incomplete object receives (and enqueues) messages!! When it
  19333. reads the DiskProxyQ╒s message queue, it must combine that with the accumulated
  19334. queue.
  19335.     Rather than hard-wire the index of the inst var ╘messageQueue╒, that method
  19336. ASSUMES that any non-nil inst var holds an Array to be concatenated with the filed
  19337. value.
  19338.  
  19339. -- 11/9/92 jhm, 12/1/92 jhm
  19340. "!
  19341. readDataFrom: aDataStream size: anInteger
  19342.     "Create an object based on the contents of aDataStream, which was
  19343.        generated by the object╒s storeDataOn: method. Answer it.
  19344.      NOTE: This implementation for DiskProxyQ deals with a subtle issue in reading a
  19345.         network of objects. Recursively reading the a DiskProxyQ╒s parts will
  19346.         internalize them (comeFullyUpOnReload), possibly sending messages to the
  19347.         nascent DiskProxyQ. I.e. the incomplete object receives (and enqueues)
  19348.         messages!! When we read the DiskProxyQ╒s message queue, we must combine
  19349.         it with the accumulated queue.
  19350.      ASSUMES: Rather than hard-wire the index of the inst var ╘messageQueue╒, we
  19351.         assume that any non-nil inst var has an Array to be concatenated with the
  19352.         filed value.
  19353.      NOTE: This method must match its corresponding storeDataOn:
  19354.        method. Also, it must send beginReference: after instantiating
  19355.        the new object but before reading any objects from aDataStream
  19356.        that might reference it. -- 12/1/92 jhm"
  19357.     | anObject cntInstVars cntIndexedVars nextValue var |
  19358.  
  19359.     cntInstVars _ self instSize.
  19360.     anObject _ self isVariable
  19361.         ifTrue:  [cntIndexedVars _ anInteger - cntInstVars.
  19362.                  self basicNew: cntIndexedVars]
  19363.         ifFalse: [cntIndexedVars _ 0.
  19364.                  self basicNew].
  19365.  
  19366.     aDataStream beginReference: anObject.
  19367.  
  19368.     "Read in the instance vars, but don╒t just overwrite vars that get contents
  19369.      before we get there due to recursive work in ╘aDataStream next╒."
  19370.     1 to: cntInstVars do: [:i |
  19371.         nextValue _ aDataStream next.
  19372.         (var _ anObject instVarAt: i) == nil
  19373.             ifTrue:     "the normal case"
  19374.                 [anObject instVarAt: i put: nextValue]
  19375.             ifFalse:    "Oops!! Recover: Concatenate nextValue and var Arrays."
  19376.                 [nextValue == nil
  19377.                     ifFalse: [anObject instVarAt: i put: (nextValue,, var)]]].
  19378.  
  19379.     "Read in the indexed vars."
  19380.     1 to: cntIndexedVars do:
  19381.         [:i | anObject basicAt: i put: aDataStream next].
  19382.  
  19383.     ^ anObject! !DisplayObject subclass: #DisplayMedium
  19384.     instanceVariableNames: ''
  19385.     classVariableNames: ''
  19386.     poolDictionaries: ''
  19387.     category: 'Graphics-Display Objects'!
  19388. DisplayMedium comment:
  19389. 'I am a display object which can both paint myself on a medium (displayOn: messages), and can act as a medium myself. My chief subclass is Form.'!
  19390.  
  19391. !DisplayMedium methodsFor: 'coloring'!
  19392. fill: aRectangle fillColor: aForm 
  19393.     "Replace a rectangular area of the receiver with the pattern described by 
  19394.     aForm according to the rule over."
  19395.  
  19396.     self fill: aRectangle rule: Form over fillColor: aForm!
  19397. fill: aRectangle rule: anInteger fillColor: aForm 
  19398.     "Replace a rectangular area of the receiver with the pattern described by 
  19399.     aForm according to the rule anInteger."
  19400.  
  19401.     self subclassResponsibility!
  19402. fillBlack
  19403.     "Set all bits in the receiver to black (ones)."
  19404.  
  19405.     self fill: self boundingBox fillColor: self black!
  19406. fillBlack: aRectangle 
  19407.     "Set all bits in the receiver's area defined by aRectangle to black (ones)."
  19408.  
  19409.     self fill: aRectangle rule: Form over fillColor: self black!
  19410. fillColor: aColor
  19411.     "Set all pixels in the receiver to the color.  Must be a correct color for this depth of medium.  TK 1 Jun 96"
  19412.  
  19413.     self fill: self boundingBox fillColor: aColor!
  19414. fillGray
  19415.     "Set all bits in the receiver to gray."
  19416.  
  19417.     self fill: self boundingBox fillColor: Color gray!
  19418. fillGray: aRectangle
  19419.     "Set all bits in the receiver's area defined by aRectangle to the gray mask."
  19420.  
  19421.     self fill: aRectangle rule: Form over fillColor: Color gray!
  19422. fillShape: aShapeForm fillColor: aColor
  19423.     "Fill a region corresponding to 1 bits in aShapeForm with aColor"
  19424.  
  19425.     ^ self fillShape: aShapeForm fillColor: aColor at: 0@0!
  19426. fillShape: aShapeForm fillColor: aColor at: location
  19427.     "Fill a region corresponding to 1 bits in aShapeForm with aColor"
  19428.  
  19429.     ((BitBlt destForm: self sourceForm: aShapeForm fillColor: aColor
  19430.         combinationRule: Form paint
  19431.         destOrigin: location + aShapeForm offset sourceOrigin: 0@0
  19432.         extent: self extent clipRect: self boundingBox)
  19433.         colorMap: (Bitmap with: 0 with: 16rFFFFFFFF))
  19434.         copyBits!
  19435. fillWhite
  19436.     "Set all bits in the form to white (zeros)."
  19437.  
  19438.     self fill: self boundingBox fillColor: self white!
  19439. fillWhite: aRectangle
  19440.     "Set all bits in the receiver's area defined by aRectangle to white (zeros)."
  19441.  
  19442.     self fill: aRectangle rule: Form over fillColor: self white!
  19443. fillWithColor: aColor
  19444.     "Fill the receiver's bounding box with the given color.  5/15/96 sw.  Subsequently fixed  by tk to be compatible with changed color definition.  7/31/96 sw: code tightened"
  19445.  
  19446.     self fill: self boundingBox fillColor:
  19447.         (aColor class == Symbol ifTrue: [Color perform: aColor] ifFalse: [aColor])!
  19448. reverse
  19449.     "Change all the bits in the receiver that are white to black, and the ones 
  19450.     that are black to white."
  19451.  
  19452.     self fill: self boundingBox rule: Form reverse fillColor: self highLight!
  19453. reverse: aRectangle
  19454.     "Change all the bits in the receiver's area that intersects with aRectangle 
  19455.     that are white to black, and the ones that are black to white."
  19456.  
  19457.     self fill: aRectangle rule: Form reverse fillColor: self highLight!
  19458. reverse: aRectangle fillColor: aMask    
  19459.     "Change all the bits in the receiver's area that intersects with aRectangle 
  19460.     according to the mask. Black does not necessarily turn to white, rather it 
  19461.     changes with respect to the rule and the bit in a corresponding mask 
  19462.     location. Bound to give a surprise."
  19463.  
  19464.     self fill: aRectangle rule: Form reverse fillColor: aMask! !
  19465.  
  19466. !DisplayMedium methodsFor: 'bordering'!
  19467. border: aRectangle width: borderWidth 
  19468.     "Paint a border whose rectangular area is defined by aRectangle. The 
  19469.     width of the border of each side is borderWidth. Uses Form black for 
  19470.     drawing the border."
  19471.  
  19472.     self border: aRectangle width: borderWidth fillColor: Color black!
  19473. border: aRectangle width: borderWidth fillColor: aHalfTone 
  19474.     "Paint a border whose rectangular area is defined by aRectangle. The 
  19475.     width of the border of each side is borderWidth. Uses aHalfTone for 
  19476.     drawing the border."
  19477.  
  19478.     self border: aRectangle
  19479.         widthRectangle: 
  19480.             (Rectangle
  19481.                 left: borderWidth
  19482.                 right: borderWidth
  19483.                 top: borderWidth
  19484.                 bottom: borderWidth)
  19485.         rule: Form over
  19486.         fillColor: aHalfTone!
  19487. border: aRectangle width: borderWidth rule: combinationRule fillColor: aHalfTone 
  19488.     "Paint a border whose rectangular area is defined by aRectangle. The 
  19489.     width of the border of each side is borderWidth. Uses aHalfTone for 
  19490.     drawing the border."
  19491.  
  19492.     self border: aRectangle
  19493.         widthRectangle: 
  19494.             (Rectangle
  19495.                 left: borderWidth
  19496.                 right: borderWidth
  19497.                 top: borderWidth
  19498.                 bottom: borderWidth)
  19499.         rule: combinationRule
  19500.         fillColor: aHalfTone!
  19501. border: aRectangle widthRectangle: insets rule: combinationRule fillColor: aHalfTone
  19502.     "Paint a border whose rectangular area is defined by aRectangle. The 
  19503.     width of each edge of the border is determined by the four coordinates 
  19504.     of insets. Uses aHalfTone and combinationRule for drawing the border."
  19505.  
  19506.     (aRectangle areasOutside: (aRectangle insetBy: insets)) do:
  19507.         [:edgeStrip | self fill: edgeStrip rule: combinationRule fillColor: aHalfTone]! !
  19508.  
  19509. !DisplayMedium methodsFor: 'displaying'!
  19510. copyBits: sourceRect from: sourceForm at: destOrigin clippingBox: clipRect rule: rule fillColor: aForm 
  19511.     "Make up a BitBlt table and copy the bits."
  19512.  
  19513.     self subclassResponsibility!
  19514. drawLine: sourceForm from: beginPoint to: endPoint clippingBox: clipRect rule: anInteger fillColor: aForm 
  19515.     "Draw line by copying the argument, sourceForm, starting at location 
  19516.     beginPoint and ending at endPoint, clipped by the rectangle, clipRect. 
  19517.     The rule and mask for copying are the arguments anInteger and aForm."
  19518.  
  19519.     self subclassResponsibility! !Object subclass: #DisplayObject
  19520.     instanceVariableNames: ''
  19521.     classVariableNames: ''
  19522.     poolDictionaries: ''
  19523.     category: 'Graphics-Display Objects'!
  19524. DisplayObject comment: 'The abstract protocol for most display primitives that are used by Views for presenting information on the screen.'!
  19525.  
  19526. !DisplayObject methodsFor: 'accessing'!
  19527. extent
  19528.     "Answer the point that represents the width and height of the receiver's 
  19529.     bounding box."
  19530.  
  19531.     ^self boundingBox extent!
  19532. height
  19533.     "Answer the number that represents the height of the receiver's 
  19534.     bounding box."
  19535.  
  19536.     ^self boundingBox height!
  19537. offset
  19538.     "Answer the amount by which the receiver should be offset when it is 
  19539.     displayed or its position is tested."
  19540.  
  19541.     self subclassResponsibility!
  19542. offset: aPoint 
  19543.     "Set the amount by which the receiver's position is offset."
  19544.  
  19545.     ^self!
  19546. relativeRectangle
  19547.     "Answer a Rectangle whose top left corner is the receiver's offset position 
  19548.     and whose width and height are the same as the receiver."
  19549.  
  19550.     ^Rectangle origin: self offset extent: self extent!
  19551. width
  19552.     "Answer the number that represents the width of the receiver's bounding 
  19553.     box."
  19554.  
  19555.     ^self boundingBox width! !
  19556.  
  19557. !DisplayObject methodsFor: 'truncation and round off'!
  19558. rounded
  19559.     "Convert the offset of the receiver to integer coordinates."
  19560.  
  19561.     self offset: self offset rounded! !
  19562.  
  19563. !DisplayObject methodsFor: 'transforming'!
  19564. align: alignmentPoint with: relativePoint 
  19565.     "Translate the receiver's offset such that alignmentPoint aligns with 
  19566.     relativePoint."
  19567.  
  19568.     self offset: (self offset translateBy: relativePoint - alignmentPoint)!
  19569. scaleBy: aPoint 
  19570.     "Scale the receiver's offset by aPoint."
  19571.  
  19572.     self offset: (self offset scaleBy: aPoint)!
  19573. translateBy: aPoint 
  19574.     "Translate the receiver's offset."
  19575.  
  19576.     self offset: (self offset translateBy: aPoint)! !
  19577.  
  19578. !DisplayObject methodsFor: 'display box access'!
  19579. boundingBox
  19580.     "Answer the rectangular area that represents the boundaries of the 
  19581.     receiver's space of information."
  19582.  
  19583.     ^self computeBoundingBox!
  19584. center
  19585.  
  19586.     ^ self boundingBox center!
  19587. computeBoundingBox
  19588.     "Answer the rectangular area that represents the boundaries of the 
  19589.     receiver's area for displaying information. This is the primitive for 
  19590.     computing the area if it is not already known."
  19591.  
  19592.     self subclassResponsibility! !
  19593.  
  19594. !DisplayObject methodsFor: 'displaying-generic'!
  19595. displayAt: aDisplayPoint 
  19596.     "Display the receiver located at aDisplayPoint with default settings for 
  19597.     the displayMedium, rule and halftone."
  19598.  
  19599.     self displayOn: Display
  19600.         at: aDisplayPoint
  19601.         clippingBox: Display boundingBox
  19602.         rule: Form over
  19603.         fillColor: nil!
  19604. displayOn: aDisplayMedium
  19605.     "Simple default display in order to see the receiver in the upper left 
  19606.     corner of screen."
  19607.  
  19608.     self displayOn: aDisplayMedium at: 0 @ 0!
  19609. displayOn: aDisplayMedium at: aDisplayPoint 
  19610.     "Display the receiver located at aDisplayPoint with default settings for 
  19611.     rule and halftone."
  19612.  
  19613.     self displayOn: aDisplayMedium
  19614.         at: aDisplayPoint
  19615.         clippingBox: aDisplayMedium boundingBox
  19616.         rule: Form over
  19617.         fillColor: nil!
  19618. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle 
  19619.     "Display the receiver located at aDisplayPoint with default settings for 
  19620.     rule and halftone. Information to be displayed must be confined to the 
  19621.     area that intersects with clipRectangle."
  19622.  
  19623.     self displayOn: aDisplayMedium
  19624.         at: aDisplayPoint
  19625.         clippingBox: clipRectangle
  19626.         rule: Form over
  19627.         fillColor: nil!
  19628. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
  19629.     "This is the basic display primitive for graphic display objects. Display 
  19630.     the receiver located at aDisplayPoint with rule, ruleInteger, and mask, 
  19631.     aForm. Information to be displayed must be confined to the area that 
  19632.     intersects with clipRectangle."
  19633.  
  19634.     self subclassResponsibility!
  19635. displayOn: aDisplayMedium at: aDisplayPoint rule: ruleInteger
  19636.     "Display the receiver located at aPoint with default setting for the 
  19637.     halftone and clippingBox."
  19638.  
  19639.     self displayOn: aDisplayMedium
  19640.         at: aDisplayPoint
  19641.         clippingBox: aDisplayMedium boundingBox
  19642.         rule: ruleInteger
  19643.         fillColor: nil!
  19644. displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle 
  19645.     "Display primitive for the receiver where a DisplayTransformation is 
  19646.     provided as an argument. Alignment is defaulted to the receiver's 
  19647.     rectangle. Information to be displayed must be confined to the area that 
  19648.     intersects with clipRectangle."
  19649.  
  19650.     self displayOn: aDisplayMedium
  19651.         transformation: displayTransformation
  19652.         clippingBox: clipRectangle
  19653.         align: self relativeRectangle center
  19654.         with: self relativeRectangle center
  19655.         rule: Form over
  19656.         fillColor: nil!
  19657. displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint 
  19658.     "Display primitive where a DisplayTransformation is provided as an 
  19659.     argument, rule is over and mask is Form black. Information to be 
  19660.     displayed must be confined to the area that intersects with clipRectangle."
  19661.  
  19662.     self displayOn: aDisplayMedium
  19663.         transformation: displayTransformation
  19664.         clippingBox: clipRectangle
  19665.         align: alignmentPoint
  19666.         with: relativePoint
  19667.         rule: Form over
  19668.         fillColor: nil!
  19669. displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aForm 
  19670.     "Display the receiver where a DisplayTransformation is provided as an 
  19671.     argument, rule is ruleInteger and mask is aForm. Translate by 
  19672.     relativePoint-alignmentPoint. Information to be displayed must be 
  19673.     confined to the area that intersects with clipRectangle."
  19674.  
  19675.     | absolutePoint |
  19676.     absolutePoint _ displayTransformation applyTo: relativePoint.
  19677.     self displayOn: aDisplayMedium
  19678.         at: (absolutePoint - alignmentPoint) 
  19679.         clippingBox: clipRectangle 
  19680.         rule: ruleInteger 
  19681.         fillColor: aForm !
  19682. displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle fixedPoint: aPoint 
  19683.     "Display the receiver where a DisplayTransformation is provided as an 
  19684.     argument, rule is over and mask is Form black. No translation. 
  19685.     Information to be displayed must be confined to the area that intersects 
  19686.     with clipRectangle."
  19687.  
  19688.     self displayOn: aDisplayMedium
  19689.         transformation: displayTransformation
  19690.         clippingBox: clipRectangle
  19691.         align: aPoint
  19692.         with: aPoint
  19693.         rule: Form over
  19694.         fillColor: nil!
  19695. displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle rule: ruleInteger fillColor: aForm 
  19696.     "Display the receiver where a DisplayTransformation is provided as an 
  19697.     argument, rule is ruleInteger and mask is aForm. No translation. 
  19698.     Information to be displayed must be confined to the area that intersects 
  19699.     with clipRectangle."
  19700.  
  19701.     self displayOn: aDisplayMedium
  19702.         transformation: displayTransformation
  19703.         clippingBox: clipRectangle
  19704.         align: self relativeRectangle origin
  19705.         with: self relativeRectangle origin
  19706.         rule: ruleInteger
  19707.         fillColor: aForm!
  19708. displayOnPort: aPort 
  19709.     self displayOnPort: aPort at: 0@0!
  19710. followCursor
  19711.     "Just show the Form following the mouse. 6/21/96 tk"
  19712.     Cursor blank showWhile:
  19713.         [self follow: [Sensor cursorPoint] while: [Sensor noButtonPressed]]
  19714. ! !
  19715.  
  19716. !DisplayObject methodsFor: 'displaying-Display'!
  19717. display 
  19718.     "Display the receiver on the Display at location 0,0."
  19719.  
  19720.     self displayOn: Display!
  19721. follow: locationBlock while: durationBlock
  19722.    "Move an image around on the Display. Restore the background
  19723.    continuously without causing flashing. The argument, locationBlock,
  19724.    supplies each new location, and the argument, durationBlock, supplies
  19725.    true to continue, and then false to stop.
  19726.    8/20/96 sw: call follow:while:bitsBehind: to do the real work.  Note that th
  19727. method
  19728.    now returns the final bits behind as method value."
  19729.  
  19730.    | bitsBehind loc |
  19731.    bitsBehind _ Form fromDisplay: ((loc _ locationBlock value) extent: self extent).
  19732.    ^ self follow: locationBlock while: durationBlock bitsBehind: bitsBehind startingLoc: loc!
  19733. follow: locationBlock while: durationBlock
  19734.     bitsBehind: initialBitsBehind startingLoc: loc
  19735.    "Move an image around on the Display. Restore the background
  19736.    continuously without causing flashing. The argument, locationBlock,
  19737.    supplies each new location, and the argument, durationBlock, supplies
  19738.    true to continue, and then false to stop.
  19739.    8/20/96 sw: this variant takes the bitsBehind as an input argument, and
  19740. returns the
  19741.    final saved saved bits as method value."
  19742.    | location newLoc save1 save1Blt buffer bufferBlt rect1 rect2 bothRects |
  19743.    location _ loc.
  19744.    rect1 _ location extent: self extent.
  19745.    save1 _ initialBitsBehind.
  19746.    save1Blt _ BitBlt toForm: save1.
  19747.    buffer _ Form extent: self extent*2 depth: Display depth.  "Holds overlappin
  19748. region"
  19749.    bufferBlt _ BitBlt toForm: buffer.
  19750.    self displayOn: Display at: location.
  19751.    [durationBlock value] whileTrue:
  19752.    [newLoc _ locationBlock value.
  19753.    newLoc ~= location ifTrue:
  19754.    [rect2 _ newLoc extent: self extent.
  19755.    bothRects _ rect1 merge: rect2.
  19756.    (rect1 intersects: rect2)
  19757.    ifTrue:  "When overlap, buffer background for both rectangles"
  19758.    [bufferBlt copyFrom: bothRects in: Display to: 0@0.
  19759.    bufferBlt copyFrom: save1 boundingBox in: save1
  19760.    to: rect1 origin - bothRects origin.
  19761.    "now buffer is clean background; get new bits for save1"
  19762.    save1Blt copy: (0@0 extent: self extent)
  19763.    from: rect2 origin - bothRects origin in: buffer.
  19764.    self displayOnPort: bufferBlt at: rect2 origin - bothRects origin.
  19765.    Display copy: bothRects from: 0@0 in: buffer rule: Form over.]
  19766.    ifFalse: "If no overlap, do the simple thing (bothrects might be too big)"
  19767.    [Display copy: (location extent: save1 extent)
  19768.    from: 0@0 in: save1 rule: Form over.
  19769.    save1Blt copyFrom: rect2 in: Display to: 0@0.
  19770.    self displayOn: Display at: newLoc ].
  19771.    location _ newLoc.
  19772.    rect1 _ rect2]].
  19773.    ^ save1 displayOn: Display at: location!
  19774. slideFrom: startPoint to: stopPoint nSteps: nSteps 
  19775.     "does not display at the first point, but does at the last"
  19776.     | i p delta |
  19777.     i_0.  p_ startPoint.
  19778.     delta _ (stopPoint-startPoint) // nSteps.
  19779.     ^ self follow: [p_ p+delta]
  19780.         while: [(i_i+1) < nSteps]! !
  19781.  
  19782. !DisplayObject methodsFor: 'fileIn/Out'!
  19783. writeOnFileNamed: fileName 
  19784.     "Saves the receiver on the file fileName in the format:
  19785.         fileCode, depth, extent, offset, bits."
  19786.     | file |
  19787.     file _ FileStream newFileNamed: fileName.
  19788.     file binary.
  19789.     file nextPut: 2.  "file code = 2"
  19790.     self writeOn: file.
  19791.     file close
  19792. "
  19793.  | f |
  19794. [(f _ Form fromUser) boundingBox area>25] whileTrue:
  19795.     [f writeOnFileNamed: 'test.form'.
  19796.     (Form newFromFileNamed: 'test.form') display].
  19797. "! !
  19798.  
  19799. !DisplayObject methodsFor: 'color'!
  19800. black
  19801.     "Caller should really ask Color for a color.  6/25/96 tk"
  19802.  
  19803.     ^ Color black!
  19804. white
  19805.     "Caller should really ask Color for a color.  6/25/96 tk"
  19806.  
  19807.     ^ Color white! !
  19808. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  19809.  
  19810. DisplayObject class
  19811.     instanceVariableNames: ''!
  19812.  
  19813. !DisplayObject class methodsFor: 'fileIn/Out'!
  19814. collectionFromFileNamed: fileName 
  19815.     "Answer a collection of Forms read from the external file 
  19816.     named fileName. The file format is: fileCode, {depth, extent, offset, bits}."
  19817.     | file fileCode coll |
  19818.     file _ FileStream oldFileNamed: fileName.
  19819.     file binary; readOnly.
  19820.     fileCode _ file next.
  19821.     fileCode = 1 ifTrue: [^ Array with: (self new readFromOldFile: file)].
  19822.     fileCode = 2 ifFalse: [self halt].
  19823.     coll _ OrderedCollection new.
  19824.     [file atEnd] whileFalse: [coll add: (self new readFrom: file)].
  19825.     file close.
  19826.     ^ coll!
  19827. newFromFileNamed: fileName 
  19828.     "Answer a Form with bitmap initialized from the external file 
  19829.     named fileName. The file format is: fileCode, depth, extent, offset, bits."
  19830.     | newForm file fileCode |
  19831.     file _ FileStream oldFileNamed: fileName.
  19832.     file binary; readOnly.
  19833.     fileCode _ file next.
  19834.     fileCode = 1 ifTrue: [^ self new readFromOldFile: file].
  19835.     fileCode = 2 ifFalse: [self halt].
  19836.     newForm _ self new readFrom: file.
  19837.     file close.
  19838.     ^ newForm!
  19839. writeCollection: coll onFileNamed: fileName 
  19840.     "Saves a collection of Forms on the file fileName in the format:
  19841.         fileCode, {depth, extent, offset, bits}."
  19842.     | file |
  19843.     file _ FileStream newFileNamed: fileName.
  19844.     file binary.
  19845.     file nextPut: 2.  "file code = 2"
  19846.     coll do: [:f | f writeOn: file].
  19847.     file close
  19848. "
  19849.  | f c | c _ OrderedCollection new.
  19850. [(f _ Form fromUser) boundingBox area>25] whileTrue: [c add: f].
  19851. Form writeCollection: c onFileNamed: 'test.forms'.
  19852. c _ Form collectionFromFileNamed: 'test.forms'.
  19853. 1 to: c size do: [:i | (c at: i) displayAt: 0@(i*100)].
  19854. "! !
  19855.  
  19856. !DisplayObject class methodsFor: 'color'!
  19857. black
  19858.     "Caller should really ask Color for a color.  6/25/96 tk"
  19859.  
  19860.     ^ Color black!
  19861. white
  19862.     "Caller should really ask Color for a color.  6/25/96 tk"
  19863.  
  19864.     ^ Color white! !CharacterScanner subclass: #DisplayScanner
  19865.     instanceVariableNames: 'lineY runX '
  19866.     classVariableNames: ''
  19867.     poolDictionaries: 'TextConstants '
  19868.     category: 'Graphics-Support'!
  19869. DisplayScanner comment:
  19870. 'My instances are used to scan text and display it on the screen or in a hidden form.'!
  19871.  
  19872. !DisplayScanner methodsFor: 'scanning'!
  19873. displayLines: linesInterval in: aParagraph clippedBy: visibleRectangle 
  19874.     "The central display routine. The call on the primitive 
  19875.     (scanCharactersFrom:to:in:rightX:) will be interrupted according to an 
  19876.     array of stop conditions passed to the scanner at which time the code to 
  19877.     handle the stop condition is run and the call on the primitive continued 
  19878.     until a stop condition returns true (which means the line has 
  19879.     terminated)."
  19880.  
  19881.     | runLength done lineGrid lineIndex stopCondition leftInRun fore back |
  19882.     "leftInRun is the # of characters left to scan in the current run; when 0,
  19883.         it is time to call 'self setStopConditions'"
  19884.     leftInRun _ 0.
  19885.     super initializeFromParagraph: aParagraph clippedBy: visibleRectangle.
  19886.     destForm depth > 1 ifTrue:
  19887.         [fore _ aParagraph foregroundColor bitPatternForDepth: destForm depth.
  19888.         back _ aParagraph backgroundColor bitPatternForDepth: destForm depth.
  19889.         self colorMap: (Bitmap with: back first with: fore first)].
  19890.     rightMargin _ aParagraph rightMarginForDisplay.
  19891.     lineGrid _ textStyle lineGrid.
  19892.     lineY _ destY _ aParagraph topAtLineIndex: linesInterval first.
  19893.     linesInterval do: 
  19894.         [:lineIndex | 
  19895.         runX _ destX _ leftMargin _ 
  19896.             aParagraph leftMarginForDisplayForLine: lineIndex.
  19897.         line _ aParagraph lines at: lineIndex.
  19898.         lastIndex _ line first.
  19899.         leftInRun<= 0 
  19900.             ifTrue:
  19901.                 [self setStopConditions.
  19902.                 "also sets the font"
  19903.                 leftInRun _ text runLengthFor: line first].
  19904.         runLength _ leftInRun.
  19905.         destY _ lineY + (textStyle baseline - font ascent).
  19906.         "fontAscent delta"
  19907.         (runStopIndex _ lastIndex + (runLength - 1)) > line last 
  19908.             ifTrue: [runStopIndex _ line last].
  19909.         leftInRun _ leftInRun - (runStopIndex - lastIndex + 1).
  19910.         spaceCount _ 0.
  19911.         done _ false.
  19912.         [done]
  19913.             whileFalse: 
  19914.                 [stopCondition _ 
  19915.                     self scanCharactersFrom: lastIndex
  19916.                         to: runStopIndex
  19917.                         in: text string
  19918.                         rightX: rightMargin
  19919.                         stopConditions: stopConditions
  19920.                         displaying: true.
  19921.                 "see setStopConditions for stopping conditions for displaying."
  19922.                 done _ self perform: stopCondition].
  19923.         lineY _ lineY + lineGrid]! !
  19924.  
  19925. !DisplayScanner methodsFor: 'stop conditions'!
  19926. cr
  19927.     "When a carriage return is encountered, simply increment the pointer 
  19928.     into the paragraph."
  19929.  
  19930.     lastIndex_ lastIndex + 1.
  19931.     ^false!
  19932. crossedX
  19933.     "This condition will sometimes be reached 'legally' during display, when, 
  19934.     for instance the space that caused the line to wrap actually extends over 
  19935.     the right boundary. This character is allowed to display, even though it 
  19936.     is technically outside or straddling the clipping ectangle since it is in 
  19937.     the normal case not visible and is in any case appropriately clipped by 
  19938.     the scanner."
  19939.  
  19940.     self checkEmphasis.
  19941.     ^ true !
  19942. endOfRun
  19943.     "The end of a run in the display case either means that there is actually 
  19944.     a change in the style (run code) to be associated with the string or the 
  19945.     end of this line has been reached. A check for any emphasis 
  19946.     (underlining, for example) that may run the length of the run is done 
  19947.     here before returning to displayLines: to do the next line."
  19948.  
  19949.     | runLength |
  19950.     self checkEmphasis.
  19951.     lastIndex = line last ifTrue: [^true].
  19952.     runX _ destX.
  19953.     runLength _ text runLengthFor: (lastIndex _ lastIndex + 1).
  19954.     (runStopIndex _ lastIndex + (runLength - 1)) > line last 
  19955.         ifTrue: [runStopIndex _ line last].
  19956.     self setStopConditions.
  19957.     destY _ lineY + textStyle baseline - font ascent.
  19958.     "ascent delta"
  19959.     ^false!
  19960. paddedSpace
  19961.     "Each space is a stop condition when the alignment is right justified. 
  19962.     Padding must be added to the base width of the space according to 
  19963.     which space in the line this space is and according to the amount of 
  19964.     space that remained at the end of the line when it was composed."
  19965.  
  19966.     spaceCount _ spaceCount + 1.
  19967.     lastIndex _ lastIndex + 1.
  19968.     destX _ destX + spaceWidth + (line justifiedPadFor: spaceCount).
  19969.     ^false!
  19970. setStopConditions
  19971.     "Set the font and the stop conditions for the current run."
  19972.     
  19973.     self setFont.
  19974.     stopConditions 
  19975.         at: Space asciiValue + 1 
  19976.         put: (textStyle alignment = Justified ifTrue: [#paddedSpace])!
  19977. tab
  19978.     destX _ (textStyle alignment == Justified and: [self leadingTab not])
  19979.         ifTrue:        "imbedded tabs in justified text are weird"
  19980.             [destX + (textStyle tabWidth - (line justifiedTabDeltaFor: spaceCount)) max: destX]
  19981.         ifFalse: 
  19982.             [textStyle
  19983.                 nextTabXFrom: destX
  19984.                 leftMargin: leftMargin
  19985.                 rightMargin: rightMargin].
  19986.     lastIndex _ lastIndex + 1.
  19987.     ^ false! !
  19988.  
  19989. !DisplayScanner methodsFor: 'private'!
  19990. checkEmphasis
  19991.     "convert mask to color 6/18/96 tk"
  19992.     | emphasis sourceRect y |
  19993.     (emphasis _ font emphasis) = 0 ifTrue: [^self].
  19994.     emphasis >= 8 ifTrue:  "struck out"
  19995.         [destForm
  19996.             fill: ((runX @ (lineY + textStyle baseline-3)) extent: (destX - runX) @ 1)
  19997.             rule: combinationRule fillColor: halftoneForm.    "color already converted to a Bitmap"
  19998.         emphasis _ emphasis - 8].
  19999.     emphasis >= 4 ifTrue:  "underlined"
  20000.         [destForm
  20001.             fill: ((runX @ (lineY + textStyle baseline)) extent: (destX - runX) @ 1)
  20002.             rule: combinationRule fillColor: halftoneForm.
  20003.         emphasis _ emphasis - 4].
  20004.     emphasis >= 2 ifTrue:  "itallic"
  20005.         [y _ lineY + textStyle lineGrid - 4.
  20006.         [y > lineY] whileTrue:
  20007.             [sourceRect _ runX @ lineY extent: (destX - runX - 1) @ (y - lineY).
  20008.             destForm
  20009.                 copyBits: sourceRect from: destForm at: (runX+1) @ lineY
  20010.                 clippingBox: sourceRect rule: Form over fillColor: nil.
  20011.             y _ y - 4].
  20012.         emphasis _ emphasis - 2].
  20013.     emphasis >= 1 ifTrue:  "bold face"
  20014.         [sourceRect _ runX @ lineY extent: (destX - runX - 1) @ textStyle lineGrid.
  20015.         destForm
  20016.             copyBits: sourceRect from: destForm at: (runX+1) @ lineY
  20017.             clippingBox: sourceRect rule: Form under fillColor: nil]!
  20018. doesDisplaying
  20019.     ^true! !Form subclass: #DisplayScreen
  20020.     instanceVariableNames: 'clippingBox '
  20021.     classVariableNames: 'ScreenSave '
  20022.     poolDictionaries: ''
  20023.     category: 'Graphics-Display Objects'!
  20024. DisplayScreen comment:
  20025. 'There is only one instance of me, Display. It is a global and is used to handle general user requests to deal with the whole display screen. 
  20026.     Although I offer no protocol, my name provides a way to distinguish this special instance from all other Forms. This is useful, for example, in dealing with saving and restoring the system.
  20027.     To change the depth of your Display...
  20028.         Display newDepth: 16.
  20029.         Display newDepth: 8.
  20030.         Display newDepth: 1.
  20031. Valid display depths are 1, 2, 4, 8, 16 and 32.  It is suggested that you run with your monitors setting the same, for better speed and color fidelity.  Note that this can add up to 4Mb for the Display form.  Finally, note that newDepth: ends by executing a ''ControlManager restore'' which currently terminates the active process, so nothing that follows in the doit will get executed.
  20032.  
  20033. Depths 1, 2, 4 and 8 bits go through a color map to put color on the screen, but 16 and 32-bit color use the pixel values directly for RGB color (5 and 8 bits per, respectivlely).  The color choice an be observed by executing Color fromUser in whatever depth you are using.
  20034. '!
  20035.  
  20036. !DisplayScreen methodsFor: 'displaying'!
  20037. boundingBox
  20038.     clippingBox == nil
  20039.         ifTrue: [clippingBox _ super boundingBox].
  20040.     ^ clippingBox!
  20041. clippingTo: aRect do: aBlock
  20042.     "Display clippingTo: Rectangle fromUser do:
  20043.     [ScheduledControllers restore: Display fullBoundingBox]"
  20044.     | saveClip |
  20045.     saveClip _ clippingBox.
  20046.     clippingBox _ aRect.
  20047.     aBlock value.
  20048.     clippingBox _ saveClip!
  20049. copyBits: rect from: sf at: destOrigin clippingBox: clipRect rule: cr fillColor: hf 
  20050.     (BitBlt
  20051.         destForm: self
  20052.         sourceForm: sf
  20053.         fillColor: hf
  20054.         combinationRule: cr
  20055.         destOrigin: destOrigin
  20056.         sourceOrigin: rect origin
  20057.         extent: rect extent
  20058.         clipRect: (clipRect intersect: clippingBox)) copyBits!
  20059. flash: aRectangle 
  20060.     "Complement twice the area of the screen defined by the argument, 
  20061.     aRectangle."
  20062.  
  20063.     2 timesRepeat:
  20064.         [self reverse: aRectangle.
  20065.         "(Delay forMilliseconds: 30) wait"]!
  20066. fullBoundingBox
  20067.     ^ super boundingBox!
  20068. fullScreen   "Display fullScreen"
  20069.  
  20070.     ScreenSave notNil ifTrue: [Display _ ScreenSave].
  20071.     clippingBox _ super boundingBox!
  20072. height
  20073.     ^ self boundingBox height!
  20074. replacedBy: aForm do: aBlock
  20075.     "Permits normal display to draw on aForm instead of the display."
  20076.  
  20077.     ScreenSave _ self.
  20078.     Display _ aForm.
  20079.     aBlock value.
  20080.     Display _ self.
  20081.     ScreenSave _ nil.!
  20082. restoreAfter: aBlock
  20083.     "Evaluate the block, wait for a mouse click, and then restore the screen"
  20084.     aBlock value.
  20085.     Sensor waitButton.
  20086.     ScheduledControllers  restore.
  20087.     ScheduledControllers activeController view emphasize!
  20088. usableArea
  20089.     "Answer the usable area of the receiver.  5/22/96 sw."
  20090.  
  20091.     ^ self boundingBox deepCopy!
  20092. width
  20093.     ^ self boundingBox width! !
  20094.  
  20095. !DisplayScreen methodsFor: 'private'!
  20096. beDisplay
  20097.     "Primitive. Tell the interpreter to use the receiver as the current display 
  20098.     image. Fail if the form is too wide to fit on the physical display. 
  20099.     Essential. See Object documentation whatIsAPrimitive."
  20100.  
  20101.     <primitive: 102>
  20102.     self primitiveFailed!
  20103. newDepth: pixelSize
  20104. "
  20105.     Display newDepth: 8.
  20106.     Display newDepth: 1.
  20107. "
  20108.     self newDepthNoRestore: pixelSize.
  20109.     ControlManager shutDown; startUp.!
  20110. newDepthNoRestore: pixelSize
  20111.     depth = pixelSize ifTrue: [^ self  "no change"].
  20112.     self depth: pixelSize.  self setExtent: self extent.
  20113.     ScheduledControllers updateGray.
  20114.     DisplayScreen startUp!
  20115. setExtent: aPoint  "DisplayScreen startUp"
  20116.     width _ aPoint x.
  20117.     height _ aPoint y.
  20118.     clippingBox _ nil.
  20119.     self bitsSize.  "Cause any errors before unrecoverable"
  20120.     bits _ nil.  "Free up old bitmap in case space is low"
  20121.     bits _ Bitmap new: self bitsSize.
  20122.     self boundingBox! !
  20123.  
  20124. !DisplayScreen methodsFor: 'disk I/O'!
  20125. objectToStoreOnDataStream
  20126.     "HyperSqueak is about to write me out.  See if I am a system object.  Write out just a name if so.  See SqueakSupport class.aComment.  8/13/96 tk"
  20127.  
  20128.     "Path or real thing, depending"
  20129.     ^ Smalltalk hyperSqueakSupportClass sysRef: self! !
  20130. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  20131.  
  20132. DisplayScreen class
  20133.     instanceVariableNames: ''!
  20134.  
  20135. !DisplayScreen class methodsFor: 'display box access'!
  20136. boundingBox
  20137.     "Answer the bounding box for the form representing the current display 
  20138.     screen."
  20139.  
  20140.     ^Display boundingBox! !
  20141.  
  20142. !DisplayScreen class methodsFor: 'snapshots'!
  20143. actualScreenSize
  20144.     <primitive: 106>
  20145.     ^ 640@480!
  20146. shutDown 
  20147.     "Minimize Display memory saved in image"
  20148.     Display setExtent: 240@120!
  20149. startUp  "DisplayScreen startUp"
  20150.     Display setExtent: self actualScreenSize.
  20151.     Display beDisplay! !DisplayObject subclass: #DisplayText
  20152.     instanceVariableNames: 'text textStyle offset form foreColor backColor '
  20153.     classVariableNames: ''
  20154.     poolDictionaries: 'TextConstants '
  20155.     category: 'Graphics-Display Objects'!
  20156. DisplayText comment:
  20157. 'I represent Text whose emphasis changes are mapped to a set of fonts. My instances have an offset used in determining screen placement for displaying. They get used two different ways in the system. In the user interface, they mainly hold onto some text which is viewed by some form of ParagraphEditor. However, as a DisplayObject, they may need to display efficiently, so my instances have a cache for the bits.'!
  20158.  
  20159. !DisplayText methodsFor: 'accessing'!
  20160. alignedTo: alignPointSelector
  20161.     "Return a copy with offset according to alignPointSelector which is one of...
  20162.     #(topLeft, topCenter, topRight, leftCenter, center, etc)"
  20163.     | boundingBox |
  20164.     boundingBox _ 0@0 corner: self form extent.
  20165.     ^ self shallowCopy offset: (0@0) - (boundingBox perform: alignPointSelector)!
  20166. fontsUsed
  20167.     "Return a list of all fonts used currently in this text.  8/19/96 tk"
  20168.  
  20169.     ^ text runs values asSet collect: [:each | textStyle fontAt: each]!
  20170. form 
  20171.     "Answer the form into which the receiver's display bits are cached."
  20172.  
  20173.     form == nil ifTrue: [self composeForm].
  20174.     ^form!
  20175. lineGrid
  20176.     "Answer the relative space between lines of the receiver's text."
  20177.  
  20178.     ^textStyle lineGrid!
  20179. numberOfLines 
  20180.     "Answer the number of lines of text in the receiver."
  20181.  
  20182.     ^self height // text lineGrid!
  20183. offset 
  20184.     "Refer to the comment in DisplayObject|offset."
  20185.  
  20186.     ^offset!
  20187. offset: aPoint 
  20188.     "Refer to the comment in DisplayObject|offset:."
  20189.  
  20190.     offset _ aPoint!
  20191. string
  20192.     "Answer the string of the characters displayed by the receiver."
  20193.  
  20194.     ^text string!
  20195. text 
  20196.     "Answer the text displayed by the receiver."
  20197.  
  20198.     ^text!
  20199. text: aText 
  20200.     "Set the receiver to display the argument, aText."
  20201.     
  20202.     text _ aText.
  20203.     form _ nil.
  20204.     self changed.
  20205.     !
  20206. textStyle 
  20207.     "Answer the style by which the receiver displays its text."
  20208.  
  20209.     ^textStyle!
  20210. textStyle: aTextStyle 
  20211.     "Set the style by which the receiver should display its text."
  20212.  
  20213.     textStyle _ aTextStyle.
  20214.     form _ nil.
  20215.     self changed.
  20216.     ! !
  20217.  
  20218. !DisplayText methodsFor: 'displaying'!
  20219. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm 
  20220.     "Refer to the comment in 
  20221.     DisplayObject|displayOn:at:clippingBox:rule:mask:."
  20222.  
  20223.     self form
  20224.         displayOn: aDisplayMedium
  20225.         at: aDisplayPoint + offset
  20226.         clippingBox: clipRectangle
  20227.         rule: ruleInteger
  20228.         fillColor: aForm!
  20229. displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aForm 
  20230.     "Refer to the comment in 
  20231.     DisplayObject|displayOn:transformation:clippingBox:align:with:rule:mask:."
  20232.  
  20233.     | absolutePoint |
  20234.     absolutePoint _ displayTransformation applyTo: relativePoint.
  20235.     absolutePoint _ absolutePoint x asInteger @ absolutePoint y asInteger.
  20236.     self displayOn: aDisplayMedium
  20237.         at: absolutePoint - alignmentPoint
  20238.         clippingBox: clipRectangle
  20239.         rule: ruleInteger
  20240.         fillColor: aForm!
  20241. displayOnPort: aPort at: location
  20242.     self form displayOnPort: aPort at: location + offset! !
  20243.  
  20244. !DisplayText methodsFor: 'display box access'!
  20245. boundingBox 
  20246.     "Refer to the comment in DisplayObject|boundingBox."
  20247.  
  20248.     ^self form boundingBox!
  20249. computeBoundingBox 
  20250.     "Compute minimum enclosing rectangle around characters."
  20251.  
  20252.     | character font width carriageReturn lineWidth lineHeight |
  20253.     carriageReturn _ Character cr.
  20254.     width _ lineWidth _ 0.
  20255.     font _ textStyle defaultFont.
  20256.     lineHeight _ textStyle lineGrid.
  20257.     1 to: text size do: 
  20258.         [:i | 
  20259.         character _ text at: i.
  20260.         character = carriageReturn
  20261.           ifTrue: 
  20262.             [lineWidth _ lineWidth max: width.
  20263.             lineHeight _ lineHeight + textStyle lineGrid.
  20264.             width _ 0]
  20265.           ifFalse: [width _ width + (font widthOf: character)]].
  20266.     lineWidth _ lineWidth max: width.
  20267.     ^offset extent: lineWidth @ lineHeight! !
  20268.  
  20269. !DisplayText methodsFor: 'converting'!
  20270. asParagraph
  20271.     "Answer a Paragraph whose text and style are identical to that of the 
  20272.     receiver."
  20273.  
  20274.     ^Paragraph withText: text style: textStyle! !
  20275.  
  20276. !DisplayText methodsFor: 'private'!
  20277. composeForm
  20278.  
  20279.     form _ self asParagraph asForm!
  20280. setText: aText textStyle: aTextStyle offset: aPoint
  20281.  
  20282.     text _ aText.
  20283.     textStyle _ aTextStyle.
  20284.     offset _ aPoint.
  20285.     form _ nil! !
  20286.  
  20287. !DisplayText methodsFor: 'color'!
  20288. backgroundColor
  20289.     backColor == nil ifTrue: [^ Display white].
  20290.     ^ backColor!
  20291. foregroundColor
  20292.     foreColor == nil ifTrue: [^ Display black].
  20293.     ^ foreColor!
  20294. foregroundColor: cf backgroundColor: cb
  20295.     foreColor _ cf.
  20296.     backColor _ cb! !
  20297. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  20298.  
  20299. DisplayText class
  20300.     instanceVariableNames: ''!
  20301.  
  20302. !DisplayText class methodsFor: 'instance creation'!
  20303. text: aText 
  20304.     "Answer an instance of me such that the text displayed is aText 
  20305.     according to the system's default text style."
  20306.  
  20307.     ^self new
  20308.         setText: aText
  20309.         textStyle: DefaultTextStyle copy
  20310.         offset: 0 @ 0!
  20311. text: aText textStyle: aTextStyle 
  20312.     "Answer an instance of me such that the text displayed is aText 
  20313.     according to the style specified by aTextStyle."
  20314.  
  20315.     ^self new
  20316.         setText: aText
  20317.         textStyle: aTextStyle
  20318.         offset: 0 @ 0!
  20319. text: aText textStyle: aTextStyle offset: aPoint 
  20320.     "Answer an instance of me such that the text displayed is aText 
  20321.     according to the style specified by aTextStyle. The display of the 
  20322.     information should be offset by the amount given as the argument, 
  20323.     aPoint."
  20324.  
  20325.     ^self new
  20326.         setText: aText
  20327.         textStyle: aTextStyle
  20328.         offset: aPoint! !
  20329.  
  20330. !DisplayText class methodsFor: 'examples'!
  20331. example
  20332.     "Continually prints two lines of text wherever you point with the cursor 
  20333.     and press any mouse button.  Terminate by pressing any key on the 
  20334.     keyboard."
  20335.  
  20336.     | t |
  20337.     t _ 'this is a line of characters and
  20338. this is the second line.' asDisplayText.
  20339.     t alignTo: #center.
  20340.     [Sensor anyButtonPressed]
  20341.         whileFalse:
  20342.             [t displayOn: Display at: Sensor cursorPoint]
  20343.  
  20344.     "DisplayText example."! !View subclass: #DisplayTextView
  20345.     instanceVariableNames: 'rule mask editParagraph centered '
  20346.     classVariableNames: ''
  20347.     poolDictionaries: ''
  20348.     category: 'Graphics-Views'!
  20349. DisplayTextView comment:
  20350. 'I represent a view of an instance of DisplayText.'!
  20351.  
  20352. !DisplayTextView methodsFor: 'initialize-release'!
  20353. initialize 
  20354.     "Refer to the comment in View|initialize."
  20355.  
  20356.     super initialize.
  20357.     centered _ false! !
  20358.  
  20359. !DisplayTextView methodsFor: 'accessing'!
  20360. centered
  20361.  
  20362.     centered _ true.
  20363.     self centerText!
  20364. fillColor
  20365.     "Answer an instance of class Form that is to be used as the mask when 
  20366.     displaying the receiver's model (a DisplayText)."
  20367.  
  20368.     ^ mask!
  20369. fillColor: aForm 
  20370.     "Set aForm to be the mask used when displaying the receiver's model."
  20371.  
  20372.     mask _ aForm!
  20373. isCentered
  20374.  
  20375.     ^centered!
  20376. mask
  20377.     "Answer an instance of class Form that is to be used as the mask when 
  20378.     displaying the receiver's model (a DisplayText)."
  20379.  
  20380.     ^ mask!
  20381. rule
  20382.     "Answer a number from 0 to 15 that indicates which of the sixteen 
  20383.     display rules is to be used when copying the receiver's model (a 
  20384.     DisplayText) onto the display screen."
  20385.  
  20386.     rule == nil
  20387.         ifTrue: [^self defaultRule]
  20388.         ifFalse: [^rule]!
  20389. rule: anInteger 
  20390.     "Set anInteger to be the rule used when displaying the receiver's model."
  20391.  
  20392.     rule _ anInteger! !
  20393.  
  20394. !DisplayTextView methodsFor: 'controller access'!
  20395. defaultController 
  20396.     "Refer to the comment in View|defaultController."
  20397.  
  20398.     ^self defaultControllerClass newParagraph: editParagraph!
  20399. defaultControllerClass 
  20400.     "Refer to the comment in View|defaultControllerClass."
  20401.  
  20402.     ^ParagraphEditor! !
  20403.  
  20404. !DisplayTextView methodsFor: 'window access'!
  20405. defaultWindow 
  20406.     "Refer to the comment in View|defaultWindow."
  20407.  
  20408.     ^self inverseDisplayTransform: (editParagraph boundingBox expandBy: 6 @ 6)!
  20409. window: aWindow 
  20410.     "Refer to the comment in View|window:."
  20411.  
  20412.     super window: aWindow.
  20413.     self centerText! !
  20414.  
  20415. !DisplayTextView methodsFor: 'model access'!
  20416. model: aDisplayText 
  20417.     "Refer to the comment in View|model:."
  20418.  
  20419.     super model: aDisplayText.
  20420.     editParagraph _ model asParagraph.
  20421.     self centerText! !
  20422.  
  20423. !DisplayTextView methodsFor: 'displaying'!
  20424. display 
  20425.     "Refer to the comment in View|display."
  20426.  
  20427.     self isUnlocked ifTrue: [self positionText].
  20428.     super display!
  20429. displayView 
  20430.     "Refer to the comment in View|displayView."
  20431.  
  20432.     self clearInside.
  20433.     (self controller isKindOf: ParagraphEditor )
  20434.         ifTrue: [controller changeParagraph: editParagraph].
  20435.     editParagraph foregroundColor: self foregroundColor
  20436.                 backgroundColor: self backgroundColor.
  20437.     self isCentered
  20438.         ifTrue: 
  20439.             [editParagraph displayOn: Display
  20440.                 transformation: self displayTransformation
  20441.                 clippingBox: self insetDisplayBox
  20442.                 fixedPoint: editParagraph boundingBox center]
  20443.         ifFalse: 
  20444.             [editParagraph displayOn: Display]!
  20445. uncacheBits
  20446.     "Normally only sent to a StandardSystemView, but for casees where a DisplayTextView is used alone, without a superview, in which we make this a no-op, put in so that the Character Recognizer doesn't fail.  8/9/96 sw"! !
  20447.  
  20448. !DisplayTextView methodsFor: 'deEmphasizing'!
  20449. deEmphasizeView 
  20450.     "Refer to the comment in View|deEmphasizeView."
  20451.  
  20452.     (self controller isKindOf: ParagraphEditor)
  20453.          ifTrue: [controller deselect]! !
  20454.  
  20455. !DisplayTextView methodsFor: 'private'!
  20456. centerText
  20457.  
  20458.     self isCentered
  20459.         ifTrue: 
  20460.             [editParagraph
  20461.                 align: editParagraph boundingBox center
  20462.                 with: self getWindow center]!
  20463. defaultRule
  20464.  
  20465.     ^Form over!
  20466. positionText
  20467.  
  20468.     | box |
  20469.     box _ (self displayBox insetBy: 6@6) origin extent: editParagraph boundingBox extent.
  20470.     editParagraph wrappingBox: box clippingBox: box.
  20471.     self centerText! !
  20472.  
  20473. !DisplayTextView methodsFor: 'lock access'!
  20474. lock 
  20475.     "Refer to the comment in View|lock.  Must do what would be done by displaying..."
  20476.  
  20477.     self isUnlocked ifTrue: [self positionText].
  20478.     super lock! !
  20479. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  20480.  
  20481. DisplayTextView class
  20482.     instanceVariableNames: ''!
  20483.  
  20484. !DisplayTextView class methodsFor: 'examples'!
  20485. example1    
  20486.     "Create a system view with a paragraph editor in it."
  20487.     | topView aDisplayTextView |
  20488.     aDisplayTextView _ DisplayTextView new model: 'test string' asDisplayText.
  20489.     aDisplayTextView borderWidth: 2.
  20490.     topView _ StandardSystemView new.
  20491.     topView label: 'Text Editor'.
  20492.     topView addSubView: aDisplayTextView.
  20493.     topView controller open
  20494.  
  20495.     "DisplayTextView example1"!
  20496. example2    
  20497.     "Create a standarad system view with two parts, one editable, the other not."
  20498.     | topView aDisplayTextView |
  20499.     topView _ StandardSystemView new.
  20500.     topView label: 'Text Editor'.
  20501.     aDisplayTextView _ self new model: 'test string label' asDisplayText.
  20502.     aDisplayTextView controller: NoController new.
  20503.     aDisplayTextView window: (0 @ 0 extent: 100 @ 100).
  20504.     aDisplayTextView borderWidthLeft: 2 right: 0 top: 2 bottom: 2.
  20505.     topView addSubView: aDisplayTextView.
  20506.  
  20507.     aDisplayTextView _ self new model: 'test string' asDisplayText.
  20508.     aDisplayTextView window: (0 @ 0 extent: 100 @ 100).
  20509.     aDisplayTextView borderWidth: 2.
  20510.     topView
  20511.         addSubView: aDisplayTextView
  20512.         align: aDisplayTextView viewport topLeft
  20513.         with: topView lastSubView viewport topRight.
  20514.     topView controller open
  20515.  
  20516.     "DisplayTextView example2"!
  20517. example3    
  20518.     "Create a passive view of some text on the screen."
  20519.     | view |
  20520.     view_ self new model: 'this is a test of one line
  20521. and the second line' asDisplayText.
  20522.     view translateBy: 100@100.    
  20523.     view borderWidth: 2.
  20524.     view display.
  20525.     view release
  20526.  
  20527.     "DisplayTextView example3"!
  20528. example4    
  20529.     "Create four passive views of some text on the screen with fat borders."
  20530.     | view |
  20531.     view_ self new model: 'this is a test of one line
  20532. and the second line' asDisplayText.
  20533.     view translateBy: 100@100.    
  20534.     view borderWidth: 5.
  20535.     view display.
  20536.     3 timesRepeat: [view translateBy: 100@100. view display].
  20537.     view release
  20538.  
  20539.     "DisplayTextView example4"!
  20540. open: textOrString label: aLabel
  20541.     "Create a system view with a paragraph editor in it.  6/2/96 sw"
  20542.  
  20543.     | topView aDisplayTextView |
  20544.     aDisplayTextView _ DisplayTextView new model: textOrString asDisplayText.
  20545.     aDisplayTextView borderWidth: 2.
  20546.     topView _ StandardSystemView new.
  20547.     topView label: aLabel.
  20548.     topView addSubView: aDisplayTextView.
  20549.     topView controller open
  20550.  
  20551.     "DisplayTextView open: 'Great green gobs' label: 'Gopher Guts'"! !Model subclass: #DualChangeSorter
  20552.     instanceVariableNames: 'leftCngSorter rightCngSorter '
  20553.     classVariableNames: ''
  20554.     poolDictionaries: ''
  20555.     category: 'Interface-Changes'!
  20556.  
  20557. !DualChangeSorter methodsFor: 'everything'!
  20558. aReadThis
  20559.     "This class presents a view of a two change sets at once.  See ChangeSorter for the details of how each sorter works.  
  20560.     
  20561.     DualChangeSorter new open.
  20562.     DualChangeSorter allInstances inspect
  20563.     "!
  20564. defaultBackgroundColor
  20565.     ^ #lightBlue!
  20566. isLeftSide: theOne
  20567.     "Which side am I?"
  20568.     ^ theOne == leftCngSorter!
  20569. open
  20570.     "1991, tk.  Modified 5/16/96 sw: decrease minimum size drastically
  20571.      6/18/96 sw: more modest minimum size, and other minor adjustments"
  20572.  
  20573.     | topView |
  20574.     leftCngSorter _ ChangeSorter new initialize.
  20575.     leftCngSorter parent: self.
  20576.     rightCngSorter _ ChangeSorter new initialize.
  20577.     rightCngSorter parent: self.
  20578.  
  20579.     topView _ StandardSystemView new.
  20580.     topView model: self.
  20581.     topView label: leftCngSorter label.
  20582.     topView minimumSize: 300 @ 200.
  20583.     self openView: topView.
  20584.     topView controller open!
  20585. openView: topView
  20586.     "Create views of dual side-by-side change sorter views"
  20587.     | leftView rightView |
  20588.  
  20589.     leftView _ View new.
  20590.     leftView model: leftCngSorter.
  20591.     leftView window: (0 @ 0 extent: 360 @ 360).
  20592.     leftView borderWidthLeft: 0 right: 0 top: 0 bottom: 0.
  20593.     leftCngSorter openView: leftView.
  20594.  
  20595.  
  20596.     rightView _ View new.
  20597.     rightView model: rightCngSorter.
  20598.     rightView window: (0 @ 0 extent: 360 @ 360).
  20599.     rightView borderWidthLeft: 0 right: 0 top: 0 bottom: 0.
  20600.     rightCngSorter openView: rightView.
  20601.  
  20602.     topView addSubView: leftView.
  20603.     topView addSubView: rightView.
  20604.  
  20605.     " leftView 
  20606.         align: leftView viewport topLeft     
  20607.         with: topView viewport topLeft. "
  20608.     rightView 
  20609.         align: rightView viewport topLeft     
  20610.         with: leftView viewport topRight.
  20611. !
  20612. other: theOne
  20613.     "Return the other side's ChangeSorter"
  20614.     ^ theOne == leftCngSorter
  20615.         ifTrue: [rightCngSorter]
  20616.         ifFalse: [leftCngSorter]!
  20617. release
  20618.     leftCngSorter release.
  20619.     rightCngSorter release.! !Stream subclass: #DummyStream
  20620.     instanceVariableNames: ''
  20621.     classVariableNames: ''
  20622.     poolDictionaries: ''
  20623.     category: 'Objects to Disk'!
  20624.  
  20625. !DummyStream methodsFor: 'as yet unclassified'!
  20626. aComment
  20627.     "The purpose of this class is to absorb all steam messages and do nothing.  This is so ReferenceStream can pretend to write on it while traversing all objects it would normally write.  We need to know what those object are.  8/17/96 tk"!
  20628. binary
  20629.     "do nothing"!
  20630. nextInt32Put: arg
  20631.     "do nothing"!
  20632. nextNumber: cnt put: num
  20633.     "do nothing"!
  20634. nextStringPut: aString
  20635.     "do nothing"!
  20636. position
  20637.     "Return any random number.  Here is where the real lying begins.  We are a DummyStream afterall.  8/17/96 tk"
  20638.  
  20639.     ^ 47 !
  20640. subclassResponsibility
  20641.     "Do nothing.  Most messages to class Stream are defined as subclassResponsibility.  Just accept them.  8/17/96 tk"
  20642.  
  20643.     "No error.  Just go on."! !
  20644. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  20645.  
  20646. DummyStream class
  20647.     instanceVariableNames: ''!
  20648.  
  20649. !DummyStream class methodsFor: 'as yet unclassified'!
  20650. on: aFile
  20651.     "Do nothing.  8/17/96 tk"
  20652.     ^ self basicNew! !ParseNode subclass: #Encoder
  20653.     instanceVariableNames: 'scopeTable nTemps supered requestor class literalStream selectorSet litIndSet litSet sourceRanges '
  20654.     classVariableNames: ''
  20655.     poolDictionaries: ''
  20656.     category: 'System-Compiler'!
  20657. Encoder comment:
  20658. 'I encode names and literals into tree nodes with byte codes for the compiler. Byte codes for literals are not assigned until the tree-sizing pass of the compiler, because only then is it known which literals are actually needed. I also keep track of sourceCode ranges during parsing and code generation so I can provide an inverse map for the debugger.'!
  20659.  
  20660. !Encoder methodsFor: 'initialize-release'!
  20661. fillDict: dict with: nodeClass mapping: keys to: codeArray
  20662.  
  20663.     | codeStream key |
  20664.     codeStream _ ReadStream on: codeArray.
  20665.     keys do: 
  20666.         [:key | dict 
  20667.                 at: key
  20668.                 put:  (nodeClass new name: key key: key code: codeStream next)]!
  20669. init: aClass context: aContext notifying: req
  20670.  
  20671.     | variable node n homeNode indexNode |
  20672.     requestor _ req.
  20673.     class _ aClass.
  20674.     nTemps _ 0.
  20675.     supered _ false.
  20676.     self initScopeAndLiteralTables.
  20677.     n _ -1.
  20678.     class allInstVarNames do: 
  20679.         [:variable | 
  20680.         node _ VariableNode new
  20681.                     name: variable
  20682.                     index: (n _ n + 1)
  20683.                     type: LdInstType.
  20684.         scopeTable at: variable put: node].
  20685.     aContext == nil
  20686.         ifFalse: 
  20687.             [homeNode _ self bindTemp: 'homeContext'.
  20688.             "first temp = aContext passed as arg"
  20689.             n _ 0.
  20690.             aContext tempNames do: 
  20691.                 [:variable | 
  20692.                 indexNode _ self encodeLiteral: (n _ n + 1).
  20693.                 node _ MessageNode new
  20694.                             receiver: homeNode
  20695.                             selector: #tempAt:
  20696.                             arguments: (Array with: indexNode)
  20697.                             precedence: 3
  20698.                             from: self.
  20699.                 scopeTable at: variable put: node]].
  20700.     sourceRanges _ Dictionary new: 32!
  20701. initScopeAndLiteralTables
  20702.  
  20703.     scopeTable _ StdVariables copy.
  20704.     litSet _ StdLiterals copy.
  20705.     selectorSet _ StdSelectors copy.
  20706.     litIndSet _ Dictionary new: 16.
  20707.     literalStream _ WriteStream on: (Array new: 32)!
  20708. noteSuper
  20709.  
  20710.     supered _ true!
  20711. nTemps: n literals: lits class: cl 
  20712.     "Decompile."
  20713.  
  20714.     class _ cl.
  20715.     nTemps _ n.
  20716.     literalStream _ ReadStream on: lits.
  20717.     literalStream position: lits size!
  20718. release
  20719.  
  20720.     requestor _ nil! !
  20721.  
  20722. !Encoder methodsFor: 'encoding'!
  20723. cantStoreInto: varName
  20724.  
  20725.     ^StdVariables includesKey: varName!
  20726. encodeLiteral: object
  20727.  
  20728.     ^self
  20729.         name: object
  20730.         key: (class literalScannedAs: object notifying: self)
  20731.         class: LiteralNode
  20732.         type: LdLitType
  20733.         set: litSet!
  20734. encodeSelector: selector
  20735.  
  20736.     ^self
  20737.         name: selector
  20738.         key: selector
  20739.         class: SelectorNode
  20740.         type: SendType
  20741.         set: selectorSet!
  20742. encodeVariable: name
  20743.     ^ self encodeVariable: name ifUnknown: [ self undeclared: name ]!
  20744. encodeVariable: name ifUnknown: action
  20745.  
  20746.     | varNode assoc sym |
  20747.     varNode _ 
  20748.         scopeTable 
  20749.             at: name
  20750.             ifAbsent: 
  20751.                 [self lookupInPools: name 
  20752.                     ifFound: [:assoc | ^self global: assoc name: name].
  20753.                 ^action value].
  20754.     ^varNode!
  20755. litIndex: literal
  20756.     | p |
  20757.     p _ literalStream position.
  20758.     p = 64 ifTrue:
  20759.         [self notify: 'More than 64 literals referenced. 
  20760. You must split or otherwise simplify this method.
  20761. The 65th literal is: ', literal printString. ^nil].
  20762.         "Would like to show where it is in the source code, 
  20763.          but that info is hard to get."
  20764.     literalStream nextPut: literal.
  20765.     ^ p!
  20766. undeclared: name
  20767.  
  20768.     | sym |
  20769.     requestor interactive ifTrue: [^self notify: 'Undeclared'].
  20770.     Transcript show: ' (' , name , ' is Undeclared) '.
  20771.     sym _ name asSymbol.
  20772.     Undeclared at: sym put: nil.
  20773.     ^self global: (Undeclared associationAt: sym) name: sym! !
  20774.  
  20775. !Encoder methodsFor: 'temps'!
  20776. autoBind: name 
  20777.     "Declare a block argument as a temp if not already declared."
  20778.  
  20779.     | node assoc |
  20780.     node _ 
  20781.         scopeTable 
  20782.             at: name
  20783.             ifAbsent: 
  20784.                 [(self lookupInPools: name ifFound: [:assoc | assoc])
  20785.                     ifTrue: [self notify: 'Name already used in a Pool or Global'].
  20786.                 ^self reallyBind: name].
  20787.     node isTemp ifFalse: [^self notify: 'Name already used in this class'].
  20788.     ^node!
  20789. bindTemp: name 
  20790.     "Declare a temporary; error not if a field or class variable."
  20791.  
  20792.     (scopeTable includesKey: name)
  20793.         ifTrue: [^self notify: 'Name is already defined'].
  20794.     ^self reallyBind: name!
  20795. maxTemp
  20796.  
  20797.     ^nTemps!
  20798. newTemp: name
  20799.  
  20800.     nTemps _ nTemps + 1.
  20801.     ^VariableNode new
  20802.         name: name
  20803.         index: nTemps - 1
  20804.         type: LdTempType! !
  20805.  
  20806. !Encoder methodsFor: 'results'!
  20807. allLiterals
  20808.     supered ifTrue: [self litIndex: (self associationFor: class)].
  20809.     ^ literalStream contents!
  20810. associationFor: aClass
  20811.  
  20812.     | name |
  20813.     name _ Smalltalk keyAtValue: aClass ifAbsent: [^Association new value: aClass].
  20814.     ^Smalltalk associationAt: name!
  20815. literals
  20816.     "Should only be used for decompiling primitives"
  20817.     ^ literalStream contents!
  20818. tempNames 
  20819.     | tempNodes |
  20820.     tempNodes _ SortedCollection sortBlock: [:n1 :n2 | n1 code <= n2 code].
  20821.     scopeTable associationsDo:
  20822.         [:assn | (assn value isTemp and:
  20823.                 [assn value isMemberOf: VariableNode]) "no remote temps"
  20824.             ifTrue: [tempNodes add: assn value]].
  20825.     ^tempNodes collect: [:node | node key]! !
  20826.  
  20827. !Encoder methodsFor: 'error handling'!
  20828. notify: string
  20829.     "Put a separate notifier on top of the requestor's window"
  20830.     | req |
  20831.     requestor == nil
  20832.         ifFalse: 
  20833.             [req _ requestor.
  20834.             self release.
  20835.             req notify: string].
  20836.     ^false!
  20837. notify: string at: location
  20838.  
  20839.     | req |
  20840.     requestor == nil
  20841.         ifFalse: 
  20842.             [req _ requestor.
  20843.             self release.
  20844.             req notify: string at: location].
  20845.     ^false!
  20846. requestor: req
  20847.     "Often the requestor is a BrowserCodeController"
  20848.     requestor _ req! !
  20849.  
  20850. !Encoder methodsFor: 'source mapping'!
  20851. noteSourceRange: range forNode: node
  20852.  
  20853.     sourceRanges at: node put: range!
  20854. sourceMap
  20855.     "Answer with a sorted set of associations (pc range)."
  20856.  
  20857.     | key |
  20858.     ^(sourceRanges keys collect: 
  20859.         [:key |  Association key: key pc value: (sourceRanges at: key)])
  20860.             asSortedCollection! !
  20861.  
  20862. !Encoder methodsFor: 'private'!
  20863. classEncoding
  20864.     "This is a hack so that the parser may findout what class it was parsing for when it wants to create a syntax error view."
  20865.     ^ class!
  20866. global: ref name: name
  20867.  
  20868.     ^self
  20869.         name: name
  20870.         key: ref
  20871.         class: VariableNode
  20872.         type: LdLitIndType
  20873.         set: litIndSet!
  20874. lookupInPools: name ifFound: assocBlock
  20875.  
  20876.     | sym out |
  20877.     Symbol 
  20878.         hasInterned: name 
  20879.         ifTrue: [:sym | ^class scopeHas: sym ifTrue: assocBlock].
  20880.     ^ class scopeHas: name ifTrue: assocBlock.  "Its a string in the pool"!
  20881. name: name key: key class: leafNodeClass type: type set: dict
  20882.  
  20883.     | node |
  20884.     ^dict 
  20885.         at: key
  20886.         ifAbsent: 
  20887.             [node _ leafNodeClass new
  20888.                         name: name
  20889.                         key: key
  20890.                         index: nil
  20891.                         type: type.
  20892.             dict at: key put: node.
  20893.             ^node]!
  20894. possibleVariablesFor: proposedVariable
  20895.  
  20896.     | results |
  20897.     results _ proposedVariable correctAgainstDictionary: scopeTable
  20898.                                 continuedFrom: nil.
  20899.     proposedVariable first isUppercase ifTrue:
  20900.         [ results _ class possibleVariablesFor: proposedVariable
  20901.                         continuedFrom: results ].
  20902.     ^ proposedVariable correctAgainst: nil continuedFrom: results.
  20903. !
  20904. reallyBind: name
  20905.  
  20906.     | node |
  20907.     node _ self newTemp: name.
  20908.     scopeTable at: name put: node.
  20909.     ^node! !ReadWriteStream subclass: #ExternalStream
  20910.     instanceVariableNames: ''
  20911.     classVariableNames: ''
  20912.     poolDictionaries: ''
  20913.     category: 'System-Files'!
  20914. ExternalStream comment:
  20915. 'I represent an accessor for a sequence of objects that communicate to the outside world. My instances can contain non-homogenous elements. Assumes streaming on a collection of binary, byte-sized elements. My methods assume that a "word" consists of two-bytes.'!
  20916.  
  20917. !ExternalStream methodsFor: 'accessing'!
  20918. next: anInteger 
  20919.     "Answer the next anInteger elements of my collection. Must override 
  20920.     because default uses self contents species, which might involve a large 
  20921.     collection."
  20922.  
  20923.     | newArray |
  20924.     newArray _ collection species new: anInteger.
  20925.     1 to: anInteger do: [:index | newArray at: index put: self next].
  20926.     ^newArray! !
  20927.  
  20928. !ExternalStream methodsFor: 'nonhomogeneous positioning'!
  20929. padTo: bsize 
  20930.     "Pad (skip) to next boundary of bsize characters, and answer how many 
  20931.     characters were skipped."
  20932.  
  20933.     self subclassResponsibility!
  20934. padTo: bsize put: aCharacter 
  20935.     "Pad using the argument, aCharacter, to the next boundary of bsize 
  20936.     characters, and answer how many characters were written."
  20937.  
  20938.     self subclassResponsibility!
  20939. padToNextWord
  20940.     "Make position even (on word boundary), answering the padding 
  20941.     character if any."
  20942.  
  20943.     self position even
  20944.         ifTrue: [^false]
  20945.         ifFalse: [^self next]!
  20946. padToNextWordPut: char
  20947.     "Make position even on word boundary, writing the padding character, 
  20948.     char, if necessary."
  20949.  
  20950.     self position even
  20951.         ifTrue: [^nil]
  20952.         ifFalse: [^self nextPut: char]!
  20953. skipWords: nWords 
  20954.     "Position after nWords number of words."
  20955.  
  20956.     self skip: 2 * nWords!
  20957. wordPosition
  20958.     "Answer the current position in words."
  20959.  
  20960.     ^self position / 2!
  20961. wordPosition: wp 
  20962.     "Set current position in words to be wp."
  20963.  
  20964.     self position: 2 * wp! !
  20965.  
  20966. !ExternalStream methodsFor: 'nonhomogeneous accessing'!
  20967. nextInt32
  20968.     "Read a 32-bit signed integer from the next 4 bytes"
  20969.     | s |
  20970.     s _ 0.
  20971.     1 to: 4 do: [:i | s _ (s bitShift: 8) + self next].
  20972.     (s bitAnd: 16r80000000) = 0
  20973.         ifTrue: [^ s]
  20974.         ifFalse: [^ -1 - s bitInvert32]!
  20975. nextInt32Put: int32
  20976.     "Write a signed integer to the next 4 bytes"
  20977.     | pos |
  20978.     pos _ int32 < 0
  20979.         ifTrue: [(0-int32) bitInvert32 + 1]
  20980.         ifFalse: [int32].
  20981.     1 to: 4 do: [:i | self nextPut: (pos digitAt: 5-i)].
  20982.     ^ int32!
  20983. nextNumber: n 
  20984.     "Answer the next n bytes as a positive Integer or LargePositiveInteger."
  20985.  
  20986.     | s |
  20987.     n <= 2
  20988.         ifTrue: 
  20989.             [s _ 0.
  20990.             n timesRepeat: [s _ s * 256 + self next].
  20991.             ^s].
  20992.     s _ LargePositiveInteger new: n.
  20993.     1 to: n do: [:i | s at: n + 1 - i put: self next].
  20994.     "reverse order of significance"
  20995.     ^s normalize!
  20996. nextNumber: n put: v 
  20997.     "Append to the receiver the argument, v, which is a positive 
  20998.     SmallInteger or a LargePositiveInteger, as the next n bytes.
  20999.     Possibly pad with leading zeros."
  21000.  
  21001.     1 to: n do: [:i | self nextPut: (v digitAt: 5-i)].
  21002.     ^ v
  21003. !
  21004. nextString
  21005.     "Read a string from the receiver. The first byte is the length of the 
  21006.     string, unless it is greater than 192, in which case the first two bytes 
  21007.     encode the length."
  21008.  
  21009.     | aString char length|
  21010.     length _ self next.        "first byte."
  21011.     length >= 192 ifTrue: [length _ (length - 192) * 256 + self next].
  21012.     aString _ String new: length.
  21013.     1 to: length do: [:i | aString at: i put: self next asCharacter].
  21014.     ^aString!
  21015. nextStringPut: s 
  21016.     "Append the string, s, to the receiver."
  21017.  
  21018.     | length |
  21019.     (length _ s size) < 192
  21020.         ifTrue: [self nextPut: length]
  21021.         ifFalse: 
  21022.             [self nextPut: (length // 256 + 192).
  21023.             self nextPut: (length \\ 256)].
  21024.     s do: [:char | self nextPut: char asciiValue].
  21025.     ^s!
  21026. nextWord
  21027.     "Answer the next two bytes from the receiver as an Integer."
  21028.  
  21029.     | high low |
  21030.     high _ self next.
  21031.         high==nil ifTrue: [^false].
  21032.     low _ self next.
  21033.         low==nil ifTrue: [^false].
  21034.     ^(high asInteger bitShift: 8) + low asInteger!
  21035. nextWordPut: aWord 
  21036.     "Append to the receiver an Integer as the next two bytes."
  21037.  
  21038.     self nextPut: ((aWord bitShift: -8) bitAnd: 255).
  21039.     self nextPut: (aWord bitAnd: 255).
  21040.     ^aWord! !
  21041.  
  21042. !ExternalStream methodsFor: 'positioning'!
  21043. resetContents
  21044.     "Set the position and limits to 0."
  21045.  
  21046.     position _ 0.
  21047.     readLimit _ 0! !
  21048. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  21049.  
  21050. ExternalStream class
  21051.     instanceVariableNames: ''!
  21052.  
  21053. !ExternalStream class methodsFor: 'instance creation'!
  21054. new
  21055.  
  21056.     ^self basicNew! !Object subclass: #FakeClassPool
  21057.     instanceVariableNames: ''
  21058.     classVariableNames: 'SystemChanges LastQuitLogPosition CachedClassNames LowSpaceProcess LowSpaceSemaphore SpecialSelectors '
  21059.     poolDictionaries: ''
  21060.     category: 'Interface-Browser'!
  21061. FakeClassPool comment:
  21062. 'The sole purpose of this class is to allow the Browser code pane to evaluate the class variables of the class whose method it is showing.  It does this by stuffing a pointer to the classpool dictionary of the class being shown into its own classpool.  It does this just around a doIt in the code pane.  An instance of FakeClasspool is then used as the receiver of the doIt.'!
  21063.  
  21064. !FakeClassPool methodsFor: 'as yet unclassified'!
  21065. aReadThis
  21066.     "The sole purpose of this class is to allow the Browser code pane to evaluate the class variables of the class whose method it is showing.  It does this by stuffing a pointer to the classpool dictionary of the class being shown into its own classpool.  It does this just around a doIt in the code pane.  An instance of FakeClasspool is then used as the receiver of the doIt."! !
  21067. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  21068.  
  21069. FakeClassPool class
  21070.     instanceVariableNames: ''!
  21071.  
  21072. !FakeClassPool class methodsFor: 'as yet unclassified'!
  21073. classPool: aDictionary
  21074.     "temporarily use the classPool of another class"
  21075.     classPool _ aDictionary!
  21076. sharedPools: anOrderedCollection
  21077.     "temporarily use the sharedPools of another class"
  21078.     sharedPools _ anOrderedCollection! !Boolean subclass: #False
  21079.     instanceVariableNames: ''
  21080.     classVariableNames: ''
  21081.     poolDictionaries: ''
  21082.     category: 'Kernel-Objects'!
  21083. False comment:
  21084. 'I represent the logical value false.'!
  21085.  
  21086. !False methodsFor: 'logical operations'!
  21087. & alternativeObject 
  21088.     "Evaluating conjunction -- answer false since receiver is false."
  21089.  
  21090.     ^self!
  21091. not
  21092.     "Negation -- answer true since the receiver is false."
  21093.  
  21094.     ^true!
  21095. | aBoolean 
  21096.     "Evaluating disjunction (OR) -- answer with the argument, aBoolean."
  21097.  
  21098.     ^aBoolean! !
  21099.  
  21100. !False methodsFor: 'controlling'!
  21101. and: alternativeBlock 
  21102.     "Nonevaluating conjunction -- answer with false since the receiver is false."
  21103.  
  21104.     ^self!
  21105. ifFalse: alternativeBlock 
  21106.     "Answer the value of alternativeBlock. Execution does not actually
  21107.     reach here because the expression is compiled in-line."
  21108.  
  21109.     ^alternativeBlock value!
  21110. ifFalse: falseAlternativeBlock ifTrue: trueAlternativeBlock 
  21111.     "Answer the value of falseAlternativeBlock. Execution does not
  21112.     actually reach here because the expression is compiled in-line."
  21113.  
  21114.     ^falseAlternativeBlock value!
  21115. ifTrue: alternativeBlock 
  21116.     "Since the condition is false, answer the value of the false alternative, 
  21117.     which is nil. Execution does not actually reach here because the
  21118.     expression is compiled in-line."
  21119.  
  21120.     ^nil!
  21121. ifTrue: trueAlternativeBlock ifFalse: falseAlternativeBlock 
  21122.     "Answer the value of falseAlternativeBlock. Execution does not
  21123.     actually reach here because the expression is compiled in-line."
  21124.  
  21125.     ^falseAlternativeBlock value!
  21126. or: alternativeBlock 
  21127.     "Nonevaluating disjunction -- answer value of alternativeBlock."
  21128.  
  21129.     ^alternativeBlock value! !
  21130.  
  21131. !False methodsFor: 'printing'!
  21132. printOn: aStream 
  21133.  
  21134.     aStream nextPutAll: 'false'! !
  21135.  
  21136. !False methodsFor: 'conversion'!
  21137. binaryValue
  21138.     ^0
  21139. ! !Dictionary subclass: #FastDictionary
  21140.     instanceVariableNames: 'key1 assoc1 key2 assoc2 key3 assoc3 key4 assoc4 '
  21141.     classVariableNames: ''
  21142.     poolDictionaries: ''
  21143.     category: 'Collections-Unordered'!
  21144.  
  21145. !FastDictionary methodsFor: 'as yet unclassified'!
  21146. at: key ifAbsent: aBlock
  21147.     "Answer the value associated with the key.  Look in cache first.  Remember to invalidate when removing.  7/10/96 tk"
  21148.  
  21149.     | index which |
  21150.     key == key1 ifTrue: [^ assoc1 value].
  21151.     key == key2 ifTrue: [^ assoc2 value].
  21152.     key == key3 ifTrue: [^ assoc3 value].
  21153.     key == key4 ifTrue: [^ assoc4 value].
  21154.  
  21155.     index _ self findElementOrNil: key.
  21156.     (array at: index) == nil ifTrue: [^ aBlock value].
  21157.  
  21158.     which _ ((Time millisecondClockValue) bitAnd: 3) + 1.
  21159.     which = 1 ifTrue: [key1 _ key.  assoc1 _ array at: index. ^ assoc1 value].
  21160.     which = 2 ifTrue: [key2 _ key.  assoc2 _ array at: index. ^ assoc2 value].
  21161.     which = 3 ifTrue: [key3 _ key.  assoc3 _ array at: index. ^ assoc3 value].
  21162.     which = 4 ifTrue: [key4 _ key.  assoc4 _ array at: index. ^ assoc4 value].
  21163.     self error: 'had to be one of those!!'!
  21164. rehash
  21165.     "Rehash gives new Associations, so must clear old ones from the cache.  9/7/96 tk"
  21166.  
  21167. key1 _ Array new: 1.    "Unique"
  21168. key2 _ Array new: 1.    "Unique"
  21169. key3 _ Array new: 1.    "Unique"
  21170. key4 _ Array new: 1.    "Unique"
  21171. ^ super rehash!
  21172. removeKey: key ifAbsent: aBlock 
  21173.     "Remove key (and its associated value) from the receiver. If key is not in 
  21174.     the receiver, answer the result of evaluating aBlock. Otherwise, answer 
  21175.     the value externally named by key.
  21176.     If the key is cached, clear it's entry.  7/10/96 tk"
  21177.  
  21178.     key == key1 ifTrue: [key1 _ Array new: 1].    "Unique"
  21179.     key == key2 ifTrue: [key2 _ Array new: 1].    "Unique"
  21180.     key == key3 ifTrue: [key3 _ Array new: 1].    "Unique"
  21181.     key == key4 ifTrue: [key4 _ Array new: 1].    "Unique"
  21182.     ^ super removeKey: key ifAbsent: aBlock! !StringHolderController subclass: #FileController
  21183.     instanceVariableNames: ''
  21184.     classVariableNames: 'FileYellowButtonMenu FileYellowButtonMessages '
  21185.     poolDictionaries: ''
  21186.     category: 'Interface-FileList'!
  21187. FileController comment:
  21188. 'I am a kind of StringHolderController (a ParagraphEditor that adds the doIt, printIt, accept, and cancel commands). The commands accept and cancel are omitted. I provide control for editing the contents of an external file. Additional menu commands are:
  21189.     fileItIn    treat the text selection as though it were the contents of a file and read it into the system
  21190.     get    retrieve the file contents to be the contents of the StringHolder (analogous to cancel)
  21191.     put    save the contents of the StringHolder in the file (analogous to accept)'!
  21192.  
  21193. !FileController methodsFor: 'menu messages'!
  21194. browseChanges
  21195.     "Browse the selected file in fileIn format."
  21196.     self controlTerminate.
  21197.     model browseChanges.
  21198.     self controlInitialize!
  21199. get
  21200.     "Get contents of file again, it may have changed. Do this by making the 
  21201.     cancel string be the contents, and doing a cancel."
  21202.  
  21203.     Cursor read
  21204.         showWhile: 
  21205.             [initialText _ (model readContentsBrief: false) asText.
  21206.             self cancel]!
  21207. getHex
  21208.     "Get contents of file again, and display in Hex. Do this by making the 
  21209.     cancel string be the contents, and doing a cancel."
  21210.  
  21211.     Cursor read
  21212.         showWhile: 
  21213.             [initialText _ (model readContentsHex) asText.
  21214.             self cancel]!
  21215. put
  21216.     "Replace file contents with contents of view."
  21217.  
  21218.     self controlTerminate.
  21219.     model put: paragraph string.
  21220.     self unlockModel.
  21221.     self controlInitialize! !
  21222.  
  21223. !FileController methodsFor: 'private'!
  21224. initializeYellowButtonMenu
  21225.  
  21226.     self yellowButtonMenu: FileYellowButtonMenu
  21227.         yellowButtonMessages: FileYellowButtonMessages! !
  21228. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  21229.  
  21230. FileController class
  21231.     instanceVariableNames: ''!
  21232.  
  21233. !FileController class methodsFor: 'class initialization'!
  21234. initialize
  21235.     "Initialize the yellow button pop-up menu for a file controller; this is the same as for a general text widnow, with the addition of the top four file-related items.  5/12/96 sw"
  21236.  
  21237.     FileYellowButtonMenu _ PopUpMenu labels: 
  21238. 'file it in
  21239. put
  21240. get
  21241. view as hex
  21242. browse changes
  21243. find...(f)
  21244. find again (g)
  21245. set search string (h)
  21246. do again (j)
  21247. undo (z)
  21248. copy (c)
  21249. cut (x)
  21250. paste (v)
  21251. do it (d)
  21252. print it (p)
  21253. inspect it (i)
  21254. accept (s)
  21255. cancel (l)
  21256. more...' 
  21257.         lines: #(5 8 10 13 16 18).
  21258.  
  21259.     FileYellowButtonMessages _ 
  21260.         #(fileItIn put get getHex browseChanges find findAgain setSearchString again undo copySelection cut paste doIt printIt inspectIt accept cancel shiftedYellowButtonActivity)
  21261.  
  21262. "FileController initialize"
  21263. ! !
  21264.  
  21265. FileController initialize!
  21266. Object subclass: #FileDirectory
  21267.     instanceVariableNames: 'pathName closed '
  21268.     classVariableNames: 'DefaultDirectory '
  21269.     poolDictionaries: ''
  21270.     category: 'System-Files'!
  21271. FileDirectory comment:
  21272. 'I represent a collection of Files. My instances are uniquely identified by the device or server to which they refer. They may also be found in some other dictionary or FileDirectory, though often this is implicit.'!
  21273.  
  21274. !FileDirectory methodsFor: 'path name'!
  21275. pathName
  21276.     ^ pathName!
  21277. pathNameDelimiter
  21278.     ^ self class pathNameDelimiter!
  21279. pathParts
  21280.     ^ pathName findTokens: self pathNameDelimiter asString! !
  21281.  
  21282. !FileDirectory methodsFor: 'file names'!
  21283. fileNames
  21284.     "FileDirectory default fileNames"
  21285.     ^ self directoryContents collect: [:spec | spec first]!
  21286. fileNamesMatching: pat
  21287.     "FileDirectory default fileNamesMatching: '*'"
  21288.     ^ self directoryContents
  21289.         collect: [:spec | spec first]
  21290.         thenSelect: [:fname | pat match: fname]!
  21291. fullNameFor: fileName
  21292.     (pathName isEmpty
  21293.         or: [fileName includes: self pathNameDelimiter])
  21294.         ifTrue: [^ fileName].
  21295.     ^ pathName , self pathNameDelimiter asString , fileName!
  21296. localNameFor: fileName
  21297.     pathName isEmpty ifTrue: [^ fileName].
  21298.     pathName size >= fileName size ifTrue: [String new].
  21299.     (pathName, '*' match: fileName)
  21300.         ifTrue: [^ fileName copyFrom: pathName size+2
  21301.                             to: fileName size].
  21302.     ^ String new! !
  21303.  
  21304. !FileDirectory methodsFor: 'file creation'!
  21305. copyFileNamed: fileName1 toFileNamed: fileName2
  21306.     "FileDirectory default copyFileNamed: 'todo.txt'
  21307.                         toFileNamed: 'todocopy.txt'"
  21308.     | file1 file2 buffer |
  21309.     file1 _ self readOnlyFileNamed: fileName1.
  21310.     file2 _ self newFileNamed: fileName2.
  21311.     buffer _ String new: 50000.
  21312.     [file1 atEnd] whileFalse:
  21313.         [file2 nextPutAll: (file1 nextInto: buffer)].
  21314.     file1 close.  file2 close!
  21315. fileNamed: fileName
  21316.     ^ self fileClass fileNamed: (self fullNameFor: fileName)!
  21317. newFileNamed: fileName
  21318.     ^ self fileClass newFileNamed: (self fullNameFor: fileName)!
  21319. oldFileNamed: fileName
  21320.     ^ self fileClass oldFileNamed: (self fullNameFor: fileName)!
  21321. readOnlyFileNamed: fileName
  21322.     ^ self fileClass readOnlyFileNamed: (self fullNameFor: fileName)! !
  21323.  
  21324. !FileDirectory methodsFor: 'delete, rename'!
  21325. deleteFileNamed: aFileName
  21326.     ^ self primitiveDeleteFileNamed: (self fullNameFor: aFileName)!
  21327. deleteFileNamed: aFileName ifAbsent: failBlock
  21328.     "Delete the file of the given name if it exists, else evaluate failBlock"
  21329.     (self deleteFileNamed: aFileName) == nil ifTrue: [^ failBlock value]!
  21330. primitiveDeleteFileNamed: aFileName
  21331.     "Delete the file of the given name.
  21332.     ^ self if it had existed, else ^ nil"
  21333.     <primitive: 156>
  21334.     ^ nil!
  21335. primitiveRename: oldFileName toBe: newFileName 
  21336.     "Rename the file of the given name if it exists, else fail"
  21337.     <primitive: 159>
  21338.     self halt: 'Attempt to rename a non-existent file,
  21339. or to use a name that is already in use'!
  21340. rename: oldFileName toBe: newFileName 
  21341.     ^ self primitiveRename: (self fullNameFor: oldFileName)
  21342.                         toBe: (self fullNameFor: newFileName) 
  21343. ! !
  21344.  
  21345. !FileDirectory methodsFor: 'dictionary access'!
  21346. includesKey: aString
  21347.     "Answer whether the receiver includes an element of the given name."
  21348.     "Note: aString may designate a file local to this directory, or it may be a full path name. Try both."
  21349.  
  21350.     ^ (StandardFileStream isAFileNamed: pathName, ':', aString) or:
  21351.         [StandardFileStream isAFileNamed: aString]!
  21352. keysDo: nameBlock
  21353.     ^ self fileNames do: nameBlock! !
  21354.  
  21355. !FileDirectory methodsFor: 'file status'!
  21356. close
  21357.     "Close the receiver if it is not already closed."
  21358.  
  21359.     closed ifFalse: [self release]!
  21360. closed
  21361.     "Answer whether the receiver is closed."
  21362.  
  21363.     ^closed!
  21364. open
  21365.     "Open the directory."
  21366.  
  21367.     closed _ false.
  21368. !
  21369. release
  21370.     "Release the receiver. a more forgiving version of close which should
  21371.     always be possible even if close isn't desired or doesn't work."
  21372.  
  21373.     closed _ true! !
  21374.  
  21375. !FileDirectory methodsFor: 'printing'!
  21376. printOn: aStream 
  21377.     "Refer to the comment in Object|printOn:."
  21378.  
  21379.     aStream nextPutAll: 
  21380.         (self closed ifTrue: ['a closed '] ifFalse: ['an open ']).
  21381.     aStream nextPutAll: self class name.
  21382.     aStream nextPutAll: ' on '.
  21383.     pathName printOn: aStream! !
  21384.  
  21385. !FileDirectory methodsFor: 'private'!
  21386. directoryContents
  21387.     "FileDirectory default directoryContents"
  21388.     ^ self class directoryContentsFor: pathName!
  21389. fileClass
  21390.     "Answer the proper subclass of File of which the files in the receiver are 
  21391.     instances."
  21392.  
  21393.     self subclassResponsibility!
  21394. setPathName: pathString
  21395.     pathName _ pathString! !
  21396.  
  21397. !FileDirectory methodsFor: 'file names-old'!
  21398. checkName: aFileName fixErrors: fixing 
  21399.     "Check a string aFileName for validity as a file name. If there are 
  21400.     problems (e.g., illegal length or characters) and fixing is false, create 
  21401.     an error; if there are problems and fixing is true, make the name legal 
  21402.     (usually by truncating and/or tranforming characters) and answer the 
  21403.     new name. Otherwise, answer the name. Default behavior is to shorten
  21404.     to 31 chars. Subclasses can do any kind of checking they want and 
  21405.     answer either the name, or false if no good."
  21406.  
  21407.     aFileName isEmpty
  21408.         ifTrue: [self error: 'file name empty'].
  21409.     aFileName size > 31 ifTrue:
  21410.         [fixing ifTrue: [^ aFileName contractTo: 31]
  21411.                 ifFalse: [self error: 'file name too long']].
  21412.     ^ aFileName!
  21413. checkNameOfFile: aFileName
  21414.     "See FileDirector|checkNameOfFile: aFileName fixErrors: false."
  21415.  
  21416.     ^self checkNameOfFile: aFileName fixErrors: false!
  21417. checkNameOfFile: aFile fixErrors: aBoolean 
  21418.     "See FileDirectory|checkNameOfFile: aFileName fixErrors: aBoolean. The 
  21419.     first argument is the name of the file, aFile."
  21420.  
  21421.     ^self checkName: aFile fileName fixErrors: aBoolean!
  21422. isLegalFileName: aString 
  21423.     "Answer whether aString is a legal file name."
  21424.  
  21425.     ^(self checkName: aString fixErrors: true) = aString! !
  21426. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  21427.  
  21428. FileDirectory class
  21429.     instanceVariableNames: ''!
  21430. FileDirectory class comment:
  21431. 'FileDirectories carry a path name, and are capable of a number of file creation and access functions, relating to the directory, or volume indicated by their path name.  A FileDirectory can be thought of as a Dictionary whose keys are the local names of files in that directory, and whose values are directory "entries".
  21432.  
  21433. A directory "entry" is an array of five items:
  21434.     <name> <creationTime> <modificationTime> <dirFlag> <fileSize>
  21435. See the comment in lookupEntry:... which provides primitive access to this information.'!
  21436.  
  21437. !FileDirectory class methodsFor: 'class initialization'!
  21438. newOnPath: pathName
  21439.     ^ (self activeDirectoryClass new setPathName: pathName) open!
  21440. openSources: sourcesName andChanges: changesName forImage: imageName
  21441.     "Look for the changes file on the image volume, and make the image volume the default directory.  Then look for the sources in the image volume.   Install results in SourceFiles.  2/13/96 sw."
  21442.     | sources changes |
  21443.     self setDefaultDirectoryFrom: imageName.
  21444.     sources _ (DefaultDirectory includesKey: sourcesName)
  21445.         ifTrue: [DefaultDirectory readOnlyFileNamed: sourcesName]
  21446.         ifFalse: [nil].
  21447.     changes _ (DefaultDirectory includesKey: changesName)
  21448.         ifTrue: [DefaultDirectory oldFileNamed: changesName]
  21449.         ifFalse: [nil].
  21450.     SourceFiles _ Array with: sources with: changes!
  21451. setDefaultDirectoryFrom: imageName
  21452.     self activeDirectoryClass convertName: imageName
  21453.         to: [:directory :fileName | DefaultDirectory _ directory]! !
  21454.  
  21455. !FileDirectory class methodsFor: 'documentation'!
  21456. documentation 
  21457.     "Subclasses are expected to implement the following messages which are
  21458.     implemented as self subclassResponsibility unless otherwise noted.
  21459.  
  21460.     file accessing
  21461.         fileClass
  21462.         [optional] rename:newName:
  21463.         [default] checkNameOfFile:
  21464.             (default makes no sense to me; for the abstract anything is okay)
  21465.  
  21466.     file status
  21467.         [optional] flush
  21468.  
  21469.     page accessing
  21470.         [optional] allocate:after:
  21471.         [optional] allocateSN
  21472.         [optional] deallocate:
  21473.         [optional] freePages
  21474.  
  21475.     dictionary adding
  21476.         addNew: 
  21477.  
  21478.     dictionary removing
  21479.         removeOld:
  21480.  
  21481.     dictionary enumerating
  21482.         [optional] next
  21483.         [default] do: 
  21484.         [optional] reset
  21485.  
  21486.     directory accessing
  21487.         [default] versionNumbers
  21488. "! !
  21489.  
  21490. !FileDirectory class methodsFor: 'name service'!
  21491. checkName: fullName fixErrors: flag
  21492.     FileDirectory convertName: fullName
  21493.         to: [:directory :fileName | ^ directory checkName: fileName fixErrors: flag]!
  21494. convertName: fileName to: volAndNameBlock
  21495.     "Convert the fileName to a directory object and a local fileName.  FileName must be of the form: <path><name> where the optional <path> specifies a known directory and <name> is the file name within that directory."
  21496.     | i delim |
  21497.     (fileName includes: (delim_ self pathNameDelimiter))
  21498.         ifFalse: [^ volAndNameBlock
  21499.                     value: DefaultDirectory
  21500.                         value: fileName].
  21501.     i _ fileName findLast: [:c | c = delim].
  21502.     ^ volAndNameBlock
  21503.         value: (self newOnPath: (fileName copyFrom: 1 to: i - 1))
  21504.         value: (fileName copyFrom: i + 1 to: fileName size)!
  21505. default
  21506.     "Answer the default directory."
  21507.  
  21508.     ^ DefaultDirectory!
  21509. fileNamesMatching: pat inVolume: volName folderSuffix: suffix
  21510.     "FileDirectory fileNamesMatching: '*' inVolume: '' "
  21511.     ^ (MacFileDirectory directoryContentsFor: volName)
  21512.         collect: [:spec | (spec at: 4) ifTrue: [spec first , suffix]
  21513.                                 ifFalse: [spec first]]
  21514.         thenSelect: [:fname | pat match: fname]!
  21515. isLegalFileName: fullName
  21516.     FileDirectory convertName: fullName
  21517.         to: [:directory :fileName | ^ directory isLegalFileName: fileName]!
  21518. joinVol: volName toFileName: fileName
  21519.     volName isEmpty ifTrue: [^ fileName].
  21520.     ^ volName , self pathNameDelimiter asString , fileName!
  21521. localNameFor: fullName
  21522.     ^ FileDirectory splitName: fullName
  21523.         to: [:vol :local | ^ local]!
  21524. splitName: fileName to: volAndNameBlock
  21525.     "Take the file name and convert it into a volume name and a fileName.  FileName must be of the form: d:f where the optional d: specifies a known directory and f is the file name within that directory."
  21526.     | delimiter colonIndex realName dirName |
  21527.     delimiter _ self pathNameDelimiter.
  21528.     (colonIndex _ fileName findLast: [:c | c = delimiter]) = 0
  21529.         ifTrue:
  21530.             [dirName _ String new.
  21531.             realName _ fileName ]
  21532.         ifFalse:
  21533.             [dirName _ fileName copyFrom: 1 to: colonIndex - 1.
  21534.             realName _ fileName copyFrom: colonIndex + 1 to: fileName size ].
  21535.  
  21536.     ^ volAndNameBlock value: dirName value: realName! !
  21537.  
  21538. !FileDirectory class methodsFor: 'primitives'!
  21539. activeDirectoryClass
  21540.     FileDirectory subclasses do:
  21541.         [:dirClass | dirClass isActive ifTrue: [^ dirClass]].
  21542.     ^ self halt "No responding subclass"!
  21543. actualPathNameDelimiter
  21544.     "Return the path delimiter for the underlying file system."
  21545.      <primitive: 161>
  21546.     self primitiveFailed.!
  21547. createDirectory: pathString
  21548.     "Create a directory named by the given path. Fail if the path is bad or if a file or directory by that name already exists."
  21549.  
  21550.      <primitive: 160>
  21551.     self primitiveFailed.!
  21552. isActive
  21553.     "Return true if this Directory class is the one we're running"
  21554.     ^ self pathNameDelimiter = self actualPathNameDelimiter!
  21555. lookupEntryIn: pathName index: index
  21556.     "Look up the index-th entry of the directory with the given path (starting from the root of the file hierarchy) and return an array containing:
  21557.  
  21558.     <name> <creationTime> <modificationTime> <dirFlag> <fileSize>
  21559.  
  21560.      The creation and modification times are in seconds since the start of the Smalltalk time epoch. DirFlag is true if the entry is a directory. FileSize the file size in bytes or zero for directories. The primitive returns nil when index is past the end of the directory. It fails if the given pathName is bad."
  21561.  
  21562.      <primitive: 162>
  21563.     self primitiveFailed.!
  21564. pathNameDelimiter
  21565.     ^ $:! !
  21566.  
  21567. !FileDirectory class methodsFor: 'primitive support'!
  21568. dateAndTimeFromSeconds: secondCount
  21569.  
  21570.     ^ Array
  21571.         with: (Time fromSeconds: secondCount \\ 86400)
  21572.         with: (Date fromDays: secondCount // 86400)!
  21573. directoryContentsFor: pathName
  21574.     "FileDirectory directoryContentsFor: ''"
  21575.  
  21576.     | entries index done entry |
  21577.     entries _ OrderedCollection new: 200.
  21578.     index _ 1.
  21579.     done _ false.
  21580.     [done] whileFalse: [
  21581.         entry _ self lookupEntryIn: pathName index: index.
  21582.         entry == nil
  21583.             ifTrue: [ done _ true ]
  21584.             ifFalse: [ entries addLast: entry ].
  21585.         index _ index + 1.
  21586.     ].
  21587.     ^ entries asArray!
  21588. scanTree: rootedPathName
  21589.     "FileDirectory scanTree: 'Reggae:Desktop Folder:New Mail'"
  21590.  
  21591.     | dirs files bytes todo p entries |
  21592.     dirs _ files _ bytes _ 0.
  21593.     todo _ OrderedCollection with: rootedPathName.
  21594.     [todo isEmpty] whileFalse: [
  21595.         p _ todo removeFirst.
  21596.         entries _ self directoryContentsFor: p.
  21597.         entries do: [ :entry |
  21598.             (entry at: 4) ifTrue: [
  21599.                 todo addLast: (p, ':', (entry at: 1)).
  21600.                 dirs _ dirs + 1.
  21601.             ] ifFalse: [
  21602.                 files _ files + 1.
  21603.                 bytes _ bytes + (entry at: 5).
  21604.             ].
  21605.         ].
  21606.     ].
  21607.     ^ Array with: dirs with: files with: bytes
  21608. ! !FileModel subclass: #FileList
  21609.     instanceVariableNames: 'list listIndex directory pattern volList volListIndex sortMode '
  21610.     classVariableNames: ''
  21611.     poolDictionaries: ''
  21612.     category: 'Interface-FileList'!
  21613. FileList comment:
  21614. 'I am a FileModel that can be viewed as a ListMenu as well as the text of a file.'!
  21615.  
  21616. !FileList methodsFor: 'initialization'!
  21617. directory: dir
  21618.     "Set the path of the volume to be displayed."
  21619.     sortMode == nil ifTrue: [sortMode _ #name].
  21620.     self okToChange ifFalse: [^ self].
  21621.     directory _ dir.
  21622.     volList _ (Array with: 'Desk Top') , directory pathParts.
  21623.     self changed: #relabel.
  21624.     self changed: #list.
  21625.     self newListAndPattern: (pattern == nil ifTrue: ['*']
  21626.                                         ifFalse: [pattern]).
  21627. !
  21628. folderString
  21629.     ^ ' [...]'!
  21630. fullName
  21631.     ^ directory fullNameFor: fileName!
  21632. newListAndPattern: aString
  21633.     self okToChange ifFalse: [^ self].
  21634.     pattern _ aString.
  21635.     self newList! !
  21636.  
  21637. !FileList methodsFor: 'list access'!
  21638. fileList
  21639.     "Answer the list of files in the current volume."
  21640.  
  21641.     ^ list!
  21642. fileListIndex
  21643.     "Answer the index of the currently selected file."
  21644.  
  21645.     ^ listIndex!
  21646. list
  21647.     "Answer the list of volumes currently in the path."
  21648.  
  21649.     ^ volList!
  21650. listIndex
  21651.     "Answer the index of the currently selected volume."
  21652.  
  21653.     ^ volListIndex!
  21654. newList
  21655.     "Make the list be those file names which match the pattern."
  21656.     Cursor execute showWhile:
  21657.         [list _ (pattern includes: $*) | (pattern includes: $#)
  21658.             ifTrue: [self listForPattern: pattern]
  21659.             ifFalse: [pattern isEmpty
  21660.                     ifTrue: [self listForPattern: '*']
  21661.                     ifFalse: [self listForPattern: '*', pattern, '*']].
  21662.         listIndex _ 0.
  21663.         volListIndex _ volList size.
  21664.         contents _ ''.
  21665.         self changed: #listIndex.
  21666.         self changed: #fileList]
  21667. !
  21668. toggleFileListIndex: anInteger
  21669.     "Select the file name in the receiver's list whose index is the argument, 
  21670.     anInteger. If the current selection index is already anInteger, deselect it."
  21671.     | item name |
  21672.     listIndex = anInteger
  21673.     ifTrue:
  21674.         [listIndex _ 0.
  21675.         contents _ ''.
  21676.         fileName _ nil]
  21677.     ifFalse: 
  21678.         [listIndex _ anInteger.
  21679.         item _ list at: anInteger.
  21680.         item first = $( ifTrue:  "remove size or date"
  21681.             [item _ item copyFrom: (item indexOf: $)) + 2 to: item size].
  21682.         (item endsWith: self folderString)
  21683.             ifTrue:
  21684.             ["remove [...] folder string and open the folder"
  21685.             name _ item copyFrom: 1 to: item size - self folderString size.
  21686.             listIndex _ 0.
  21687.             ^ self directory: (FileDirectory newOnPath:
  21688.                 (directory fullNameFor: name))]
  21689.             ifFalse:
  21690.             ["open the file selected"
  21691.             self setFileName: item]].
  21692.     self changed: #fileListIndex!
  21693. toggleListIndex: index
  21694.     "Select the volume name in the receiver's list whose index is the argument."
  21695.     | delim name |
  21696.     volListIndex _ index.
  21697.     delim _ directory pathNameDelimiter.
  21698.     name _ volList at: index.
  21699.     self directory: (FileDirectory newOnPath: 
  21700.             (String streamContents: 
  21701.                     [:strm | 2 to: index do:
  21702.                         [:i | strm nextPutAll: (volList at: i).
  21703.                         i < index ifTrue: [strm nextPut: delim]]])).! !
  21704.  
  21705. !FileList methodsFor: 'menu messages'!
  21706. addNewFile
  21707.     "Add a new file and update the list"
  21708.     | newName index |
  21709.     self okToChange ifFalse: [^ self].
  21710.     newName _ (FillInTheBlank request: 'New File Name?'                     initialAnswer: 'FileName') asFileName.
  21711.     (directory newFileNamed: newName) close.
  21712.     self newList.
  21713.     index _ list indexOf: newName ifAbsent: [^0].
  21714.     self toggleFileListIndex: index!
  21715. browseChanges
  21716.     "FileIn all of the currently selected file if any."
  21717.     listIndex = 0 ifTrue: [^ self].
  21718.     super browseChanges!
  21719. copyName
  21720.     listIndex = 0 ifTrue: [^ self].
  21721.     ParagraphEditor new clipboardTextPut: 
  21722.         (FileDirectory default localNameFor: self fullName) asText!
  21723. deleteFile
  21724.     "Delete the currently selected file"
  21725.     listIndex = 0 ifTrue: [^ self].
  21726.     (self confirm: 'Really delete ' , fileName , '?') ifFalse: [^ self].
  21727.     directory deleteFileNamed: fileName.
  21728.     self newList!
  21729. editFile
  21730.     "Open a simple Edit window"
  21731.     listIndex = 0 ifTrue: [^ self].
  21732.     (directory oldFileNamed: fileName) edit!
  21733. fileAllIn
  21734.     "FileIn all of the currently selected file if any."
  21735.     listIndex = 0 ifTrue: [^ self].
  21736.     super fileAllIn!
  21737. renameFile
  21738.     "Rename the currently selected file"
  21739.     | newName index |
  21740.     listIndex = 0 ifTrue: [^ self].
  21741.     self okToChange ifFalse: [^ self].
  21742.     newName _ (FillInTheBlank request: 'NewFileName?'                     initialAnswer: fileName) asFileName.
  21743.     newName = fileName ifTrue: [^ self].
  21744.     directory rename: fileName toBe: newName.
  21745.     self newList.
  21746.     index _ list indexOf: newName ifAbsent: [^0].
  21747.     self toggleFileListIndex: index!
  21748. sortByDate
  21749.     "Resort the list of files"
  21750.     sortMode _ #date.
  21751.     self newListAndPattern:
  21752.         (pattern == nil ifTrue: ['*'] ifFalse: [pattern])!
  21753. sortByName
  21754.     "Resort the list of files"
  21755.     sortMode _ #name.
  21756.     self newListAndPattern:
  21757.         (pattern == nil ifTrue: ['*'] ifFalse: [pattern])!
  21758. sortBySize
  21759.     "Resort the list of files"
  21760.     sortMode _ #size.
  21761.     self newListAndPattern:
  21762.         (pattern == nil ifTrue: ['*'] ifFalse: [pattern])! !
  21763.  
  21764. !FileList methodsFor: 'private'!
  21765. labelString
  21766.     ^ directory pathName contractTo: 50!
  21767. listForPattern: pat
  21768.     "Make the list be those file names which match the pattern."
  21769.     | newList thisName allFiles sizeStr specList maxiPad |
  21770.     specList _ directory directoryContents.
  21771.     sortMode == #size
  21772.         ifTrue: [maxiPad _ (specList inject: 0 into:
  21773.                         [:mx :spec | mx max: (spec at: 5)])
  21774.                             asStringWithCommas size - 1].
  21775.     newList _ sortMode == #name
  21776.         ifTrue: [(SortedCollection new: 30) sortBlock: [:x :y | x <= y]]
  21777.         ifFalse: [(SortedCollection new: 30) sortBlock: [:x :y | x >= y]].
  21778.     allFiles _ pat = '*'.
  21779.     specList do:
  21780.         [:spec | "<name><creationTime><modificationTime><dirFlag><fileSize>"
  21781.         thisName _ (spec at: 4)
  21782.             ifTrue: [spec first , self folderString]
  21783.             ifFalse: [spec first].
  21784.         (allFiles or: [pat match: thisName]) ifTrue:
  21785.             [sortMode == #date
  21786.                 ifTrue: [thisName _ '(' ,
  21787.                         ((Date fromDays: (spec at: 3) // 86400)
  21788.                             printFormat: #(3 2 1 $. 1 1 2)) , ' ' ,
  21789.                         (String streamContents: [:s |
  21790.                             (Time fromSeconds: (spec at: 3) \\ 86400)
  21791.                                 print24: true on: s])
  21792.                         , ') ' , thisName].
  21793.             sortMode == #size
  21794.                 ifTrue: [sizeStr _ (spec at: 5) asStringWithCommas.
  21795.                         thisName _ '(' ,
  21796.                             ((sizeStr size to: maxiPad) collect: [:i | $ ]) ,
  21797.                             sizeStr
  21798.                         , ') ' , thisName].
  21799.             newList add: thisName]].
  21800.     ^ newList!
  21801. put: aString 
  21802.     "Refer to the comment in FileModel|put:."
  21803.  
  21804.     listIndex = 0
  21805.         ifFalse: [super put: aString]!
  21806. readContentsBrief: brevity
  21807.     "Read the contents of the receiver's selected file."
  21808.     listIndex = 0
  21809.         ifTrue: [^'']
  21810.         ifFalse: [^ super readContentsBrief: brevity]! !
  21811. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  21812.  
  21813. FileList class
  21814.     instanceVariableNames: ''!
  21815.  
  21816. !FileList class methodsFor: 'instance creation'!
  21817. open  "FileList open"
  21818.     ^ self openWithEditPane: true!
  21819. openWithEditPane: withEdit  "FileList open"
  21820.     "Open a view of an instance of me on the default directory.   2/14/96 sw: use standard directory.  (6/96 functionality substantially changed by di)
  21821.      7/12/96 sw: set the label to the pathname"
  21822.  
  21823.     | topView aTemplateView fileListView aFileView aFileList aFileTemplateHolder dir volListView |
  21824.     topView _ StandardSystemView new.
  21825.     aFileList _ self new directory: (dir _ FileDirectory default).
  21826.     topView model: aFileList.
  21827.     topView label: dir pathName.
  21828.     topView minimumSize:
  21829.         200 @ (withEdit ifTrue: [200] ifFalse: [60]).
  21830.  
  21831.     volListView _ ListView new.
  21832.     volListView model: aFileList.
  21833.     volListView list: aFileList list.
  21834.     volListView window: (0 @ 0 extent: 80 @ 45).
  21835.     volListView borderWidthLeft: 2 right: 1 top: 2 bottom: 1.
  21836.     topView addSubView: volListView.
  21837.  
  21838.     aFileTemplateHolder _ FileTemplateHolder on: aFileList.
  21839.     aTemplateView _ StringHolderView new.
  21840.     aTemplateView controller: FileTemplateController new.
  21841.     aTemplateView model: aFileTemplateHolder.
  21842.     aTemplateView window: (0 @ 0 extent: 80 @ 15).
  21843.     aTemplateView borderWidthLeft: 2 right: 1 top: 1 bottom: 1.
  21844.     topView addSubView: aTemplateView below: volListView.
  21845.  
  21846.     fileListView _ FileListView new.
  21847.     fileListView model: aFileList.
  21848.     fileListView controller: FileListController new.
  21849.     fileListView list: aFileList fileList.
  21850.     fileListView window: (0 @ 0 extent: 120 @ 60).
  21851.     fileListView borderWidthLeft: 1 right: 2 top: 2 bottom: 1.
  21852.     topView addSubView: fileListView toRightOf: volListView.
  21853.  
  21854.     withEdit ifTrue: [
  21855.     aFileView _ FileView new.
  21856.     aFileView model: aFileList.
  21857.     aFileView window: (0 @ 0 extent: 200 @ 140).
  21858.     aFileView borderWidthLeft: 2 right: 2 top: 1 bottom: 2.
  21859.     topView addSubView: aFileView below: aTemplateView.
  21860.     ].
  21861.  
  21862.     topView controller open!
  21863. openWithoutEditPane  "FileList openWithoutEditPane"
  21864.     ^ self openWithEditPane: false! !BrowserListController subclass: #FileListController
  21865.     instanceVariableNames: ''
  21866.     classVariableNames: 'FileListYellowButtonMessages FileListYellowButtonMenu '
  21867.     poolDictionaries: ''
  21868.     category: 'Interface-FileList'!
  21869.  
  21870. !FileListController methodsFor: 'initialize'!
  21871. initialize
  21872.     super initialize.
  21873.     self yellowButtonMenu: FileListYellowButtonMenu
  21874.         yellowButtonMessages: FileListYellowButtonMessages
  21875. ! !
  21876.  
  21877. !FileListController methodsFor: 'menu messages'!
  21878. addNewFile
  21879.     "FileIn all of the selected file."
  21880.     model isLocked ifTrue: [^view flash].
  21881.     self controlTerminate.
  21882.     model addNewFile.
  21883.     self controlInitialize!
  21884. browseChanges
  21885.     "Browse the selected file in fileIn format."
  21886.     self controlTerminate.
  21887.     model browseChanges.
  21888.     self controlInitialize!
  21889. copyName
  21890.     model copyName.
  21891. !
  21892. deleteFile
  21893.     "FileIn all of the selected file."
  21894.     model isLocked ifTrue: [^view flash].
  21895.     self controlTerminate.
  21896.     model deleteFile.
  21897.     self controlInitialize!
  21898. editFile
  21899.     "FileIn all of the selected file."
  21900.     self controlTerminate.
  21901.     model editFile.
  21902.     self controlInitialize!
  21903. fileInSelection
  21904.     "FileIn all of the selected file."
  21905.     model isLocked ifTrue: [^view flash].
  21906.     self controlTerminate.
  21907.     model fileAllIn.
  21908.     self controlInitialize!
  21909. fileIntoNewChangeSet
  21910.     "File in the selected file into a new change set.  7/12/96 sw"
  21911.  
  21912.     model isLocked ifTrue: [^ view flash].
  21913.  
  21914.     self controlTerminate.
  21915.     model fileIntoNewChangeSet.
  21916.     self controlInitialize!
  21917. imporHyperSqueaktGIF
  21918.     "Import the selected file as a GIF file, into the HyperSqueak picture library.  8/17/96 sw"
  21919.  
  21920.     model isLocked ifTrue: [^ view flash].
  21921.  
  21922.     self controlTerminate.
  21923.     model imporHyperSqueaktGIF.
  21924.     self controlInitialize!
  21925. importGIF
  21926.     "Import the selected file as a GIF file, putting it into the global GIFImports dictionary at a key that is a function of the filename.  7/18/96 sw"
  21927.  
  21928.     model isLocked ifTrue: [^ view flash].
  21929.  
  21930.     self controlTerminate.
  21931.     model importGIF.
  21932.     self controlInitialize!
  21933. loadIntoHyperSqueak
  21934.     "Import the selected file as a HyperSqueak file.  8/12/96 sw"
  21935.  
  21936.     self controlTerminate.
  21937.     model loadIntoHyperSqueak.
  21938.     self controlInitialize!
  21939. renameFile
  21940.     "FileIn all of the selected file."
  21941.     model isLocked ifTrue: [^view flash].
  21942.     self controlTerminate.
  21943.     model renameFile.
  21944.     self controlInitialize!
  21945. sortByDate
  21946.     "Resort the list of files"
  21947.     model isLocked ifTrue: [^view flash].
  21948.     self controlTerminate.
  21949.     model sortByDate.
  21950.     self controlInitialize!
  21951. sortByName
  21952.     "Resort the list of files"
  21953.     model isLocked ifTrue: [^view flash].
  21954.     self controlTerminate.
  21955.     model sortByName.
  21956.     self controlInitialize!
  21957. sortBySize
  21958.     "Resort the list of files"
  21959.     model isLocked ifTrue: [^view flash].
  21960.     self controlTerminate.
  21961.     model sortBySize.
  21962.     self controlInitialize! !
  21963.  
  21964. !FileListController methodsFor: 'private'!
  21965. changeModelSelection: anInteger
  21966.     self controlTerminate.
  21967.     model toggleFileListIndex: anInteger.
  21968.     self controlInitialize! !
  21969. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  21970.  
  21971. FileListController class
  21972.     instanceVariableNames: ''!
  21973.  
  21974. !FileListController class methodsFor: 'class initialization'!
  21975. initialize
  21976.     "Initialize the file list menu.  6/96 di; modified 7/12/96 sw to add the file-into-new-change-set feature"
  21977.  
  21978.     FileListYellowButtonMenu _ PopUpMenu labels:
  21979. 'fileIn
  21980. file into new change set
  21981. import GIF into GIFImports
  21982. import GIF into HyperSqueak
  21983. load HyperSqueak stack
  21984. browse changes
  21985. spawn this file
  21986. sort by name
  21987. sort by size
  21988. sort by date
  21989. copy name
  21990. rename
  21991. delete
  21992. add new file' lines: # (3 5 7 10 ).
  21993.     FileListYellowButtonMessages _ #(fileInSelection fileIntoNewChangeSet importGIF imporHyperSqueaktGIF loadIntoHyperSqueak browseChanges editFile sortByName sortBySize sortByDate copyName renameFile deleteFile addNewFile)
  21994.  
  21995.     "FileListController initialize"! !
  21996.  
  21997. FileListController initialize!
  21998. ListView subclass: #FileListView
  21999.     instanceVariableNames: ''
  22000.     classVariableNames: ''
  22001.     poolDictionaries: ''
  22002.     category: 'Interface-FileList'!
  22003.  
  22004. !FileListView methodsFor: 'as yet unclassified'!
  22005. update: aSymbol 
  22006.     aSymbol = #relabel ifTrue: [^ self].
  22007.     aSymbol == #fileList ifTrue: 
  22008.             [self list: model fileList.
  22009.             self displayView.
  22010.             ^self].
  22011.     aSymbol == #fileListIndex ifTrue: 
  22012.             [self moveSelectionBox: model fileListIndex.
  22013.             ^self]! !StringHolder subclass: #FileModel
  22014.     instanceVariableNames: 'fileName fileGotten '
  22015.     classVariableNames: ''
  22016.     poolDictionaries: ''
  22017.     category: 'Interface-FileList'!
  22018. FileModel comment:
  22019. 'I represent an interface between a File and an editable view of it. As a StringHolder, the string is the contents of the File.'!
  22020.  
  22021. !FileModel methodsFor: 'accessing'!
  22022. browseChanges
  22023.     "Browse the selected file in fileIn format."
  22024.     ChangeList browseFile: self fullName!
  22025. contents
  22026.     "Answer the contents of the file, reading it first if needed."
  22027.  
  22028.     contents _ self readContentsBrief: true.
  22029.     ^ super contents.!
  22030. defaultBackgroundColor
  22031.     ^ #lightMagenta!
  22032. fileAllIn
  22033.     "FileIn all of the contents from the external file"
  22034.     | f |
  22035.     f _ FileStream oldFileNamed: self fullName.
  22036.     f fileIn!
  22037. fileIntoNewChangeSet
  22038.     "FileIn all of the contents from the external file, into a new change set.  7/12/96 sw"
  22039.  
  22040.     ChangeSorter newChangesFromFileStream: (FileStream oldFileNamed: self fullName)!
  22041. fileName
  22042.     "Answer the receiver's file name"
  22043.  
  22044.     ^ fileName!
  22045. fullName
  22046.     ^ fileName!
  22047. imporHyperSqueaktGIF
  22048.     "Import the file into a GIF file, into HyperSqueak. It had better be in the appropriate format, or you'll regret it!!  Places the resulting form into the HyperSqueak picture library, at a key which the short filename up to the first period. 8/17/96 sw
  22049.      9/18/96 sw: handle no-gif-reader and no-HyperSqueak cases with Informers"
  22050.  
  22051.     | aKey anImage hsq gifReader |
  22052.     Smalltalk hyperSqueakPresent ifFalse:
  22053.         [^ self inform: 'Sorry, HyperSqueak is not present in the current system.'].
  22054.     (gifReader _ Smalltalk gifReaderClass) == nil ifTrue: [^ self inform: 'Sorry, there is no GIF reader available in the current system.'].
  22055.     aKey _ self fileName sansPeriodSuffix.
  22056.     anImage _ gifReader imageFrom: (FileStream oldFileNamed: self fullName).
  22057.     (hsq _ Smalltalk at: #SqueakSupport ifAbsent: [nil]) == nil
  22058.         ifFalse:
  22059.             [hsq importPicture: anImage withKey: aKey]!
  22060. importGIF
  22061.     "Import the file into a GIF file. It had better be in the appropriate format, or you'll regret it!!  Places the resulting form into the global dictionary GIFImports, at a key which the short filename up to the first period.  7/18/96 sw
  22062.      9/18/96 sw: fail gracefully if GIF is missing."
  22063.  
  22064.     | aKey anImage gifReader |
  22065.     (gifReader _ Smalltalk gifReaderClass) == nil ifTrue: [^ self inform: 'Sorry, there is no GIF reader available in the current system.'].
  22066.     aKey _ self fileName sansPeriodSuffix.
  22067.     anImage _ gifReader imageFrom: (FileStream oldFileNamed: self fullName).
  22068.     Smalltalk gifImports at: aKey put: anImage!
  22069. loadIntoHyperSqueak
  22070.     "Load the currently-selected file in as a HyperSqueak save-file.  8/12/96 sw"
  22071.  
  22072.     | ff this save |
  22073.     Smalltalk hyperSqueakPresent ifFalse:
  22074.         [^ self inform: 'Sorry, HyperSqueak is not present in the current system.'].
  22075.  
  22076.     ff _ ReferenceStream fileNamed: self fullName.
  22077.     save _ Preferences logUserScripts.
  22078.     Preferences startLoggingUserScripts.  "for incoming buttons"
  22079.     [this _ ff next.
  22080.         this class == SmallInteger ifTrue: ["version number"].
  22081.         this class == Array ifTrue:
  22082.             [(this at: 1) = 'class structure' ifTrue:
  22083.                 ["Verify the shapes of all the classes"
  22084.                 (DataStream incomingObjectsClass  acceptStructures: this) ifFalse:
  22085.                     [^ ff close]]].    "An error occurred"
  22086.         this class name == DataStream incomingObjectsClass name ifTrue:
  22087.             ["My HyperSqueak objects were installed during 'next'"].
  22088.         ff atEnd] whileFalse.         
  22089.     ff close.
  22090.     save ifFalse: [Preferences stopLoggingUserScripts].!
  22091. put: aString 
  22092.     | f |
  22093.     (aString size >= 5 and:
  22094.         [#('File ' '16r0 ') includes: (aString copyFrom: 1 to: 5)])
  22095.         ifTrue: [(PopUpMenu confirm:
  22096. 'Abbreviated and hexadecimal file views
  22097. cannot be meaningfully saved at present.
  22098. Is this REALLY what you want to do?')
  22099.                 ifFalse: [^ self]].
  22100.     f _ FileStream newFileNamed: self fullName.
  22101.     Cursor write showWhile: [f nextPutAll: aString; close].!
  22102. readContentsBrief: brevityFlag
  22103.     "retrieve the contents from the external file unless it is too long"
  22104.     | f size newContents first1000 last1000 |
  22105.     f _ FileStream fileNamed: self fullName. 
  22106.     f == nil ifTrue:
  22107.         [^ 'For some reason, this file cannot be read'].
  22108.     (brevityFlag and: [(size _ f size) > 30000]) ifFalse: 
  22109.         [^ f contentsOfEntireFile].
  22110.  
  22111.     "Don't display long files at first.
  22112.     Composing the paragraph may take a long time."
  22113.     first1000 _ f next: 1000.
  22114.     f position: size - 1000.
  22115.     last1000 _ f next: 1000.
  22116.     f close.
  22117.     ^ 'File ''' , fileName , ''' is ', size printString, ' bytes long.
  22118. You may use the ''get'' command to read the entire file.
  22119.  
  22120. Here are the first 1000 characters:
  22121. --------------------------------
  22122. ' , first1000 , '
  22123.  
  22124. ... and here are the last 1000 characters:
  22125. --------------------------------------
  22126. ' , last1000!
  22127. readContentsHex
  22128.     "retrieve the contents from the external file unless it is too long"
  22129.     | f size data hexData s |
  22130.     f _ FileStream fileNamed: self fullName. 
  22131.     f == nil ifTrue:
  22132.         [^ 'For some reason, this file cannot be read'].
  22133.     (size _ f size) > 10000
  22134.         ifTrue: [data _ f next: 10000. f close]
  22135.         ifFalse: [data _ f contentsOfEntireFile].
  22136.  
  22137.     s _ WriteStream on: (String new: data size*4).
  22138.     0 to: data size-1 by: 16 do:
  22139.         [:loc | s nextPutAll: loc hex; space;
  22140.             nextPut: $(; print: loc; nextPut: $); space; tab.
  22141.         loc+1 to: (loc+16 min: data size) do: [:i | s nextPutAll: (data at: i) hex; space].
  22142.         s cr].
  22143.     hexData _ s contents.
  22144.  
  22145.     size > 10000
  22146.         ifTrue: [^ 'First 10k bytes:
  22147. ------------------
  22148. ' , hexData]
  22149.         ifFalse: [^ hexData].! !
  22150.  
  22151. !FileModel methodsFor: 'private'!
  22152. setFileName: fullFileName
  22153.  
  22154.     fileName _ fullFileName!
  22155. setFileStream: aStream
  22156.  
  22157.     fileName _ aStream file fullName.
  22158.     aStream close.
  22159. ! !
  22160. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  22161.  
  22162. FileModel class
  22163.     instanceVariableNames: ''!
  22164.  
  22165. !FileModel class methodsFor: 'instance creation'!
  22166. fileStream: aFileStream
  22167.     "Answer an instance of me on the argument, aFileStream."
  22168.  
  22169.     ^self new setFileStream: aFileStream!
  22170. open: aFileModel named: aString 
  22171.     "Answer a scheduled view whose model is aFileModel and whose label is aString. "
  22172.  
  22173.     | topView aView |
  22174.     topView _ StandardSystemView new.
  22175.     topView model: aFileModel.
  22176.     topView label: aString.
  22177.     topView minimumSize: 180 @ 120.
  22178.     aView _ FileView new.
  22179.     aView model: aFileModel.
  22180.     aView window: (0 @ 0 extent: 180 @ 120).
  22181.     aView
  22182.         borderWidthLeft: 2
  22183.         right: 2
  22184.         top: 2
  22185.         bottom: 2.
  22186.     topView addSubView: aView.
  22187.     topView controller open! !ExternalStream subclass: #FileStream
  22188.     instanceVariableNames: 'rwmode closed '
  22189.     classVariableNames: ''
  22190.     poolDictionaries: 'FilePool '
  22191.     category: 'System-Files'!
  22192. FileStream comment:
  22193. 'I represent a Stream that accesses a FilePage from a File. One use for my instance is to access larger "virtual Strings" than can be stored contiguously in main memory. I restrict the objects stored and retrieved to be Integers or Characters. An end of file pointer terminates reading; it can be extended by writing past it, or the file can be explicitly truncated.
  22194.     
  22195. To use the file system for most applications, you typically create a FileStream. This is done by sending a message to a FileDirectory (file:, oldFile:, newFile:, rename:newName:) which creates an instance of me. Accesses to the file are then done via my instance.'!
  22196.  
  22197. !FileStream methodsFor: 'accessing'!
  22198. contentsOfEntireFile
  22199.     "Read all of the contents of the receiver."
  22200.  
  22201.     | s binary |
  22202.     self readOnly.
  22203.     binary _ self isBinary.
  22204.     self reset.    "erases knowledge of whether it is binary"
  22205.     binary ifTrue: [self binary].
  22206.     s _ self next: self size.
  22207.     self close.
  22208.     ^s!
  22209. dataContents
  22210.     "Read most of the contents of the receiver."
  22211.     | s |
  22212.     s _ self size < 4000
  22213.         ifTrue: [self next: self size]
  22214.         ifFalse: [self next: 4000].
  22215.     self close.
  22216.     ^s!
  22217. next
  22218.  
  22219.     (position >= readLimit and: [self atEnd])
  22220.         ifTrue: [^nil]
  22221.         ifFalse: [^collection at: (position _ position + 1)]!
  22222. next: anInteger
  22223.  
  22224.     | newCollection howManyRead increment |
  22225.     newCollection _ collection species new: anInteger.
  22226.     howManyRead _ 0.
  22227.     [howManyRead < anInteger] whileTrue:
  22228.         [self atEnd ifTrue:
  22229.             [(howManyRead + 1) to: anInteger do: [:i | newCollection at: i put: (self next)].
  22230.             ^newCollection].
  22231.         increment _ (readLimit - position) min: (anInteger - howManyRead).
  22232.         newCollection replaceFrom: (howManyRead + 1)
  22233.             to: (howManyRead _ howManyRead + increment)
  22234.             with: collection
  22235.             startingAt: (position + 1).
  22236.         position _ position + increment].
  22237.     ^newCollection!
  22238. nextPut: aByte
  22239.     "1/31/96 sw: subclassResponsibility"
  22240.  
  22241.     self subclassResponsibility!
  22242. nextPutAll: aCollection
  22243.     "1/31/96 sw: made subclass responsibility"
  22244.  
  22245.     self subclassResponsibility!
  22246. size
  22247.     "Answer the size of the file in characters.
  22248.      1/31/96 sw: made subclass responsibility"
  22249.  
  22250.     self subclassResponsibility! !
  22251.  
  22252. !FileStream methodsFor: 'testing'!
  22253. atEnd
  22254.     "Answer true if the current position is >= the end of file position.
  22255.      1/31/96 sw: subclassResponsibility"
  22256.  
  22257.     self subclassResponsibility! !
  22258.  
  22259. !FileStream methodsFor: 'positioning'!
  22260. position
  22261.     "Answer the current character position in the file.
  22262.      1/31/96 sw: subclassResponsibility"
  22263.  
  22264.     self subclassResponsibility!
  22265. position: pos
  22266.     "Set the current character position in the file to pos.
  22267.      1/31/96 sw: made subclassResponsibility"
  22268.  
  22269.     self subclassResponsibility!
  22270. reset
  22271.     "Set the current character position to the beginning of the file.
  22272.      1/31/96 sw: subclassResponsibility"
  22273.  
  22274.     self subclassResponsibility!
  22275. setToEnd
  22276.     "Set the current character position to the end of the File. The same as
  22277.     self position: self size.  1/31/96 sw: made subclassResponsibility"
  22278.  
  22279.     self subclassResponsibility!
  22280. skip: n
  22281.     "Set the character position to n characters from the current position.
  22282.     Error if not enough characters left in the file
  22283.     1/31/96 sw: made subclassResponsibility."
  22284.  
  22285.     self subclassResponsibility! !
  22286.  
  22287. !FileStream methodsFor: 'printing'!
  22288. printOn: aStream
  22289.  
  22290.     super printOn: aStream.
  22291.     aStream nextPutAll: ' on '.
  22292.     self file printOn: aStream! !
  22293.  
  22294. !FileStream methodsFor: 'nonhomogeneous positioning'!
  22295. padTo: bsize put: aCharacter 
  22296.     "Refer to the comment in ExternalStream|padTo:put:."
  22297.     | rem |
  22298.     rem _ bsize - (self position \\ bsize).
  22299.     rem = bsize ifTrue: [^ 0].
  22300.     self next: rem put: aCharacter.
  22301.     ^rem! !
  22302.  
  22303. !FileStream methodsFor: 'editing'!
  22304. edit
  22305.     "Create and schedule a FileView of the contents of the receiver. The 
  22306.     label of the view is the name of the receiver."
  22307.  
  22308.     FileModel 
  22309.         open: (FileModel fileStream: self)
  22310.         named: self file fullName! !
  22311.  
  22312. !FileStream methodsFor: 'file accessing'!
  22313. file
  22314.     "Answer the file for the page the receiver is streaming over.
  22315.      1/31/96 sw: made subclass responsibility"
  22316.  
  22317.     self subclassResponsibility!
  22318. localName
  22319.     ^ self class localNameFor: self name!
  22320. name
  22321.     "Answer the name of the file for the page the receiver is streaming over.  1/31/96 sw: made subclassResponsibility"
  22322.  
  22323.     self subclassResponsibility! !
  22324.  
  22325. !FileStream methodsFor: 'file testing'!
  22326. closed
  22327.     "Answer the status of the file--false if open, true otherwise."
  22328.  
  22329.     ^closed!
  22330. writing
  22331.     "Answer whether it is possible to write on the receiver."
  22332.  
  22333.     rwmode == nil
  22334.         ifTrue: 
  22335.             [self readWriteShorten.    "default mode"
  22336.             ^true].
  22337.     ^(rwmode bitAnd: Write) = Write! !
  22338.  
  22339. !FileStream methodsFor: 'file modes'!
  22340. binary
  22341.     "Set the receiver's file to be binary mode.
  22342.      1/31/96 sw: subclassResponsibility"
  22343.  
  22344.     self subclassResponsibility!
  22345. readOnly
  22346.     "Set the receiver's mode so that pages are not flushed and reading stops at 
  22347.     end of file."
  22348.  
  22349.     self setMode: Read!
  22350. readWrite
  22351.     "Set the receiver's mode so that pages are flushed, end of file can be 
  22352.     extended by writing, and closing does not truncate file."
  22353.  
  22354.     self setMode: Read + Write!
  22355. readWriteShorten
  22356.     "Same as readWrite except close truncates file at current position."
  22357.  
  22358.     self setMode: Read + Write + Shorten!
  22359. text
  22360.     "Set the receiver's file to be in text mode.
  22361.      1/31/96 sw: subclassResponsibility"
  22362.  
  22363.     self subclassResponsibility!
  22364. writeShorten
  22365.     "Allow write and shorten the receiver's file upon closing."
  22366.  
  22367.     self setMode: Write + Shorten! !
  22368.  
  22369. !FileStream methodsFor: 'file status'!
  22370. close
  22371.     "Set the receiver's file status to closed."
  22372.  
  22373.     closed
  22374.         ifFalse: 
  22375.             [self writing 
  22376.                 ifTrue: [(rwmode bitAnd: Shorten) = Shorten
  22377.                             ifTrue: [self shorten]
  22378.                             ifFalse: [self flush]].
  22379.             closed _ true.
  22380.             readLimit _ writeLimit _ 0.
  22381.             self file close.
  22382.             FileDirectory removeExternalReference: self]!
  22383. flush
  22384.     "Write the current buffer back onto the file
  22385.     1/31/96 sw: made subclassResponsibility"
  22386.  
  22387.     self subclassResponsibility!
  22388. release
  22389.     "Set the receiver's status to closed, if it is not already, and do not allow
  22390.     any further reading or writing."
  22391.  
  22392.     closed
  22393.         ifFalse: 
  22394.             [closed _ true.
  22395.             readLimit _ writeLimit _ 0.
  22396.             self file release]!
  22397. reopen
  22398.     "Set the receiver's file to be open again, setting the position to its 
  22399.     previous position. Create an error if the file cannot be reopened.
  22400.      1/31/96 sw: subclassResponsibility"
  22401.  
  22402.     self subclassResponsibility! !
  22403.  
  22404. !FileStream methodsFor: 'fileIn/Out'!
  22405. fileIn
  22406.     "Guarantee that the receiver is readOnly before fileIn for efficiency and
  22407.     to eliminate remote sharing conflicts."
  22408.  
  22409.     self readOnly.
  22410.     ^super fileIn! !
  22411.  
  22412. !FileStream methodsFor: 'private'!
  22413. setMode: m
  22414.  
  22415.     rwmode = m 
  22416.         "don't flush if first time or not write mode or continuing write mode"
  22417.         ifFalse: [(rwmode == nil or: [(rwmode bitAnd: Write) = 0 
  22418.                     or: [(m bitAnd: Write) = Write]])
  22419.                     ifTrue: [rwmode _ m]
  22420.                     ifFalse: 
  22421.                         [self flush.
  22422.                         rwmode _ m]]!
  22423. shorten
  22424.     "Normally called by close and not directly by the user.
  22425.     1/31/96 sw: made subclassResponsibility"
  22426.  
  22427.     self subclassResponsibility! !
  22428. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  22429.  
  22430. FileStream class
  22431.     instanceVariableNames: ''!
  22432.  
  22433. !FileStream class methodsFor: 'instance creation'!
  22434. fileNamed: fileName 
  22435.     ^ StandardFileStream fileNamed: (self fullName: fileName)!
  22436. fullName: fileName
  22437.     ^ FileDirectory default fullNameFor: fileName!
  22438. localNameFor: fullName
  22439.     ^ self directoryClass localNameFor: fullName!
  22440. newFileNamed: fileName 
  22441.     ^ StandardFileStream newFileNamed: (self fullName: fileName)!
  22442. oldFileNamed: fileName 
  22443.     ^ StandardFileStream oldFileNamed: (self fullName: fileName)!
  22444. readOnlyFileNamed: fileName 
  22445.     ^ StandardFileStream readOnlyFileNamed: (self fullName: fileName)! !
  22446.  
  22447. !FileStream class methodsFor: 'concrete classes'!
  22448. directoryClass
  22449.     "To be overridden by different file systems"
  22450.     ^ FileDirectory! !StringHolderController subclass: #FileTemplateController
  22451.     instanceVariableNames: ''
  22452.     classVariableNames: 'TemplateMenu TemplateMessages '
  22453.     poolDictionaries: ''
  22454.     category: 'Interface-FileList'!
  22455. FileTemplateController comment:
  22456. 'I am the controller of the upper part of a three-part file directory window. My contents may be edited. When accepted, my contents becomes the template for the list of files in the other parts. The template consists of repetitions of file name/pattern followed by a carriage return character. A file pattern is a sequence of characters including at least one asterisk, $*. A file name is a sequence of characters without any asterisks.'!
  22457.  
  22458. !FileTemplateController methodsFor: 'menu messages'!
  22459. accept
  22460.     model okToChange ifFalse: [^ self].
  22461.     self controlTerminate.
  22462.     super accept.
  22463.     model newListAndPattern: paragraph text string.
  22464.     self controlInitialize! !
  22465.  
  22466. !FileTemplateController methodsFor: 'editing'!
  22467. dispatchOnCharacter: char with: typeAheadStream
  22468.     "Check for CR and cause an ACCEPT"
  22469.  
  22470.     char = Character cr
  22471.         ifTrue: [sensor keyboard.     "gobble cr"
  22472.                 self replaceSelectionWith:
  22473.                     (Text string: typeAheadStream contents
  22474.                         emphasis: emphasisHere).
  22475.                 self accept.
  22476.                 ^ true]
  22477.         ifFalse: [^ super dispatchOnCharacter: char with: typeAheadStream]! !StringHolder subclass: #FileTemplateHolder
  22478.     instanceVariableNames: 'fileList '
  22479.     classVariableNames: ''
  22480.     poolDictionaries: ''
  22481.     category: 'Interface-FileList'!
  22482. FileTemplateHolder comment:
  22483. 'I am a StringHolder that also refers to an instance of FileList. Typically, my contents is the template being edited in an upper pane of a file list window; the instance of FileList is the one whose list appears in the middle pane.'!
  22484.  
  22485. !FileTemplateHolder methodsFor: 'accessing'!
  22486. defaultContents
  22487.  
  22488.     ^'*'!
  22489. newListAndPattern: pattern
  22490.     fileList newListAndPattern: pattern! !
  22491.  
  22492. !FileTemplateHolder methodsFor: 'lock access'!
  22493. isLocked 
  22494.     "Refer to the comment in StringHolder|isLocked."
  22495.  
  22496.     ^fileList isLocked! !
  22497.  
  22498. !FileTemplateHolder methodsFor: 'private'!
  22499. fileList: aFileList
  22500.  
  22501.     fileList _ aFileList! !
  22502. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  22503.  
  22504. FileTemplateHolder class
  22505.     instanceVariableNames: ''!
  22506.  
  22507. !FileTemplateHolder class methodsFor: 'instance creation'!
  22508. on: aFileList 
  22509.     "Create an instance of me on the argument, aFileList."
  22510.  
  22511.     ^self new fileList: aFileList! !StringHolderView subclass: #FileView
  22512.     instanceVariableNames: ''
  22513.     classVariableNames: ''
  22514.     poolDictionaries: ''
  22515.     category: 'Interface-FileList'!
  22516. FileView comment:
  22517. 'I am a StringHolderView of the text contained in a File. FileController is my default controller.'!
  22518.  
  22519. !FileView methodsFor: 'controller access'!
  22520. defaultControllerClass
  22521.  
  22522.     ^FileController! !
  22523.  
  22524. !FileView methodsFor: 'updating'!
  22525. update: aSymbol
  22526.     aSymbol = #relabel
  22527.         ifTrue: [^ self topView relabel: model labelString].
  22528.     ^ super update: aSymbol! !StringHolder subclass: #FillInTheBlank
  22529.     instanceVariableNames: 'actionBlock actionTaken '
  22530.     classVariableNames: ''
  22531.     poolDictionaries: ''
  22532.     category: 'Interface-Menus'!
  22533. FillInTheBlank comment:
  22534. 'I represent a request for information that will be applied as the argument of a block of actions.'!
  22535.  
  22536. !FillInTheBlank methodsFor: 'initialize-release'!
  22537. defaultBackgroundColor
  22538.     ^ #lightBrown!
  22539. initialize 
  22540.     "Refer to the comment in StringHolder|initialize."
  22541.  
  22542.     super initialize.
  22543.     actionTaken _ false! !
  22544.  
  22545. !FillInTheBlank methodsFor: 'accessing'!
  22546. action: aBlock
  22547.     "The argument, aBlock, will be evaluated when the receiver is sent the 
  22548.     message selectAction."
  22549.  
  22550.     actionBlock _ aBlock!
  22551. actionTaken 
  22552.     "Answer whether the receiver has taken its appropriate action(s) yet."
  22553.  
  22554.     ^actionTaken !
  22555. setAction: aBoolean 
  22556.     "Set the receiver's flag denoting whether its action(s) were taken to be 
  22557.     the argument, aBoolean."
  22558.  
  22559.     actionTaken _ aBoolean! !
  22560.  
  22561. !FillInTheBlank methodsFor: 'menu messages'!
  22562. selectAction
  22563.     "Evaluate the receiver's assigned action block, if any, with the answer as 
  22564.     the block argument."
  22565.  
  22566.     actionBlock notNil ifTrue: [actionBlock value: contents]! !
  22567. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  22568.  
  22569. FillInTheBlank class
  22570.     instanceVariableNames: ''!
  22571.  
  22572. !FillInTheBlank class methodsFor: 'instance creation'!
  22573. action: aBlock initialAnswer: aString 
  22574.     "Answer an instance of me whose action is aBlock and initial action 
  22575.     argument is aString."
  22576.  
  22577.     | newBlank |
  22578.     newBlank _ self new initialize.
  22579.     newBlank action: aBlock.
  22580.     newBlank contents: aString.
  22581.     ^newBlank!
  22582. message: messageString displayAt: aPoint centered: centered action: aBlock initialAnswer: aString 
  22583.     "Answer an instance of me whose question is messageString. Once the 
  22584.     user provides an answer, then evaluate aBlock. If centered, a Boolean, is 
  22585.     false, display the view of the instance at aPoint; otherwise display it 
  22586.     with its center at aPoint."
  22587.  
  22588.     | newBlank |
  22589.     newBlank _ self new initialize.
  22590.     newBlank action: aBlock.
  22591.     newBlank contents: aString.
  22592.     FillInTheBlankView
  22593.         openOn: newBlank
  22594.         message: messageString
  22595.         displayAt: aPoint
  22596.         centered: centered!
  22597. request: messageString
  22598.     "Create an instance of me whose question is messageString. Display it 
  22599.     centered around the cursor. Answer whatever the user accepts."
  22600.  
  22601.     ^self request: messageString initialAnswer: ''!
  22602. request: messageString displayAt: aPoint centered: centered action: aBlock initialAnswer: aString 
  22603.     "Answer an instance of me whose question is messageString. Once the user provides an answer, then evaluate aBlock. If centered, aBoolean, is false, display the view of the instance at aPoint; otherwise display it with its center at aPoint. "
  22604.  
  22605.     | newBlank fillInView savedArea |
  22606.     newBlank _ self new initialize.
  22607.     newBlank action: aBlock.
  22608.     newBlank contents: aString.
  22609.     fillInView _ FillInTheBlankView
  22610.                 on: newBlank
  22611.                 message: messageString
  22612.                 displayAt: aPoint
  22613.                 centered: centered.
  22614.     savedArea _ Form fromDisplay: fillInView displayBox.
  22615.     fillInView display.
  22616.     aString isEmpty
  22617.         ifFalse: [fillInView lastSubView controller selectFrom: 1 to: aString size].
  22618.     (fillInView lastSubView containsPoint: Sensor cursorPoint)
  22619.         ifFalse: [fillInView lastSubView controller centerCursorInView].
  22620.     fillInView controller startUp.
  22621.     fillInView release.
  22622.     savedArea displayOn: Display at: fillInView viewport topLeft!
  22623. request: messageString initialAnswer: aString 
  22624.     "Create an instance of me whose question is messageString. Display it 
  22625.     centered around the cursor. Supply aString as an initial answer. Answer 
  22626.     whatever the user accepts."
  22627.  
  22628.     self
  22629.         request: messageString
  22630.         displayAt: Sensor cursorPoint
  22631.         centered: true
  22632.         action: [:response | response]
  22633.         initialAnswer: aString.
  22634.     ^response!
  22635. request: messageString  initialAnswer: aString  avoiding: aRect
  22636.     "Answer an instance of me whose question is messageString. Once the user provides an answer, then evaluate aBlock. If centered, aBoolean, is false, display the view of the instance at aPoint; otherwise display it with its center at aPoint.   
  22637.     2/5/96 sw: This variant tries to avoid obscuring aRect
  22638.     2/6/96 sw: fixed to return the user's response"
  22639.  
  22640.     self request: messageString displayAt: aRect bottomLeft centered: false action: [:response | response] initialAnswer: ''.
  22641.     ^ response! !
  22642.  
  22643. !FillInTheBlank class methodsFor: 'examples'!
  22644. example1
  22645.  
  22646.     FillInTheBlank
  22647.         message: 'What is your name?' 
  22648.         displayAt: Sensor waitButton 
  22649.         centered: true
  22650.         action: [:answer | Transcript cr; show: answer] 
  22651.         initialAnswer: ''
  22652.  
  22653.     "FillInTheBlank example1"!
  22654. example2
  22655.  
  22656.     FillInTheBlank
  22657.         request: 'What is your name?' 
  22658.         displayAt: Sensor waitButton 
  22659.         centered: true
  22660.         action: [:answer | Transcript cr; show: answer] 
  22661.         initialAnswer: 'Your Name'
  22662.  
  22663.     "FillInTheBlank example2"!
  22664. example3
  22665.  
  22666.     ^Text fromUser
  22667.  
  22668.     "FillInTheBlank example3"! !StringHolderController subclass: #FillInTheBlankController
  22669.     instanceVariableNames: ''
  22670.     classVariableNames: ''
  22671.     poolDictionaries: ''
  22672.     category: 'Interface-Menus'!
  22673. FillInTheBlankController comment:
  22674. 'I am a StringHolderController for a FillInTheBlankView. The string is information that the user can type in and edit. Upon issuing the accept command, this information is used by my model in the evaluation of an action block.'!
  22675.  
  22676. !FillInTheBlankController methodsFor: 'basic control sequence'!
  22677. controlTerminate
  22678.  
  22679.     | topController |
  22680.     super controlTerminate.
  22681.     model actionTaken ifFalse: [^self].
  22682.     topController _ view topView controller.
  22683.     topController notNil ifTrue: [topController close].
  22684.     model selectAction! !
  22685.  
  22686. !FillInTheBlankController methodsFor: 'control defaults'!
  22687. isControlActive
  22688.  
  22689.     model actionTaken ifTrue: [^false].
  22690.     ^ true!
  22691. isControlWanted
  22692.  
  22693.     ^ model actionTaken not! !
  22694.  
  22695. !FillInTheBlankController methodsFor: 'menu messages'!
  22696. accept
  22697.  
  22698.     super accept.
  22699.     model setAction: true! !StringHolderView subclass: #FillInTheBlankView
  22700.     instanceVariableNames: ''
  22701.     classVariableNames: ''
  22702.     poolDictionaries: ''
  22703.     category: 'Interface-Menus'!
  22704. FillInTheBlankView comment:
  22705. 'I am a view of a FillInTheBlank. I display a query and an area in which the user can type some information. My instances'' default controller is FillinTheBlankController.'!
  22706.  
  22707. !FillInTheBlankView methodsFor: 'controller access'!
  22708. defaultControllerClass
  22709.  
  22710.     ^FillInTheBlankController! !
  22711. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  22712.  
  22713. FillInTheBlankView class
  22714.     instanceVariableNames: ''!
  22715.  
  22716. !FillInTheBlankView class methodsFor: 'instance creation'!
  22717. on: aFillInTheBlank message: messageString displayAt: originPoint centered: centered 
  22718.     "Answer an instance of me on the model aFillInTheBlank asking the 
  22719.     question messageString. If the argument centered, a Boolean, is false, 
  22720.     display the instance with top left corner at originPoint; otherwise, 
  22721.     display it with its center at originPoint."
  22722.  
  22723.     | topView messageView answerView |
  22724.     messageView _ self buildMessageView: messageString.
  22725.     answerView _ 
  22726.         self buildAnswerView: aFillInTheBlank 
  22727.             frameWidth: messageView window width.
  22728.     answerView controller: CRFillInTheBlankController new.
  22729.     topView _ View new model: aFillInTheBlank.
  22730.     topView controller: ModalController new.
  22731.     topView addSubView: messageView.
  22732.     topView addSubView: answerView below: messageView.
  22733.     topView align: (centered
  22734.             ifTrue: [topView viewport center]
  22735.             ifFalse: [topView viewport topLeft])
  22736.         with: originPoint.
  22737.     topView window: 
  22738.         (0 @ 0 extent: 
  22739.             messageView window width @ 
  22740.             (messageView window height + answerView window height)).
  22741.     topView translateBy:
  22742.         (topView displayBox amountToTranslateWithin: Display boundingBox).
  22743.     ^topView!
  22744. openOn: aFillInTheBlank message: messageString displayAt: originPoint centered: centered
  22745.     "Create and schedule an instance of me that displays aFillInTheBlank 
  22746.     asking the question messageString. If the argument centered, a Boolean, 
  22747.     is false, display the instance with top left corner at originPoint; 
  22748.     otherwise, display it with its center at originPoint. Do not schedule, 
  22749.     rather take control immediately and insist that the user respond."
  22750.  
  22751.     | topView messageView answerView |
  22752.     messageView _ self buildMessageView: messageString.
  22753.     answerView _ 
  22754.         self buildAnswerView: aFillInTheBlank 
  22755.             frameWidth: messageView window width.
  22756.     topView _ StandardSystemView new model: aFillInTheBlank.
  22757.     topView addSubView: messageView.
  22758.     topView addSubView: answerView below: messageView. 
  22759.     topView
  22760.         align: (centered
  22761.                 ifTrue: [topView viewport center]
  22762.                 ifFalse: [topView viewport topLeft])
  22763.         with: originPoint.
  22764.     topView label: 'Type a response'.
  22765.     topView window: 
  22766.         (0@0 extent: messageView window width @ (messageView window height + 40)).
  22767.     topView controller openDisplayAt: originPoint! !
  22768.  
  22769. !FillInTheBlankView class methodsFor: 'private'!
  22770. buildAnswerView: aFillInTheBlank frameWidth: widthInteger
  22771.  
  22772.     | answerView |
  22773.     answerView _ self new model: aFillInTheBlank.
  22774.     answerView window: (0@0 extent: widthInteger @ 40).
  22775.     answerView borderWidth: 2.
  22776.     ^answerView!
  22777. buildMessageView: messageString
  22778.     |  messageView  |
  22779.     messageView _ DisplayTextView new model: messageString asDisplayText.
  22780.     messageView borderWidthLeft: 2 right: 2 top: 2 bottom: 0.
  22781.     messageView controller: NoController new.
  22782.     messageView window: (0@0 extent: (messageView window extent max: 200@30)).
  22783.     messageView centered.
  22784.     ^messageView! !Number variableWordSubclass: #Float
  22785.     instanceVariableNames: ''
  22786.     classVariableNames: 'Fourthpi ExpPCoefficients TanCoefficients RadiansPerDegree SinCoefficients Sqrt2 LnCoefficients ExpQCoefficients Pi Ln2 Twopi Halfpi '
  22787.     poolDictionaries: ''
  22788.     category: 'Numeric-Numbers'!
  22789. Float comment:
  22790. 'My instances represent about 8 or 9 digits of accuracy; their range is between plus and minus 10^32. Some valid examples are:
  22791.     
  22792.     8.0 13.3 0.3 2.5e6 1.27e-30 1.27e-31 -12.987654e12
  22793.     
  22794. Mainly: no embedded blanks, little e for tens power, and a digit on both sides of the decimal point.'!
  22795.  
  22796. !Float methodsFor: 'arithmetic'!
  22797. * aNumber 
  22798.     "Primitive. Answer the result of multiplying the receiver by aNumber.
  22799.     Fail if the argument is not a Float. Essential. See Object documentation
  22800.     whatIsAPrimitive."
  22801.  
  22802.     <primitive: 49>
  22803.     ^self retry: #* coercing: aNumber!
  22804. + aNumber 
  22805.     "Primitive. Answer the sum of the receiver and aNumber. Essential.
  22806.     Fail if the argument is not a Float. See Object documentation
  22807.     whatIsAPrimitive."
  22808.  
  22809.     <primitive: 41>
  22810.     ^self retry: #+ coercing: aNumber!
  22811. - aNumber 
  22812.     "Primitive. Answer the difference between the receiver and aNumber.
  22813.     Fail if the argument is not a Float. Essential. See Object documentation
  22814.     whatIsAPrimitive."
  22815.  
  22816.     <primitive: 42>
  22817.     ^self retry: #- coercing: aNumber!
  22818. / aNumber 
  22819.     "Primitive. Answer the result of dividing receiver by aNumber.
  22820.     Fail if the argument is not a Float. Essential. See Object documentation
  22821.     whatIsAPrimitive."
  22822.  
  22823.     <primitive: 50>
  22824.     aNumber = 0
  22825.         ifTrue: [self error: 'attempt to divide by zero']
  22826.         ifFalse: [^self retry: #/ coercing: aNumber]!
  22827. abs
  22828.     self < 0.0
  22829.         ifTrue: [^ self negated]
  22830.         ifFalse: [^ self]!
  22831. negated
  22832.     "Answer a Number that is the negation of the receiver."
  22833.  
  22834.     ^0.0 - self! !
  22835.  
  22836. !Float methodsFor: 'mathematical functions'!
  22837. arcCos
  22838.     "Answer the angle in radians."
  22839.  
  22840.     ^Halfpi - self arcSin!
  22841. arcSin
  22842.     "Answer the angle in radians."
  22843.  
  22844.     self abs > 1.0 ifTrue: [self error: 'Value out of range'].
  22845.     self abs = 1.0
  22846.         ifTrue: [^Halfpi]
  22847.         ifFalse: [^(self / (1 - (self * self)) sqrt) arcTan]!
  22848. arcTan
  22849.     "Answer the angle in radians."
  22850.  
  22851.     | theta term y eps i |
  22852.     self = 1.0 ifTrue: [^Fourthpi].
  22853.     self = -1.0 ifTrue: [^Fourthpi negated].
  22854.     self * self > 1.0
  22855.         ifTrue: 
  22856.             [theta _ Halfpi.
  22857.             y _ -1.0 / (self * self).
  22858.             term _ -1.0 / self abs]
  22859.         ifFalse: 
  22860.             [theta _ 0.0.
  22861.             y _ 0.0 - (self * self).
  22862.             term _ self abs].
  22863.     i _ 1.
  22864.     eps _ 1.0e-4.
  22865.     [term abs > eps]
  22866.         whileTrue: 
  22867.             [theta _ theta + term.
  22868.             term _ term * y * i asFloat / (i + 2) asFloat.
  22869.             i _ i + 2].
  22870.     ^self sign asFloat * theta!
  22871. cos
  22872.     "Answer the cosine of the receiver in radians."
  22873.  
  22874.     self < 0.0 ifTrue: [^(self + Halfpi) sin].
  22875.     ^(Halfpi - self) sin!
  22876. degreeCos
  22877.     "Answer the sine of the receiver in degrees."
  22878.     ^ self degreesToRadians cos!
  22879. degreeSin
  22880.     "Answer the sine of the receiver in degrees."
  22881.     ^ self degreesToRadians sin!
  22882. exp
  22883.     "See Computer Approximations, pp. 96-104, p. 205 (EXPB 1065)."
  22884.  
  22885.     | a n1 x x2 P Q |
  22886.     self abs > 9212.0
  22887.         ifTrue: ["Float maxVal ln"
  22888.             "1.0 exp"
  22889.             self error: 'exp overflow']
  22890.         ifFalse: 
  22891.             [x _ self / Ln2.
  22892.             n1 _ 2.0 raisedTo: x asInteger.
  22893.             (x _ x - x asInteger) >= 0.5
  22894.                 ifTrue: 
  22895.                     [n1 _ n1 * Sqrt2.
  22896.                     x _ x - 0.5].
  22897.             x2 _ x * x.
  22898.             "compute 2.0 power: x"
  22899.             P _ Q _ 0.0.
  22900.             ExpPCoefficients do: [:a | P _ P * x2 + a].
  22901.             ExpQCoefficients do: [:a | Q _ Q * x2 + a].
  22902.             ^n1 * (Q + (x * P) / (Q - (x * P)))]!
  22903. floorLog: radix 
  22904.     "Quick computation of (self log: radix) floor."
  22905.  
  22906.     | x |
  22907.     self < radix ifTrue: [^0].     "self assumed positive"
  22908.     self < radix squared ifTrue: [^1].
  22909.     x _ 2 * (self floorLog: radix squared).    "binary recursion like ipow"
  22910.     ^x + (self / (radix raisedTo: x) floorLog: radix)!
  22911. ln
  22912.     "See Computer Approximations, pp. 105-111, p. 227 (LOGE 2663)."
  22913.  
  22914.     | expt x x2 n P |
  22915.     self <= 0.0
  22916.         ifTrue: [self error: 'ln not valid for ' , self printString]
  22917.         ifFalse: 
  22918.             [expt _ self exponent.
  22919.             n _ Ln2 * (expt - 0.5).
  22920.             "mantissa between 0.5 and 1.0"
  22921.             x _ self timesTwoPower: 0 - expt.
  22922.             x _ x * Sqrt2.
  22923.             x _ x - 1.0 / (x + 1.0).
  22924.             x2 _ x * x.
  22925.             P _ 0.0.
  22926.             LnCoefficients do: [:a | P _ P * x2 + a].
  22927.             ^n + (x * P)]
  22928.  
  22929.     "2.718284 ln 1.0"!
  22930. log
  22931.     "Answer the base 10 logarithm."
  22932.  
  22933.     ^self ln / 10.0 ln!
  22934. sin
  22935.     "Answer the sine of the receiver in radians."
  22936.  
  22937.     | x x2 sum |
  22938.         "normalize to 0<=self<=(Pi/2)"
  22939.     self < 0.0 ifTrue: [^self negated sin negated].
  22940.     self > Twopi ifTrue: [^(self \\ Twopi) sin].
  22941.     self > Pi ifTrue: [^(self - Pi) sin negated].
  22942.     self > Halfpi ifTrue: [^(Pi - self) sin].
  22943.     sum _ x _ self.
  22944.     x2 _ x * x.
  22945.     SinCoefficients do: [:const | sum _ const * (x _ x * x2) + sum].
  22946.     ^sum!
  22947. sqrt
  22948.     "Answer the square root of the receiver."
  22949.  
  22950.     | guess |
  22951.     self <= 0.0 ifTrue: [self = 0.0
  22952.             ifTrue: [^0.0]
  22953.             ifFalse: [^self error: 'sqrt invalid for x < 0']].
  22954.     "copy and halve the exponent for first guess"
  22955.     guess _ self timesTwoPower: 0 - (self exponent // 2).
  22956.     5 timesRepeat: [guess _ self - (guess * guess) / (guess * 2.0) + guess].
  22957.     ^guess!
  22958. tan
  22959.     "Answer the ratio of the sine to cosine of the receiver in radians."
  22960.  
  22961.     | x x2 sum |
  22962.         "normalize to 0<=self<=(Pi/4)"
  22963.     self < 0.0 ifTrue: [^self negated tan negated].
  22964.     self > Pi ifTrue: [^(self \\ Pi) tan].
  22965.     self > Halfpi ifTrue: [^(Pi - self) tan negated].
  22966.     self > Fourthpi ifTrue: [^1.0 / (Halfpi - self) tan].
  22967.     sum _ x _ self.
  22968.     x2 _ x * x.
  22969.     TanCoefficients do: [:const | sum _ const * (x _ x * x2) + sum].
  22970.     ^sum! !
  22971.  
  22972. !Float methodsFor: 'comparing'!
  22973. < aNumber 
  22974.     "Primitive. Compare the receiver with the argument and return true
  22975.     if the receiver is less than the argument. Otherwise return false.
  22976.     Fail if the argument is not a Float. Essential. See Object documentation
  22977.     whatIsAPrimitive."
  22978.  
  22979.     <primitive: 43>
  22980.     ^self retry: #< coercing: aNumber!
  22981. <= aNumber 
  22982.     "Primitive. Compare the receiver with the argument and return true
  22983.     if the receiver is less than or equal to the argument. Otherwise return
  22984.     false. Fail if the argument is not a Float. Optional. See Object
  22985.     documentation whatIsAPrimitive."
  22986.  
  22987.     <primitive: 45>
  22988.     ^self retry: #<= coercing: aNumber!
  22989. = aNumber 
  22990.     "Primitive. Compare the receiver with the argument and return true
  22991.     if the receiver is equal to the argument. Otherwise return false.
  22992.     Fail if the argument is not a Float. Essential. See Object documentation
  22993.     whatIsAPrimitive."
  22994.  
  22995.     <primitive: 47>
  22996.     aNumber isNumber ifFalse: [^ false].
  22997.     ^ self retry: #= coercing: aNumber!
  22998. > aNumber 
  22999.     "Primitive. Compare the receiver with the argument and return true
  23000.     if the receiver is greater than the argument. Otherwise return false.
  23001.     Fail if the argument is not a Float. Essential. See Object documentation
  23002.     whatIsAPrimitive."
  23003.  
  23004.     <primitive: 44>
  23005.     ^self retry: #> coercing: aNumber!
  23006. >= aNumber 
  23007.     "Primitive. Compare the receiver with the argument and return true
  23008.     if the receiver is greater than or equal to the argument. Otherwise return
  23009.     false. Fail if the argument is not a Float. Optional. See Object documentation 
  23010.     whatIsAPrimitive. "
  23011.  
  23012.     <primitive: 46>
  23013.     ^self retry: #>= coercing: aNumber!
  23014. hash
  23015.     "Hash is reimplemented because = is implemented."
  23016.  
  23017.     ^(self basicAt: 1) bitAnd: 16383        "High bits as an Integer"!
  23018. ~= aNumber 
  23019.     "Primitive. Compare the receiver with the argument and return true
  23020.     if the receiver is not equal to the argument. Otherwise return false.
  23021.     Fail if the argument is not a Float. Optional. See Object documentation
  23022.     whatIsAPrimitive."
  23023.  
  23024.     <primitive: 48>
  23025.     ^super ~= aNumber! !
  23026.  
  23027. !Float methodsFor: 'truncation and round off'!
  23028. fractionPart
  23029.     "Primitive. Answer a Float whose value is the difference between the 
  23030.     receiver and the receiver's asInteger value. Optional. See Object 
  23031.     documentation whatIsAPrimitive."
  23032.  
  23033.     <primitive: 52>
  23034.     ^self - self asInteger!
  23035. integerPart
  23036.     "Answer a Float whose value is the receiver's truncated value."
  23037.  
  23038.     ^self - self fractionPart!
  23039. rounded
  23040.     "Answer the integer nearest the receiver."
  23041.  
  23042.     self >= 0.0
  23043.         ifTrue: [^(self + 0.5) truncated]
  23044.         ifFalse: [^(self - 0.5) truncated]!
  23045. truncated
  23046.     "Answer with a SmallInteger equal to the value of the receiver without 
  23047.     its fractional part. The primitive fails if the truncated value cannot be 
  23048.     represented as a SmallInteger. In that case, the code below will compute 
  23049.     a LargeInteger truncated value. Essential. See Object documentation 
  23050.     whatIsAPrimitive. "
  23051.  
  23052.     <primitive: 51>
  23053.     self primitiveFailed! !
  23054.  
  23055. !Float methodsFor: 'coercing'!
  23056. coerce: aNumber 
  23057.     "Refer to the comment in Number|coerce:."
  23058.  
  23059.     ^aNumber asFloat!
  23060. generality 
  23061.     "Refer to the comment in Number|generality."
  23062.  
  23063.     ^80! !
  23064.  
  23065. !Float methodsFor: 'converting'!
  23066. asFloat
  23067.     "Answer the receiver itself."
  23068.  
  23069.     ^self!
  23070. asFraction
  23071.     "Answer a Fraction representing the receiver. This conversion uses the 
  23072.     continued fraction method to approximate a floating point number."
  23073.  
  23074.     | num1 denom1 num2 denom2 int frac newD temp |
  23075.     num1 _ self asInteger.    "The first of two alternating numerators"
  23076.     denom1 _ 1.        "The first of two alternating denominators"
  23077.     num2 _ 1.        "The second numerator"
  23078.     denom2 _ 0.        "The second denominator--will update"
  23079.     int _ num1.        "The integer part of self"
  23080.     frac _ self fractionPart.        "The fractional part of self"
  23081.     [frac = 0]
  23082.         whileFalse: 
  23083.             ["repeat while the fractional part is not zero"
  23084.             newD _ 1.0 / frac.            "Take reciprocal of the fractional part"
  23085.             int _ newD asInteger.        "get the integer part of this"
  23086.             frac _ newD fractionPart.    "and save the fractional part for next time"
  23087.             temp _ num2.                "Get old numerator and save it"
  23088.             num2 _ num1.                "Set second numerator to first"
  23089.             num1 _ num1 * int + temp.    "Update first numerator"
  23090.             temp _ denom2.                "Get old denominator and save it"
  23091.             denom2 _ denom1.            "Set second denominator to first"
  23092.             denom1 _ int * denom1 + temp.        "Update first denominator"
  23093.             10000.0 < denom1
  23094.                 ifTrue: 
  23095.                     ["Is ratio past float precision?  If so, pick which 
  23096.                     of the two ratios to use"
  23097.                     num2 = 0.0 
  23098.                         ifTrue: ["Is second denominator 0?"
  23099.                                 ^Fraction numerator: num1 denominator: denom1].
  23100.                     ^Fraction numerator: num2 denominator: denom2]].
  23101.     "If fractional part is zero, return the first ratio"
  23102.     denom1 = 1
  23103.         ifTrue: ["Am i really an Integer?"
  23104.                 ^num1"Yes, return Integer result"]
  23105.         ifFalse: ["Otherwise return Fraction result"
  23106.                 ^Fraction numerator: num1 denominator: denom1]!
  23107. degreesToRadians
  23108.     "Answer the receiver in radians. Assumes the receiver is in degrees."
  23109.  
  23110.     ^self * RadiansPerDegree!
  23111. radiansToDegrees
  23112.     "Answer the receiver in degrees. Assumes the receiver is in radians."
  23113.  
  23114.     ^self / RadiansPerDegree! !
  23115.  
  23116. !Float methodsFor: 'copying'!
  23117. deepCopy
  23118.  
  23119.     ^self copy!
  23120. shallowCopy
  23121.  
  23122.     ^self + 0.0! !
  23123.  
  23124. !Float methodsFor: 'printing'!
  23125. hex
  23126.     | word nibble |
  23127.     ^ String streamContents:
  23128.         [:strm |
  23129.         1 to: 5 do:
  23130.             [:i | word _ self at: i.
  23131.             1 to: 4 do: 
  23132.                 [:s | nibble _ (word bitShift: -4+s*4) bitAnd: 16rF.
  23133.                 strm nextPut: ('0123456789ABCDEF' at: nibble+1)]]]
  23134. "
  23135. (-2.0 to: 2.0) collect: [:f | f hex]
  23136. "!
  23137. isLiteral
  23138.  
  23139.     ^true!
  23140. printOn: aStream base: base
  23141.     "Estimate significant figures and handle sign." 
  23142.     | digitCount |
  23143.     digitCount _ 2r1.0e23 "23 bits" floorLog: base asFloat.
  23144.     self > 0.0
  23145.         ifTrue: [self absPrintOn: aStream base: base digitCount: digitCount]
  23146.         ifFalse: [self = 0.0 ifTrue: [^ aStream nextPutAll: '0.0'].
  23147.                 aStream nextPutAll: '-'.
  23148.                 self negated absPrintOn: aStream base: base digitCount: digitCount]! !
  23149.  
  23150. !Float methodsFor: 'private'!
  23151. absPrintOn: aStream base: base digitCount: digitCount 
  23152.     "Print me in the given base, using digitCount significant figures."
  23153.     | fuzz x exp q i fBase |
  23154.     fBase _ base asFloat.
  23155.     "x is myself normalized to [1.0, fBase), exp is my exponent"
  23156.     exp _ 
  23157.         self < 1.0
  23158.             ifTrue: [(fBase / self floorLog: fBase) negated]
  23159.             ifFalse: [self floorLog: fBase].
  23160.     x _ self / (fBase raisedTo: exp).
  23161.     fuzz _ fBase raisedTo: 1 - digitCount.
  23162.     "round the last digit to be printed"
  23163.     x _ 0.5 * fuzz + x.
  23164.     x >= fBase
  23165.         ifTrue: 
  23166.             ["check if rounding has unnormalized x"
  23167.             x _ x / fBase.
  23168.             exp _ exp + 1].
  23169.     (exp < 6 and: [exp > -4])
  23170.         ifTrue: 
  23171.             ["decimal notation"
  23172.             q _ 0.
  23173.             exp < 0 ifTrue: [1 to: 1 - exp do: [:i | aStream nextPut: ('0.0000' at: i)]]]
  23174.         ifFalse: 
  23175.             ["scientific notation"
  23176.             q _ exp.
  23177.             exp _ 0].
  23178.     [x >= fuzz]
  23179.         whileTrue: 
  23180.             ["use fuzz to track significance"
  23181.             i _ x asInteger.
  23182.             aStream nextPut: (Character digitValue: i).
  23183.             x _ x - i * fBase.
  23184.             fuzz _ fuzz * fBase.
  23185.             exp _ exp - 1.
  23186.             exp = -1 ifTrue: [aStream nextPut: $.]].
  23187.     [exp >= -1]
  23188.         whileTrue: 
  23189.             [aStream nextPut: $0.
  23190.             exp _ exp - 1.
  23191.             exp = -1 ifTrue: [aStream nextPut: $.]].
  23192.     q ~= 0
  23193.         ifTrue: 
  23194.             [aStream nextPut: $e.
  23195.             q printOn: aStream]!
  23196. exponent
  23197.     "Primitive. Consider the receiver to be represented as a power of two
  23198.     multiplied by a mantissa (between one and two). Answer with the
  23199.     SmallInteger to whose power two is raised. Optional. See Object
  23200.     documentation whatIsAPrimitive."
  23201.  
  23202.     | positive |
  23203.     <primitive: 53>
  23204.     self >= 1.0 ifTrue: [^self floorLog: 2].
  23205.     self > 0.0
  23206.         ifTrue: 
  23207.             [positive _ (1.0 / self) exponent.
  23208.             self = (1.0 / (1.0 timesTwoPower: positive))
  23209.                 ifTrue: [^positive negated]
  23210.                 ifFalse: [^positive negated - 1]].
  23211.     self = 0.0 ifTrue: [^-1].
  23212.     ^self negated exponent!
  23213. timesTwoPower: anInteger 
  23214.     "Primitive. Answer with the receiver mulitplied by 2.0 raised to the
  23215.     power of the argument. Optional. See Object documentation
  23216.     whatIsAPrimitive."
  23217.  
  23218.     <primitive: 54>
  23219.     ^self * (2.0 raisedToInteger: anInteger)! !
  23220. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  23221.  
  23222. Float class
  23223.     instanceVariableNames: ''!
  23224.  
  23225. !Float class methodsFor: 'class initialization'!
  23226. initialize        "Float initialize. Float pi"
  23227.     "Constants from Computer Approximations, pp. 182-183:
  23228.         Pi = 3.14159265358979323846264338327950288 
  23229.         Pi/2 = 1.57079632679489661923132169163975144 
  23230.         Pi/4 = 0.78539816339744830961566084581987572 
  23231.         Pi*2 = 6.28318530717958647692528676655900576 
  23232.         Pi/180 = 0.01745329251994329576923690768488612 
  23233.         2.0 ln = 0.69314718055994530941723212145817657 
  23234.         2.0 sqrt = 1.41421356237309504880168872420969808"
  23235.  
  23236.     Pi _ 3.14159265.
  23237.     Halfpi _ Pi / 2.0.
  23238.     Fourthpi _ Pi / 4.0.
  23239.     Twopi _ Pi * 2.0.
  23240.     RadiansPerDegree _ Pi / 180.0.
  23241.     Ln2 _ 0.69314718.
  23242.     Sqrt2 _ 1.41421356.
  23243.     SinCoefficients _ #(-0.166667 0.00833333 -1.98409e-4 2.7526e-6 -2.39e-8 ).
  23244.     TanCoefficients _ #(0.333331 0.133392 0.0533741 0.0245651 0.00290052 0.00951681 ).
  23245.     ExpPCoefficients _ #(28.8756 2525.04 ).
  23246.     ExpQCoefficients _ #(1.0 375.022 7285.73 ).
  23247.     LnCoefficients _ #(0.237625 0.285254 0.400006 0.666667 2.0 )! !
  23248.  
  23249. !Float class methodsFor: 'instance creation'!
  23250. readFrom: aStream 
  23251.     "Answer a new Float as described on the stream, aStream."
  23252.  
  23253.     ^(super readFrom: aStream) asFloat! !
  23254.  
  23255. !Float class methodsFor: 'constants'!
  23256. pi
  23257.     "Answer the constant, Pi."
  23258.  
  23259.     ^Pi! !
  23260.  
  23261. Float initialize!
  23262. WaveTableSound subclass: #FMSound
  23263.     instanceVariableNames: 'initialModulation modulation modulationDecay offsetIncrement offsetIndex '
  23264.     classVariableNames: ''
  23265.     poolDictionaries: ''
  23266.     category: 'Sound'!
  23267.  
  23268. !FMSound methodsFor: 'initialization'!
  23269. setPitch: p dur: d loudness: l
  23270.  
  23271.     super setPitch: p dur: d loudness: l.
  23272.     self modulation: 900 multiplier: 0.76.
  23273.     self modulationDecay: 0.92.
  23274.     self decayRate: 0.85.
  23275.  
  23276. ! !
  23277.  
  23278. !FMSound methodsFor: 'accessing'!
  23279. modulation: mod multiplier: mult
  23280.  
  23281.     | modInRange multInRange |
  23282.     modInRange _ mod rounded min: 1023 max: 0.
  23283.     multInRange _ mult asFloat max: 0.0.
  23284.     initialModulation _ (modInRange * increment) bitShift: -7.
  23285.     modulation _ initialModulation.
  23286.     offsetIncrement _ (increment * multInRange) rounded.
  23287.     offsetIndex _ 1.
  23288. !
  23289. modulationDecay: modDecay
  23290.  
  23291.     modulationDecay _ modDecay asFloat min: 1.0 max: 0.0.
  23292. ! !
  23293.  
  23294. !FMSound methodsFor: 'sound generation'!
  23295. doControl
  23296.  
  23297.     super doControl.
  23298.     modulationDecay ~= 1.0 ifTrue: [
  23299.         modulation _ (modulationDecay * modulation asFloat) asInteger.
  23300.     ].
  23301. !
  23302. mixSampleCount: n into: aSoundBuffer startingAt: startIndex pan: pan
  23303.     "A simple implementation of Chowning's frequency-modulation synthesis technique. The center frequency is varied as the sound plays by changing the increment by which to step through the wave table."
  23304.     "FMSound majorScale play"
  23305.     "(FMSound pitch: 440.0 dur: 1.0 loudness: 200) play"
  23306.  
  23307.     | lastIndex i mySample sample channelIndex |
  23308.     <primitive: 177>
  23309.     self var: #aSoundBuffer declareC: 'short int *aSoundBuffer'.
  23310.     self var: #waveTable declareC: 'short int *waveTable'.
  23311.  
  23312.     lastIndex _ (startIndex + n) - 1.
  23313.     startIndex to: lastIndex do: [ :i |
  23314.         mySample _ (amplitude * (waveTable at: index)) // 1000.
  23315.         pan > 0 ifTrue: [
  23316.             channelIndex _ 2 * i.
  23317.             sample _ (aSoundBuffer at: channelIndex) + ((mySample * pan) // 1000).
  23318.             sample >  32767 ifTrue: [ sample _  32767 ].  "clipping!!"
  23319.             sample < -32767 ifTrue: [ sample _ -32767 ].  "clipping!!"
  23320.             aSoundBuffer at: channelIndex put: sample.
  23321.         ].
  23322.         pan < 1000 ifTrue: [
  23323.             channelIndex _ (2 * i) - 1.
  23324.             sample _ (aSoundBuffer at: channelIndex) + ((mySample * (1000 - pan)) // 1000).
  23325.             sample >  32767 ifTrue: [ sample _  32767 ].  "clipping!!"
  23326.             sample < -32767 ifTrue: [ sample _ -32767 ].  "clipping!!"
  23327.             aSoundBuffer at: channelIndex put: sample.
  23328.         ].
  23329.  
  23330.         index _ index + increment + ((modulation * (waveTable at: offsetIndex)) // 1000000).
  23331.         index > waveTableSize ifTrue: [
  23332.             index _ index - waveTableSize.
  23333.         ].
  23334.         index < 1 ifTrue: [
  23335.             index _ index + waveTableSize.
  23336.         ].
  23337.         offsetIndex _ offsetIndex + offsetIncrement.
  23338.         offsetIndex > waveTableSize ifTrue: [
  23339.             offsetIndex _ offsetIndex - waveTableSize.
  23340.         ].
  23341.     ].
  23342.     count _ count - n.
  23343. !
  23344. reset
  23345.  
  23346.     super reset.
  23347.     modulation _ initialModulation.
  23348. ! !DisplayMedium subclass: #Form
  23349.     instanceVariableNames: 'bits width height depth offset '
  23350.     classVariableNames: ''
  23351.     poolDictionaries: ''
  23352.     category: 'Graphics-Display Objects'!
  23353. Form comment:
  23354. 'A rectangular array of pixels, used for holding images.  All pictures, including character images are Forms.  The depth of a Form is how many bits are used to specify the color at each pixel.  The actual bits are held in a Bitmap, whose internal structure is different at each depth.  Class Color allows you to deal with colors without knowing how they are actually encoded inside a Bitmap.
  23355.       The supported depths (in bits) are 1, 2, 4, 8, 16, and 32.  The number of actual colors at these depths are: 2, 4, 16, 256, 32768, and 16 million.
  23356.     Forms are combined using BitBlt.  See the comment in class BitBlt.  Forms that are have both transparent and opapue areas are MaskedForms.  Forms that repeat many times to fill a large destination are InfiniteForms.
  23357.  
  23358.     colorAt: x@y        Returns the abstract color at this location
  23359.     displayAt: x@y        shows this form on the screen
  23360.     displayOn: aMedium at: x@y    shows this form in a Window, a Form, or other DisplayMedium
  23361.     fillColor: aColor        Set all the pixels to the color.
  23362.     edit        launch an editor to change the bits of this form.
  23363.     pixelValueAt: x@y    The encoded color.  Depends on the depth.
  23364. '!
  23365.  
  23366. !Form methodsFor: 'initialize-release'!
  23367. fromDisplay: aRectangle 
  23368.     "Create a virtual bit map from a user specified rectangular area on the 
  23369.     display screen. Reallocates bitmap only if aRectangle ~= the receiver's 
  23370.     extent."
  23371.  
  23372.     (width = aRectangle width and: [height = aRectangle height])
  23373.         ifFalse: [self setExtent: aRectangle extent depth: depth].
  23374.     self
  23375.         copyBits: (aRectangle origin extent: self extent)
  23376.         from: Display
  23377.         at: 0 @ 0
  23378.         clippingBox: self boundingBox
  23379.         rule: Form over
  23380.         fillColor: nil! !
  23381.  
  23382. !Form methodsFor: 'accessing'!
  23383. extent
  23384.     ^ width @ height!
  23385. form
  23386.     "Answer the receiver's form.  For vanilla Forms, this degenerates to self.  Makes several methods that operate on both Forms and MaskedForms much more straightforward.   6/1/96 sw"
  23387.  
  23388.     ^ self!
  23389. height
  23390.     ^ height!
  23391. offset
  23392.  
  23393.     offset == nil
  23394.         ifTrue: [^0 @ 0]
  23395.         ifFalse: [^offset]!
  23396. offset: aPoint
  23397.  
  23398.     offset _ aPoint!
  23399. size
  23400.     "Answer the number of bits in the receiver's bitmap."
  23401. self halt.  "Should no longer be used -- use bitsSize instead"
  23402.     ^ self bitsSize!
  23403. width
  23404.     ^ width! !
  23405.  
  23406. !Form methodsFor: 'copying'!
  23407. copy: aRect
  23408.      "Return a new form which derives from the portion of the original form delineated by aRect."
  23409.     | newForm |
  23410.     newForm _ Form extent: aRect extent depth: depth.
  23411.     ^ newForm copyBits: aRect from: self at: 0@0
  23412.         clippingBox: newForm boundingBox rule: Form over fillColor: nil!
  23413. deepCopy
  23414.     | newForm |
  23415.     newForm _ self shallowCopy.
  23416.     newForm bits: (bits class new: self bitsSize).
  23417.     newForm copyBits: self boundingBox
  23418.         from: self
  23419.         at: 0 @ 0
  23420.         clippingBox: newForm boundingBox
  23421.         rule: Form over
  23422.         fillColor: nil.
  23423.     ^newForm! !
  23424.  
  23425. !Form methodsFor: 'displaying'!
  23426. copyBits: sourceRect from: sourceForm at: destOrigin clippingBox: clipRect rule: rule fillColor: aForm 
  23427.     "Make up a BitBlt table and copy the bits."
  23428.  
  23429.     (BitBlt 
  23430.         destForm: self
  23431.         sourceForm: sourceForm
  23432.         fillColor: aForm
  23433.         combinationRule: rule
  23434.         destOrigin: destOrigin
  23435.         sourceOrigin: sourceRect origin
  23436.         extent: sourceRect extent
  23437.         clipRect: clipRect) copyBits!
  23438. copyBits: sourceRect from: sourceForm at: destOrigin colorMap: map 
  23439.     "Make up a BitBlt table and copy the bits with the given colorMap."
  23440.     ((BitBlt 
  23441.         destForm: self
  23442.         sourceForm: sourceForm
  23443.         halftoneForm: nil
  23444.         combinationRule: Form over
  23445.         destOrigin: destOrigin
  23446.         sourceOrigin: sourceRect origin
  23447.         extent: sourceRect extent
  23448.         clipRect: self boundingBox) colorMap: map) copyBits!
  23449. displayOffset
  23450.  
  23451. "Answer the offset from the bottom center to the origin (top left corner)."
  23452.  
  23453. ^0@0 - ((width // 2) @ height)!
  23454. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
  23455.  
  23456.     aDisplayMedium copyBits: self boundingBox
  23457.         from: self
  23458.         at: aDisplayPoint + self offset
  23459.         clippingBox: clipRectangle
  23460.         rule: ruleInteger
  23461.         fillColor: aForm!
  23462. displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aForm 
  23463.     "Graphically, it means nothing to scale a Form by floating point values.  
  23464.     Because scales and other display parameters are kept in floating point to 
  23465.     minimize round off errors, we are forced in this routine to round off to the 
  23466.     nearest integer."
  23467.  
  23468.     | absolutePoint scale magnifiedForm |
  23469.     absolutePoint _ displayTransformation applyTo: relativePoint.
  23470.     absolutePoint _ absolutePoint x asInteger @ absolutePoint y asInteger.
  23471.     displayTransformation noScale
  23472.         ifTrue: [magnifiedForm _ self]
  23473.         ifFalse: 
  23474.             [scale _ displayTransformation scale.
  23475.             scale _ scale x rounded @ scale y rounded.
  23476.             (1@1 = scale)
  23477.                     ifTrue: [scale _ nil. magnifiedForm _ self]
  23478.                     ifFalse: [magnifiedForm _ self magnify: self boundingBox by: scale]].
  23479.     magnifiedForm
  23480.         displayOn: aDisplayMedium
  23481.         at: absolutePoint - alignmentPoint
  23482.         clippingBox: clipRectangle
  23483.         rule: ruleInteger
  23484.         fillColor: aForm!
  23485. displayOnPort: port at: location
  23486.     port copyForm: self to: location rule: Form over!
  23487. drawLine: sourceForm from: beginPoint to: endPoint clippingBox: clipRect rule: anInteger fillColor: aForm 
  23488.     "Refer to the comment in 
  23489.     DisplayMedium|drawLine:from:to:clippingBox:rule:mask:." 
  23490.     
  23491.     | dotSetter |
  23492.     "set up an instance of BitBlt for display"
  23493.     dotSetter _ BitBlt
  23494.         destForm: self
  23495.         sourceForm: sourceForm
  23496.         fillColor: aForm
  23497.         combinationRule: anInteger
  23498.         destOrigin: beginPoint
  23499.         sourceOrigin: 0 @ 0
  23500.         extent: sourceForm extent
  23501.         clipRect: clipRect.
  23502.     dotSetter drawFrom: beginPoint to: endPoint! !
  23503.  
  23504. !Form methodsFor: 'display box access'!
  23505. boundingBox
  23506.     ^ Rectangle origin: 0 @ 0
  23507.             corner: width @ height!
  23508. computeBoundingBox
  23509.     ^ Rectangle origin: 0 @ 0
  23510.             corner: width @ height! !
  23511.  
  23512. !Form methodsFor: 'pattern'!
  23513. bitPatternForDepth: suspectedDepth
  23514.     "Only called when a Form is being used as a fillColor.  Use a Pattern or InfiniteForm instead for this purpose.
  23515.     Interpret me as an array of (32/depth) Color pixelValues.  BitBlt aligns the first element of this array with the top scanline of the destinationForm, the second with the second, and so on, cycling through the color array as necessary. 6/18/96 tk"
  23516.  
  23517.     ^ self!
  23518. borderFormOfWidth: borderWidth sharpCorners: sharpen
  23519.     "Smear this form around and then subtract the original to produce
  23520.     an outline.  If sharpen is true, then cause right angles to be outlined
  23521.     by right angles (takes an additional diagonal smears ANDed with both
  23522.     horizontal and vertical smears)."
  23523.     | smearForm bigForm smearPort all cornerForm cornerPort d2 nbrs |
  23524.     depth > 1 ifTrue: [self halt]. "Only meaningful for B/W forms."
  23525.     bigForm _ self deepCopy.
  23526.     all _ bigForm boundingBox.
  23527.     smearForm _ Form extent: self extent.
  23528.     smearPort _ BitBlt toForm: smearForm.
  23529.     sharpen ifTrue:
  23530.         [cornerForm _ Form extent: self extent.
  23531.         cornerPort _ BitBlt toForm: cornerForm].
  23532.     nbrs _ (0@0) fourNeighbors.
  23533.     1 to: borderWidth do:
  23534.         [:i |  "Iterate to get several layers of 'skin'"
  23535.         nbrs do:
  23536.             [:d |  "Smear the self in 4 directions to grow each layer of skin"
  23537.             smearPort copyForm: bigForm to: d rule: Form under].
  23538.         sharpen ifTrue:
  23539.             ["Special treatment to smear sharp corners"
  23540.             nbrs with: ((2 to: 5) collect: [:i2 | nbrs atWrap: i2]) do:
  23541.                 [:d1 :d2 |
  23542.                 "Copy corner points diagonally"
  23543.                 cornerPort copyForm: bigForm to: d1+d2 rule: Form over.
  23544.                 "But only preserve if there were dots on either side"
  23545.                 cornerPort copyForm: bigForm to: d1+d1+d2 rule: Form and.
  23546.                 cornerPort copyForm: bigForm to: d1+d2+d2 rule: Form and.
  23547.                 smearPort copyForm: cornerForm to: 0@0 rule: Form under].
  23548.             ].
  23549.         bigForm copy: all from: 0@0 in: smearForm rule: Form over.
  23550.         ].
  23551.     "Now erase the original shape to obtain the outline"
  23552.     bigForm copy: all from: 0@0 in: self rule: Form erase.
  23553.     ^ bigForm!
  23554. colorAt: aPoint
  23555.     "Return the Color in the pixel at coordinate aPoint.  6/20/96 tk"
  23556.  
  23557.     ^ Color 
  23558.         colorFromPixelValue: 
  23559.             ((BitBlt bitPokerToForm: self) pixelAt: aPoint)
  23560.         depth: depth!
  23561. colorAt: aPoint put: aColor
  23562.     "Store a Color into the pixel at coordinate aPoint.  6/20/96 tk"
  23563.  
  23564.     ^ (BitBlt bitPokerToForm: self)
  23565.         pixelAt: aPoint
  23566.         put: (aColor pixelValueForDepth: depth)
  23567. "
  23568. [Sensor anyButtonPressed] whileFalse:
  23569.     [Display colorAt: Sensor cursorPoint put: Color red]
  23570. "!
  23571. fillFromXColorBlock: colorBlock
  23572.     "Horizontal Gradient Fill.
  23573.     Supply relative x in [0.0 ... 1.0] to colorBlock,
  23574.     and paint each pixel with the color that comes back"
  23575.     | xRel |
  23576.     0 to: width-1 do:
  23577.         [:x |  xRel _ x asFloat / (width-1) asFloat.
  23578.         self fill: (x@0 extent: 1@height) 
  23579.             fillColor: (colorBlock value: xRel)]
  23580. "
  23581. ((Form extent: 100@100 depth: Display depth)
  23582.     fillFromXColorBlock: [:x | Color r: x g: 0.0 b: 0.5]) display
  23583. "!
  23584. fillFromXYColorBlock: colorBlock
  23585.     "General Gradient Fill.
  23586.     Supply relative x and y in [0.0 ... 1.0] to colorBlock,
  23587.     and paint each pixel with the color that comes back"
  23588.     | poker yRel xRel |
  23589.     poker _ BitBlt bitPokerToForm: self.
  23590.     0 to: height-1 do:
  23591.         [:y | yRel _ y asFloat / (height-1) asFloat.
  23592.         0 to: width-1 do:
  23593.             [:x |  xRel _ x asFloat / (width-1) asFloat.
  23594.             poker pixelAt: x@y
  23595.                 put: ((colorBlock value: xRel value: yRel) pixelWordForDepth: depth)]]
  23596. "
  23597.  | d |
  23598. ((Form extent: 100@20 depth: Display depth)
  23599.     fillFromXYColorBlock:
  23600.     [:x :y | d _ 1.0 - (x - 0.5) abs - (y - 0.5) abs.
  23601.     Color r: d g: 0 b: 1.0-d]) display
  23602. "!
  23603. fillFromYColorBlock: colorBlock
  23604.     "Vertical Gradient Fill.
  23605.     Supply relative y in [0.0 ... 1.0] to colorBlock,
  23606.     and paint each pixel with the color that comes back"
  23607.     | yRel |
  23608.     0 to: height-1 do:
  23609.         [:y |  yRel _ y asFloat / (height-1) asFloat.
  23610.         self fill: (0@y extent: width@1) 
  23611.             fillColor: (colorBlock value: yRel)]
  23612. "
  23613. ((Form extent: 100@100 depth: Display depth)
  23614.     fillFromYColorBlock: [:y | Color r: y g: 0.0 b: 0.5]) display
  23615. "!
  23616. fillPeriphery: aHalfTone
  23617.     "Fill any white areas at the periphery of this form with aHalftone."
  23618.     ^ self shapeFill: aHalfTone seedBlock:
  23619.         [:form | form border: form boundingBox width: 1 rule: Form reverse fillColor: nil]!
  23620. findShapeAroundSeedBlock: seedBlock
  23621.     "Build a shape that is black in any region marked by seedBlock. 
  23622.     SeedBlock will be supplied a form, in which to blacken various
  23623.     pixels as 'seeds'.  Then the seeds are smeared until 
  23624.     there is no change in the smear when it fills the region, ie,
  23625.     when smearing hits a black border and thus goes no further."
  23626.     | smearForm previousSmear all count smearPort |
  23627.     depth > 1 ifTrue: [self halt]. "Only meaningful for B/W forms."
  23628.     all _ self boundingBox.
  23629.     smearForm _ Form extent: self extent.
  23630.     smearPort _ BitBlt toForm: smearForm.
  23631.     seedBlock value: smearForm.        "Blacken seeds to be smeared"
  23632.     smearPort copyForm: self to: 0@0 rule: Form erase.  "Clear any in black"
  23633.     previousSmear _ smearForm deepCopy.
  23634.     count _ 1.
  23635.     [count = 10 and:   "check for no change every 10 smears"
  23636.         [count _ 1.
  23637.         previousSmear copy: all from: 0@0 in: smearForm rule: Form reverse.
  23638.         previousSmear isAllWhite]]
  23639.         whileFalse: 
  23640.             [smearPort copyForm: smearForm to: 1@0 rule: Form under.
  23641.             smearPort copyForm: smearForm to: -1@0 rule: Form under.
  23642.             "After horiz smear, trim around the region border"
  23643.             smearPort copyForm: self to: 0@0 rule: Form erase.
  23644.             smearPort copyForm: smearForm to: 0@1 rule: Form under.
  23645.             smearPort copyForm: smearForm to: 0@-1 rule: Form under.
  23646.             "After vert smear, trim around the region border"
  23647.             smearPort copyForm: self to: 0@0 rule: Form erase.
  23648.             count _ count+1.
  23649.             count = 9 ifTrue: "Save penultimate smear for comparison"
  23650.                 [previousSmear copy: all from: 0@0 in: smearForm rule: Form over]].
  23651.     "Now paint the filled region in me with aHalftone"
  23652.     ^ smearForm!
  23653. makeBWForm: foregroundColor
  23654.     "Map this form into a B/W form with 1's in the foreground regions."
  23655.     | bwForm map |
  23656.     bwForm _ Form extent: self extent.
  23657.     map _ self newColorMap.  "All non-foreground go to 0's"
  23658.     map at: (foregroundColor mapIndexForDepth: depth) put: 1.
  23659.     bwForm copyBits: self boundingBox from: self at: 0@0 colorMap: map.
  23660.     ^ bwForm!
  23661. pixelValueAt: aPoint 
  23662.     "Return the raw pixel value at coordinate aPoint.  Depends on the form's depth.  Use colorAt: instead to get a Color.  6/20/96 tk"
  23663.  
  23664.     ^ (BitBlt bitPeekerFromForm: self) pixelAt: aPoint!
  23665. pixelValueAt: aPoint put: pixelValue
  23666.     "Store the pixel value at coordinate aPoint.  Use colorAt:put: instead. 6/20/96 tk"
  23667.  
  23668.     ^ (BitBlt bitPokerToForm: self) pixelAt: aPoint put: pixelValue!
  23669. shapeBorder: aColor width: borderWidth interiorPoint: interiorPoint
  23670.     sharpCorners: sharpen internal: internal
  23671.     "Identify the shape (region of identical color) at interiorPoint,
  23672.     and then add an outline of width=borderWidth and color=aColor.
  23673.     If sharpen is true, then cause right angles to be outlined by
  23674.     right angles.  If internal is true, then produce a border that lies
  23675.     within the identified shape.  Thus one can put an internal border
  23676.     around the whole background, thus effecting a normal border
  23677.     around every other foreground image."
  23678.     | shapeForm borderForm interiorColor |
  23679.     "First identify the shape in question as a B/W form"
  23680.     interiorColor _ Color colorFromPixelValue:
  23681.         (self pixelValueAt: interiorPoint) depth: depth.
  23682.     shapeForm _ (self makeBWForm: interiorColor) reverse
  23683.                 findShapeAroundSeedBlock:
  23684.                     [:form | form pixelValueAt: interiorPoint put: 1].
  23685.     "Reverse the image to grow the outline inward"
  23686.     internal ifTrue: [shapeForm reverse].
  23687.     "Now find the border fo that shape"
  23688.     borderForm _ shapeForm borderFormOfWidth: borderWidth sharpCorners: sharpen.
  23689.     "Finally use that shape as a mask to paint the border with color"
  23690.     self fillShape: borderForm fillColor: aColor!
  23691. shapeFill: aColor interiorPoint: interiorPoint
  23692.     "Identify the shape (region of identical color) at interiorPoint,
  23693.     and then fill that shape with the new color, aColor
  23694.     9/19/96 sw: modified di's original method such that it returns the bwForm, for potential use by the caller"
  23695.  
  23696.     | bwForm map interiorColor |
  23697.     depth = 1 ifTrue:
  23698.         [^ self shapeFill: aColor
  23699.             seedBlock: [:form | form pixelValueAt: interiorPoint put: 1]].
  23700.  
  23701.     "First map this form into a B/W form with 0's in the interior region."
  23702.     interiorColor _ Color colorFromPixelValue:
  23703.         (self pixelValueAt: interiorPoint) depth: depth.
  23704.     bwForm _ self makeBWForm: interiorColor.
  23705.     bwForm reverse.  "Make interior region be 0's"
  23706.  
  23707.     "Now fill the interior region and return that shape"
  23708.     bwForm _ bwForm findShapeAroundSeedBlock:
  23709.                     [:form | form pixelValueAt: interiorPoint put: 1].
  23710.  
  23711.     "Finally use that shape as a mask to flood the region with color"
  23712.     self fillShape: bwForm fillColor: aColor.
  23713.     ^ bwForm!
  23714. shapeFill: aColor seedBlock: seedBlock
  23715.     depth > 1 ifTrue: [self halt]. "Only meaningful for B/W forms."
  23716.     (self findShapeAroundSeedBlock: seedBlock)
  23717.         displayOn: self at: 0@0 clippingBox: self boundingBox
  23718.         rule: Form under fillColor: aColor !
  23719. sumBitsAt: aPoint cellSize: s
  23720.     "Return the number of pixels whose value is 1 (black) in the s-by-s cell whose topLeft is aPoint.  Only meaningful for depth 1 forms."
  23721.     | bp n |
  23722.     n _ 0.
  23723.     bp _ BitBlt bitPeekerFromForm: self.
  23724.     0 to: s-1 do:
  23725.         [:x | 0 to: s-1 do: 
  23726.             [:y | n _ n + (bp pixelAt: aPoint + (x@y))]].
  23727.     ^ n! !
  23728.  
  23729. !Form methodsFor: 'bordering'!
  23730. borderWidth: anInteger 
  23731.     "Set the width of the border for the receiver to be anInteger and paint it 
  23732.     using Form black as the border color."
  23733.  
  23734.     self border: self boundingBox width: anInteger fillColor: Color black!
  23735. borderWidth: anInteger color: aMask
  23736.     "Set the width of the border for the receiver to be anInteger and paint it 
  23737.     using aMask as the border color."
  23738.  
  23739.     self border: self boundingBox width: anInteger fillColor: aMask!
  23740. borderWidth: anInteger fillColor: aMask
  23741.     "Set the width of the border for the receiver to be anInteger and paint it 
  23742.     using aMask as the border color."
  23743.  
  23744.     self border: self boundingBox width: anInteger fillColor: aMask! !
  23745.  
  23746. !Form methodsFor: 'scaling'!
  23747. magnify: aRectangle by: scale 
  23748.     "Answer a Form created as a scaling of the receiver.
  23749.     Scale may be a Float, and may be greater or less than 1.0."
  23750.     | newForm |
  23751.     newForm _ Form extent: (aRectangle extent * scale) truncated depth: depth.
  23752.     (WarpBlt toForm: newForm)
  23753.         sourceForm: self;
  23754.         combinationRule: 3;
  23755.         copyQuad: aRectangle asQuad toRect: newForm boundingBox.
  23756.     ^ newForm
  23757.  
  23758. "Dynamic test...
  23759. [Sensor anyButtonPressed] whileFalse:
  23760.     [(Display magnify: (Sensor cursorPoint extent: 31@41) by: 5@3) display]
  23761. "
  23762. "Scaling test...
  23763. | f cp | f _ Form fromDisplay: (Rectangle originFromUser: 100@100).
  23764. Display restoreAfter: [Sensor waitNoButton.
  23765. [Sensor anyButtonPressed] whileFalse:
  23766.     [cp _ Sensor cursorPoint.
  23767.     (f magnify: f boundingBox by: (cp x asFloat@cp y asFloat)/f extent) display]]
  23768. "!
  23769. shrink: aRectangle by: scale 
  23770.     ^ self magnify: aRectangle by: 1.0/scale! !
  23771.  
  23772. !Form methodsFor: 'editing'!
  23773. bitEdit
  23774.     "Create and schedule a view located in an area designated by the user 
  23775.     that contains a view of the receiver magnified by 8@8 that can be 
  23776.     modified using the Bit Editor. It also contains a view of the original 
  23777.     form."
  23778.  
  23779.     BitEditor openOnForm: self
  23780.  
  23781.     "Note that using direct messages to BitEditor, fixed locations and scales can be created.
  23782.     That is, also try:
  23783.         BitEditor openOnForm: self at: <some point>
  23784.         BitEditor openOnForm: self at: <some point> scale: <some point>"!
  23785. bitEditAt: magnifiedFormLocation scale: scaleFactor 
  23786.     "Create and schedule a view whose top left corner is magnifiedLocation 
  23787.     and that contains a view of the receiver magnified by scaleFactor that 
  23788.     can be modified using the Bit Editor. It also contains a view of the 
  23789.     original form."
  23790.  
  23791.     BitEditor openOnForm: self at: magnifiedFormLocation scale: scaleFactor !
  23792. edit
  23793.     "Start up an instance of the FormEditor on this form. Typically the form 
  23794.     is not visible on the screen. The editor menu is located at the bottom of 
  23795.     the form editing frame. The form is displayed centered in the frame. 
  23796.     YellowButtonMenu accept is used to modify the form to reflect the 
  23797.     changes made on the screen version; cancel restores the original form to 
  23798.     the screen. Note that the changes are clipped to the original size of the 
  23799.     form."
  23800.  
  23801.     FormEditor openOnForm: self! !
  23802.  
  23803. !Form methodsFor: 'image manipulation'!
  23804. cgForPixelValue: pv orNot: not
  23805.     "Return the center of gravity for all pixels of value pv.
  23806.     Note:  If orNot is true, then produce the center of gravity for all pixels
  23807.     that are DIFFERENT from the supplied (background) value"
  23808.     | pixCount weighted xAndY |
  23809.     xAndY _ (Array with: (self xTallyPixelValue: pv orNot: not)
  23810.                     with: (self yTallyPixelValue: pv orNot: not)) collect:
  23811.         [:profile |    "For both x and y profiles..."
  23812.         pixCount _ 0.  weighted _ 0.
  23813.         profile doWithIndex:
  23814.             [:t :i | pixCount _ pixCount + t.
  23815.             weighted _ weighted + (t*i)].
  23816.         pixCount = 0  "Produce average of nPixels weighted by coordinate"
  23817.             ifTrue: [0.0]
  23818.             ifFalse: [weighted asFloat / pixCount asFloat - 1.0]].
  23819.  
  23820.     ^ xAndY first @ xAndY last
  23821. "
  23822. | f cg |
  23823. [Sensor anyButtonPressed] whileFalse:
  23824.     [f _ Form fromDisplay: (Sensor cursorPoint extent: 50@50).
  23825.     cg _ f cgForPixelValue: (Color black pixelValueForDepth: f depth) orNot: false.
  23826.     f displayAt: 0@0.
  23827.     Display fill: (cg extent: 2@2) fillColor: Color red].
  23828.     ScheduledControllers restore
  23829. "!
  23830. convexShapeFill: aMask     "(Form dotOfSize: 20) displayAt: 20@20"
  23831.     "Fill the interior of the outtermost outlined region in the receiver.  The outlined region must not be concave by more than 90 degrees."
  23832.     | destForm tempForm |
  23833.     destForm _ Form extent: self extent.  destForm fillBlack.
  23834.     tempForm _ Form extent: self extent.
  23835.     (0@0) fourNeighbors do:
  23836.         [:dir |  "Smear self in all 4 directions, and AND the result"
  23837.         self displayOn: tempForm at: (0@0) - self offset.
  23838.         tempForm smear: dir distance: (dir dotProduct: tempForm extent).
  23839.         tempForm displayOn: destForm at: 0@0
  23840.             clippingBox: destForm boundingBox
  23841.             rule: Form and fillColor: nil].
  23842.     destForm displayOn: self at: 0@0
  23843.         clippingBox: self boundingBox
  23844.         rule: Form over fillColor: aMask!
  23845. flipBy: direction centerAt: aPoint
  23846.     "Return a copy of the receiver flipped either #vertical or #horizontal."
  23847.     | newForm quad |
  23848.     newForm _ Form extent: self extent depth: depth.
  23849.     quad _ self boundingBox asQuad.
  23850.     quad _ (direction = #vertical ifTrue: [#(2 1 4 3)] ifFalse: [#(4 3 2 1)])
  23851.         collect: [:i | quad at: i].
  23852.     (WarpBlt toForm: newForm)
  23853.         sourceForm: self;
  23854.         combinationRule: 3;
  23855.         copyQuad: quad toRect: newForm boundingBox.
  23856.     newForm offset: (self offset flipBy: direction centerAt: aPoint).
  23857.     ^ newForm
  23858. "
  23859. [Sensor anyButtonPressed] whileFalse:
  23860.     [((Form fromDisplay: (Sensor cursorPoint extent: 130@66))
  23861.             flipBy: #vertical centerAt: 0@0) display]
  23862. "!
  23863. innerPixelRectFor: pv orNot: not
  23864.     "Return a rectangle describing the smallest part of me that includes 
  23865.     all pixels of value pv.
  23866.     Note:  If orNot is true, then produce a copy that includes all pixels
  23867.     that are DIFFERENT from the supplied (background) value"
  23868.  
  23869.     | xTally yTally |
  23870.     xTally _ self xTallyPixelValue: pv orNot: not.
  23871.     yTally _ self yTallyPixelValue: pv orNot: not.
  23872.     ^ ((xTally findFirst: [:t | t>0]) - 1) @ ((yTally findFirst: [:t | t>0]) - 1)
  23873.         corner:
  23874.             (xTally findLast: [:t | t>0])@(yTally findLast: [:t | t>0])!
  23875. opaqueRotationSet: steps rotationCenter: aPoint
  23876.     "CAUTION:  this returns the set in counterclockwise order from north-pointing.  For the HyperSqueak work of 6/96, the assumption is that they come in clockwise order, and so a fudging routine, SqueakSupport.reversedFormSetFrom:, is provided.  Someday this should be cleaned up.
  23877.     8/8/96 sw: this variant has a rotationCenter argument, though at the moment it is not used.  It will come in as nil if there is no special center, in which case the centroid of the form should be used, as it always is in the current implementation."
  23878.  
  23879.     | drawing  back90 flip quad |
  23880.  
  23881.     self flag: #noteToTed.  "This at the moment is the same as what you fixed up a couple of months ago, and does not actually use the rotationCenter part.  8/9/96 sw"
  23882.  
  23883.     drawing _ Array new: steps.
  23884.  
  23885.     steps \\ 4 = 0 ifFalse: ["Can't pull any symmetry tricks, rotate every one"
  23886.         1 to: steps do: [:ind |
  23887.             drawing at: ind put: (self rotateBy: 360 - ((ind-1) * 360 // steps))].
  23888.             ^ drawing].
  23889.     "Do in four sections"
  23890.     quad _ steps // 4.
  23891.     1 to: quad do: [:ind |        "degrees: 360, 330, 300"
  23892.             drawing at: ind put: (self rotateBy: 360 - ((ind-1)*360//steps))].
  23893.     1 to: quad do: [:ind |        "degrees: 270, 240, 210"
  23894.             back90 _ drawing at: ind.
  23895.             drawing at:  ind + quad put: (back90 rotateBy: #left centerAt: back90 center)].
  23896.     1 to: quad + quad do: [:ind |    "the entire second half circle is rotated 180"
  23897.             back90 _ drawing at: ind.
  23898.             flip _ back90 flipBy: #vertical centerAt: back90 center. 
  23899.             drawing at: ind + quad + quad put: (flip flipBy: #horizontal centerAt: flip center)]. 
  23900.  
  23901.     ^ drawing collect: [:elem |
  23902.         elem offset: 0@0. 
  23903.         MaskedForm transparentBorder: elem]!
  23904. pixelCompare: aRect with: otherForm at: otherLoc
  23905.     "Compare the selected bits of this form (those within aRect) against
  23906.     those in a similar rectangle of otherFrom.  Return the sum of the
  23907.     absolute value of the differences of the color values of every pixel.
  23908.     Obviously, this is most useful for rgb (16- or 32-bit) pixels but,
  23909.     in the case of 8-bits or less, this will return the sum of the differing
  23910.     bits of the corresponding pixel values (somewhat less useful)"
  23911.     | pixPerWord temp |
  23912.     pixPerWord _ 32//depth.
  23913.     (aRect left\\pixPerWord = 0 and: [aRect right\\pixPerWord = 0]) ifTrue:
  23914.         ["If word-aligned, use on-the-fly difference"
  23915.         ^ (BitBlt toForm: self) copy: aRect from: otherLoc in: otherForm
  23916.                 fillColor: nil rule: 22].
  23917.     "Otherwise, combine in a word-sized form and then compute difference"
  23918.     temp _ self copy: aRect.
  23919.     temp copy: aRect from: otherLoc in: otherForm rule: 21.
  23920.     ^ (BitBlt toForm: temp) copy: aRect from: otherLoc in: nil
  23921.                 fillColor: (Bitmap with: 0) rule: 22
  23922. "  Dumb example prints zero only when you move over the original rectangle...
  23923.  | f diff | f _ Form fromUser.
  23924. [Sensor anyButtonPressed] whileFalse:
  23925.     [diff _ f pixelCompare: f boundingBox
  23926.         with: Display at: Sensor cursorPoint.
  23927.     diff printString , '        ' displayAt: 0@0]
  23928. "!
  23929. primCountBits
  23930.     "Count the non-zero pixels of this form."
  23931.     ^ (BitBlt toForm: self)
  23932.         fillColor: (Bitmap with: 0);
  23933.         destRect: (0@0 extent: width@height);
  23934.         combinationRule: 22;
  23935.         copyBits!
  23936. rotateBy: deg
  23937.     "Rotate the receiver by the indicated number of degrees."
  23938.     "rot is the destination form, bit enough for any angle."
  23939.     | side rot warp r1 pts p p0 center |
  23940.     side _ 1 + ((width*width) + (height*height)) asFloat sqrt asInteger.
  23941.     rot _ Form extent: side@side depth: self depth.
  23942.     center _ rot extent // 2.
  23943.  
  23944.     "Now compute the sin and cos constants for the rotation angle." 
  23945.     warp _ (WarpBlt toForm: rot)
  23946.         sourceForm: self;
  23947.         combinationRule: Form over.
  23948.     r1 _ rot boundingBox align: center with: self boundingBox center.
  23949.  
  23950.     pts _ r1 asQuad collect:
  23951.         [:pt | p _ pt - r1 center.
  23952.         (r1 center x asFloat + (p x asFloat*deg degreeCos) + (p y asFloat*deg degreeSin)) @
  23953.         (r1 center y asFloat - (p x asFloat*deg degreeSin) + (p y asFloat*deg degreeCos))].
  23954.     warp copyQuad: pts toRect: rot boundingBox.
  23955.     ^ rot
  23956. "
  23957.  | a f |  f _ Form fromDisplay: (0@0 extent: 200@200).  a _ 0.
  23958. [Sensor anyButtonPressed] whileFalse:
  23959.     [((Form fromDisplay: (Sensor cursorPoint extent: 130@66))
  23960.         rotateBy: (a _ a+5)) display].
  23961. f display
  23962. "!
  23963. rotateBy: direction centerAt: aPoint
  23964.     "Return a copy of the receiver rotated either #right or #left"
  23965.     | newForm warp quad |
  23966.     newForm _ Form extent: height@width depth: depth.
  23967.     quad _ self boundingBox asQuad.
  23968.     quad _ (direction = #left ifTrue: [0 to: 3] ifFalse: [2 to: 5])
  23969.         collect: [:i | quad atWrap: i].
  23970.     (WarpBlt toForm: newForm)
  23971.         sourceForm: self;
  23972.         combinationRule: 3;
  23973.         copyQuad: quad toRect: newForm boundingBox.
  23974.     newForm offset: (self offset rotateBy: direction centerAt: aPoint).
  23975.     ^ newForm
  23976. "
  23977. [Sensor anyButtonPressed] whileFalse:
  23978.     [((Form fromDisplay: (Sensor cursorPoint extent: 130@66))
  23979.         rotateBy: #left centerAt: 0@0) display]
  23980. "!
  23981. rotateBy: deg rotationCenter: aPoint
  23982.     "Rotate the receiver by the indicated number of degrees.  This variant gets a rotation center, but in fact ignores the thing -- awaiting someone's doing the right thing.   8/9/96 sw
  23983.     Note that rotationCenter should now be easy to include in the offset of the resulting form -- see <Point> rotateBy: angle about: center.  Could be even faster by sharing the sin, cos inside rotateBy:.  This should really be reversed so that this becomes the workhorse, and rotateBy: calls this with rotationCenter: self boundingBox center.  And while we're at it, why not include scaling?  9/19/96 di "
  23984.  
  23985.     ^ self rotateBy: deg!
  23986. smear: dir distance: dist
  23987.     "Smear any black pixels in this form in the direction dir in Log N steps"
  23988.     | skew bb |
  23989.     bb _ BitBlt destForm: self sourceForm: self fillColor: nil
  23990.         combinationRule: Form under destOrigin: 0@0 sourceOrigin: 0@0
  23991.         extent: self extent clipRect: self boundingBox.
  23992.     skew _ 1.
  23993.     [skew < dist] whileTrue:
  23994.         [bb destOrigin: dir*skew; copyBits.
  23995.         skew _ skew+skew]!
  23996. tallyPixelValues
  23997.     "Return a Bitmap with tallies in it of the number of pixels in this Form
  23998.     that have each of the given values.  Note that several forms may be
  23999.     tallied into the same table by callingtPVInto: with the same table.
  24000.     Also bitmaps of depth 16 or 32 can be tallied into tables of size
  24001.     512, 4096 or 32768 by direct calls with a Bitmap of such size."
  24002.     | tallies pixPerWord |
  24003.     tallies _ Bitmap new: (1 bitShift: (self depth min: 9)).
  24004.     self tallyPixelValuesPrimitive: self boundingBox into: tallies.
  24005.     pixPerWord _ 32//depth.
  24006.     self width\\pixPerWord ~= 0 ifTrue:
  24007.         ["Subtract bogus null-count due to word-boundary."
  24008.         tallies at: 1 put: (tallies at: 1) - (pixPerWord-(self width\\pixPerWord)*self height)].
  24009.     ^ tallies!
  24010. tallyPixelValuesInRect: destRect into: valueTable
  24011.     "Tally the selected pixels of this form into the valueTable, which is
  24012.     a bitmap similar to a color map.  Since the underlying BitBlt function
  24013.     that performs the tally does not do bit-boundary clipping, the
  24014.     tallies for any word-boundary fringes must be subtracted."
  24015.     | fringeTallies pixPerWord |
  24016.     self tallyPixelValuesPrimitive: destRect into: valueTable.
  24017.     pixPerWord _ 32//depth.
  24018.     destRect left\\pixPerWord ~= 0 ifTrue:
  24019.         [fringeTallies _ (self copy:
  24020.             ((destRect left//pixPerWord*pixPerWord)@destRect top extent: pixPerWord@destRect height)) tallyPixelValues.
  24021.         "Extra nulls in the fringeTallies about to be subtracted"
  24022.         valueTable at: 1 put: (valueTable at: 1) + (destRect left\\pixPerWord*destRect height).
  24023.         1 to: fringeTallies size do:
  24024.             [:i | valueTable at: i put: (valueTable at: i) - (fringeTallies at: i)]].
  24025.     destRect right\\pixPerWord ~= 0 ifTrue:
  24026.         [fringeTallies _ (self copy:
  24027.             ((destRect right)@destRect top extent: pixPerWord@destRect height)) tallyPixelValues.
  24028.         "Extra nulls in the fringeTallies about to be subtracted"
  24029.         valueTable at: 1 put: (valueTable at: 1) + ((pixPerWord-(destRect right\\pixPerWord))*destRect height).
  24030.         1 to: fringeTallies size do:
  24031.             [:i | valueTable at: i put: (valueTable at: i) - (fringeTallies at: i)]].
  24032.     ^ valueTable
  24033.  
  24034. "Move a little rectangle around the screen and print its tallies...
  24035. | r tallies nonZero |
  24036. Cursor blank showWhile: [
  24037. [Sensor anyButtonPressed] whileFalse:
  24038.     [r _ Sensor cursorPoint extent: 10@10.
  24039.     Display border: (r expandBy: 2) width: 2 rule: Form reverse fillColor: nil.
  24040.     tallies _ (Display copy: r) tallyPixelValues.
  24041.     nonZero _ (1 to: tallies size) collect: [:i | i -> (tallies at: i)]
  24042.             thenSelect: [:assn | assn value > 0].
  24043.     nonZero printString , '          ' displayAt: 0@0.
  24044.     Display border: (r expandBy: 2) width: 2 rule: Form reverse fillColor: nil]]
  24045. "!
  24046. tallyPixelValuesPrimitive: destRect into: valueTable
  24047.     "Tally the selected pixels of this form into the valueTable, which is
  24048.     a bitmap similar to a color map.  Since the underlying BitBlt function
  24049.     that performs the tally does not do bit-boundary clipping, the
  24050.     tallies for any word-boundary fringes must be subtracted."
  24051.  
  24052.     (BitBlt toForm: self)
  24053.         sourceForm: self;  "src must be given for color map ops"
  24054.         sourceOrigin: 0@0;
  24055.         colorMap: valueTable;
  24056.         combinationRule: 23;
  24057.         destRect: destRect;
  24058.         copyBits.
  24059.     ^ valueTable!
  24060. trimToPixelValue: pv orNot: not
  24061.     "Return the smallest part of me that includes all pixels of value pv.
  24062.     Note:  If orNot is true, then produce a copy that includes all pixels
  24063.     that are DIFFERENT from the supplied (background) value"
  24064.  
  24065.     ^ self copy: (self innerPixelRectFor: pv orNot: not)
  24066. "
  24067. Try this to select all but the background...
  24068. Form fromUser do: [:f |
  24069. (f trimToPixelValue: f peripheralColor orNot: true) display]
  24070.  
  24071. Or this to select whatever is black...
  24072. Form fromUser do: [:f |
  24073. (f trimToPixelValue: (Color black pixelValueForDepth: f depth) orNot: false) display]
  24074. "!
  24075. xTallyPixelValue: pv orNot: not
  24076.     "Return an array of the number of pixels with value pv by x-value.
  24077.     Note that if not is true, then this will tally those different from pv."
  24078.     | cm slice |
  24079.     cm _ self newColorMap.        "Map all colors but pv to zero"
  24080.     not ifTrue: [cm atAllPut: 1].        "... or all but pv to one"
  24081.     cm at: pv+1 put: 1 - (cm at: pv+1).
  24082.     slice _ Form extent: 1@height.
  24083.     ^ (0 to: width-1) collect:
  24084.         [:x |
  24085.         slice copyBits: (x@0 extent: 1@height) from: self at: 0@0
  24086.             colorMap: cm.
  24087.         slice primCountBits]!
  24088. yTallyPixelValue: pv orNot: not
  24089.     "Return an array of the number of pixels with value pv by y-value.
  24090.     Note that if not is true, then this will tally those different from pv."
  24091.     | cm slice |
  24092.     cm _ self newColorMap.        "Map all colors but pv to zero"
  24093.     not ifTrue: [cm atAllPut: 1].        "... or all but pv to one"
  24094.     cm at: pv+1 put: 1 - (cm at: pv+1).
  24095.     slice _ Form extent: width@1.
  24096.     ^ (0 to: height-1) collect:
  24097.         [:y |
  24098.         slice copyBits: (0@y extent: width@1) from: self at: 0@0
  24099.             colorMap: cm.
  24100.         slice primCountBits]! !
  24101.  
  24102. !Form methodsFor: 'fileIn/Out'!
  24103. bigMacPaintOn: stream
  24104.     | wLimit hLimit |
  24105.     width <= height 
  24106.         ifTrue: [wLimit _ 576. hLimit _ 720]
  24107.         ifFalse: [wLimit _ 720.    hLimit _ 576].
  24108.  
  24109.     (width <= wLimit and: [height <= hLimit])
  24110.         ifTrue: [^ self macPaintOn: stream].
  24111.  
  24112.     (width > 576 and: [width <= 720]) ifTrue:        "subdivide along height using 576"
  24113.         [^ self divideOn: stream extent: width@576 restOrigin: 0@576 restName: 'b'].
  24114.     (height > 576 and: [height <= 720]) ifTrue:    "subdivide along width using 576"
  24115.         [^ self divideOn: stream extent: 576@height restOrigin: 576@0 restName: 'a'].
  24116.  
  24117.     width > wLimit ifTrue:    "subdivide along width first"
  24118.         [^ self divideOn: stream extent: wLimit@height restOrigin: wLimit@0 restName: 'a'].
  24119.  
  24120.     "subdivide along height"
  24121.     self divideOn: stream extent: width@hLimit restOrigin: 0@hLimit restName: 'b'.
  24122. !
  24123. bigMacPaintOn: stream label: labelDisplayBox
  24124.     | form |
  24125.     form _ Form extent: (width max: labelDisplayBox width) @ (height + labelDisplayBox height).
  24126.     form copy: (0@0 extent: labelDisplayBox extent)
  24127.         from: labelDisplayBox topLeft
  24128.         in: Display rule: Form over.
  24129.     form copy: (0@labelDisplayBox height extent: self extent)
  24130.         from: 0@0
  24131.         in: self rule: Form over.
  24132.     form bigMacPaintOn: stream!
  24133. divideOn: stream extent: ext restOrigin: restOrigin restName: name
  24134.     "Divide self to fit in MacPaint file along width or height."
  24135.     | form newStream |
  24136.     form _ Form extent: ext.
  24137.     form copy: (0@0 extent: form extent)
  24138.             from: 0@0
  24139.             in: self rule: Form over.
  24140.     form bigMacPaintOn: stream.
  24141.     stream close.
  24142.     form _ Form extent: self extent - restOrigin.
  24143.     form copy: (0@0 extent: form extent)
  24144.             from: restOrigin
  24145.             in: self rule: Form over.
  24146.     newStream _ FileStream fileNamed: stream fileName, name.
  24147.     form bigMacPaintOn: newStream.
  24148.     newStream close.
  24149. !
  24150. macPaintOn: stream
  24151.     "Write the form to the stream in MacPaint format." 
  24152.  
  24153.     | scanLineForm scanLineBits scanLineBitBlt topMargin leftMargin |
  24154.     (width > 576) | (height > 720) ifTrue:
  24155.         [(width <=720 and: [height <= 576]) ifTrue:
  24156.             [^ (self rotateBy: #left centerAt: 0@0) macPaintOn: stream].
  24157.         self error: 'Form too big for MacPaint' ].
  24158.     stream nextPutAll: (ByteArray new: 512).    "The header"
  24159.  
  24160.     "BitBlt wants even # bytes, but Macpaint format wants
  24161.     73 bytes per line, so have to skip -1 after each write."
  24162.     scanLineBits _ ByteArray new: 74.
  24163.     scanLineBits at: 1 put: 71.    "Magic number for un-compressed images"
  24164.     scanLineForm _ Form new.
  24165.     scanLineForm setExtent: 584@1    "8 bits on left for magic number"
  24166.         offset: 0@0
  24167.         bits: scanLineBits.
  24168.     leftMargin _ ((576 - width) / 2) asInteger + 8.
  24169.     scanLineBitBlt _ BitBlt destForm: scanLineForm
  24170.         sourceForm: self
  24171.         fillColor: nil
  24172.         combinationRule: Form over
  24173.         destOrigin: leftMargin@0
  24174.         sourceOrigin: 0@0
  24175.         extent: width@1
  24176.         clipRect: (leftMargin@0 extent: (leftMargin+width)@1).
  24177.  
  24178.     topMargin _ ((720 - height) / 3) asInteger.
  24179.     scanLineBitBlt sourceForm: nil; fillColor: (Color white); copyBits.
  24180.     topMargin timesRepeat:
  24181.         [ stream nextPutAll: scanLineBits; skip: -1 ].
  24182.  
  24183.     scanLineBitBlt sourceForm: self; fillColor: nil; copyBits.
  24184.     0 to: height - 1 do: [ :n |
  24185.         scanLineBitBlt sourceY: n; copyBits.
  24186.         stream nextPutAll: scanLineBits; skip: -1 ].
  24187.  
  24188.     topMargin _ (720 - height - topMargin).
  24189.     scanLineBitBlt sourceForm: nil; fillColor: (Color white); copyBits.
  24190.     topMargin timesRepeat:
  24191.         [ stream nextPutAll: scanLineBits; skip: -1 ].
  24192.  
  24193.     (stream isKindOf: FileStream) ifTrue:
  24194.         [stream setType: 'PNTG' creator: 'MPNT']
  24195.  
  24196.     "To turn some rectangle on the screen into a MacPaint file do:
  24197.     | f |
  24198.     f _ FileStream fileNamed: 'STScreen0'.
  24199.     Form fromUser macPaintOn: f.
  24200.     f close.
  24201.     "!
  24202. macPaintOn: stream label: labelDisplayBox
  24203.     "Write the form to the stream in MacPaint format.
  24204.      NOTE: this implementation is nearly identical to the equally lengthy macPaintOn: method, from which it was derived (by Frank Ludolph, back in 1988, I believe); if we retain these methods, then surely someone should go to the work of merging them so that there's not so much wasted overlalp.  Modified 2/14/96 sw so that non-HFS versions of filestreams can be used also"
  24205.  
  24206.     | scanLineForm scanLineBits scanLineBitBlt topMargin leftMargin labelForm |
  24207.  
  24208.     (width > 576) | (height > (720 - (labelDisplayBox height)))
  24209.         ifTrue: [ self error: 'Form too big for MacPaint' ].
  24210.     stream nextPutAll: (ByteArray new: 512).    "The header"
  24211.  
  24212.     scanLineBits _ ByteArray new: 74.
  24213.     "BitBlt wants even # bytes, but Macpaint format wants
  24214.     73 bytes per line, so have to skip -1 after each write."
  24215.     scanLineBits at: 1 put: 71.    "Magic number for un-compressed images"
  24216.     scanLineForm _ Form new.
  24217.     scanLineForm setExtent: 584@1    "8 bits on left for magic number"
  24218.         offset: 0@0
  24219.         bits: scanLineBits.
  24220.     leftMargin _ ((576 - width) / 2) asInteger + 8.
  24221.     labelForm _ Form fromDisplay: labelDisplayBox.
  24222.     scanLineBitBlt _ BitBlt destForm: scanLineForm
  24223.         sourceForm: labelForm
  24224.         fillColor: nil
  24225.         combinationRule: Form over
  24226.         destOrigin: leftMargin@0
  24227.         sourceOrigin: 0@0
  24228.         extent: (labelDisplayBox width)@1
  24229.         clipRect: (leftMargin@0
  24230.                 extent: (leftMargin+labelDisplayBox width)@1).
  24231.  
  24232.     topMargin _ ((720 - height - (labelDisplayBox height)) / 3) asInteger.
  24233.     scanLineBitBlt sourceForm: nil; fillColor: (Color white); copyBits.
  24234.     topMargin timesRepeat:
  24235.         [ stream nextPutAll: scanLineBits; skip: -1 ].
  24236.  
  24237.     scanLineBitBlt sourceForm: labelForm; fillColor: nil; copyBits.
  24238.     0 to: (labelDisplayBox height) - 1 do: [ :n |
  24239.         scanLineBitBlt sourceY: n; copyBits.
  24240.         stream nextPutAll: scanLineBits; skip: -1 ].
  24241.  
  24242.     scanLineBitBlt _ BitBlt destForm: scanLineForm
  24243.         sourceForm: self
  24244.         halftoneForm: nil
  24245.         combinationRule: Form over
  24246.         destOrigin: leftMargin@0
  24247.         sourceOrigin: 0@0
  24248.         extent: width@1
  24249.         clipRect: (leftMargin@0 extent: (leftMargin+width)@1).
  24250.     0 to: height - 1 do: [ :n |
  24251.         scanLineBitBlt sourceY: n; copyBits.
  24252.         stream nextPutAll: scanLineBits; skip: -1 ].
  24253.  
  24254.     topMargin _ (720 - height - (labelDisplayBox height) - topMargin).
  24255.     scanLineBitBlt sourceForm: nil; fillColor: (Color white); copyBits.
  24256.     topMargin timesRepeat:
  24257.         [ stream nextPutAll: scanLineBits; skip: -1 ].
  24258.  
  24259.     (stream isKindOf: FileStream) ifTrue:
  24260.         [stream setType: 'PNTG' creator: 'MPNT']!
  24261. readFrom: aFile
  24262.     "Reads the receiver from the file in the format:
  24263.         depth, extent, offset, bits."
  24264.     | offsetX offsetY |
  24265.     depth _ aFile next.
  24266.     (depth isPowerOfTwo and: [depth between: 1 and: 32])
  24267.         ifFalse: [self halt  "invalid depth"].
  24268.     width _ aFile nextWord.
  24269.     height _ aFile nextWord.
  24270.     offsetX  _ aFile nextWord.
  24271.     offsetY _ aFile nextWord.
  24272.     offsetX > 32767 ifTrue: [offsetX _ offsetX - 65536].
  24273.     offsetY > 32767 ifTrue: [offsetY _ offsetY - 65536].
  24274.     bits _ Bitmap newFromStream: aFile.
  24275.     bits size = self bitsSize ifFalse: [self halt "incompatible bitmap size"].
  24276.     ^ self!
  24277. readFromOldFile: file
  24278.     "Read a Form in the original ST-80 format"
  24279.     | newForm w h code theBits pos offsetX offsetY |
  24280.     w _ file nextWord.
  24281.     h _ file nextWord.
  24282.     offsetX  _ file nextWord.
  24283.     offsetY _ file nextWord.
  24284.     offsetX > 32767 ifTrue: [offsetX _ offsetX - 65536].
  24285.     offsetY > 32767 ifTrue: [offsetY _ offsetY - 65536].
  24286.     newForm _ Form extent: w @ h offset: offsetX @ offsetY.
  24287.     theBits _ newForm bits.
  24288.     pos _ 0.
  24289. self halt.  "Update this to 32-bit bitmaps"
  24290.     1 to: w + 15 // 16 do:
  24291.         [:j | 
  24292.         1 to: h do:
  24293.             [:i | theBits at: (pos _ pos+1) put: file nextWord]].
  24294.     newForm bits: theBits.
  24295.     file close.
  24296.     ^ newForm!
  24297. writeOn: file
  24298.     "Write the receiver on the file in the format
  24299.         depth, extent, offset, bits."
  24300.     file nextPut: depth.
  24301.     file nextWordPut: width.
  24302.     file nextWordPut: height.
  24303.     file nextWordPut: ((self offset x) >=0
  24304.                     ifTrue: [self offset x]
  24305.                     ifFalse: [self offset x + 65536]).
  24306.     file nextWordPut: ((self offset y) >=0
  24307.                     ifTrue: [self offset y]
  24308.                     ifFalse: [self offset y + 65536]).
  24309.     bits writeOn: file! !
  24310.  
  24311. !Form methodsFor: 'printing'!
  24312. storeOn: aStream
  24313.  
  24314.     self storeOn: aStream base: 10!
  24315. storeOn: aStream base: anInteger 
  24316.     "Store the receiver out in the form: Form newExtent:fromArray:#()offset:"
  24317.  
  24318.     aStream nextPut: $(.
  24319.     aStream nextPutAll: self species name.
  24320.     aStream crtab: 1.
  24321.     aStream nextPutAll: 'extent: '.
  24322.     self extent printOn: aStream.
  24323.     aStream crtab: 1.
  24324.     aStream nextPutAll: 'fromArray: #('.
  24325.     1 to: bits size do: 
  24326.         [:index | 
  24327.         anInteger = 10
  24328.             ifTrue: [aStream space]
  24329.             ifFalse: [aStream crtab: 2].
  24330.         (self bits at: index) printOn: aStream base: anInteger].
  24331.     aStream nextPut: $).
  24332.     aStream crtab: 1.
  24333.     aStream nextPutAll: 'offset: '.
  24334.     self offset printOn: aStream.
  24335.     aStream nextPut: $)! !
  24336.  
  24337. !Form methodsFor: 'private'!
  24338. copy: destRectangle from: sourcePt in: sourceForm rule: rule 
  24339.     "Make up a BitBlt table and copy the bits."
  24340.     (BitBlt toForm: self)
  24341.         copy: destRectangle
  24342.         from: sourcePt in: sourceForm
  24343.         fillColor: nil rule: rule!
  24344. fill: aRectangle rule: anInteger fillColor: aForm 
  24345.     "Replace a rectangular area of the receiver with the pattern described by aForm 
  24346.     according to the rule anInteger."
  24347.     (BitBlt toForm: self)
  24348.         copy: aRectangle
  24349.         from: 0@0 in: nil
  24350.         fillColor: aForm rule: anInteger!
  24351. initFromArray: anArray
  24352.     "Fill the bitmap from anArray.  If the array is shorter,
  24353.     then cycle around in its contents until the bitmap is filled."
  24354.     | ax as |
  24355.     ax _ 0.
  24356.     as _ anArray size.
  24357.     1 to: bits size do:
  24358.         [:index |
  24359.         (ax _ ax + 1) > as ifTrue: [ax _ 1].
  24360.         bits at: index put: (anArray at: ax)]!
  24361. isAllWhite
  24362.     "Answer whether all bits in the receiver are white (=0)."
  24363.  
  24364.     bits do: [:data | data ~= 0 ifTrue: [^false]].
  24365.     ^true!
  24366. setExtent: extent
  24367.     "Create a virtual bit map with the given extent."
  24368.  
  24369.     ^ self setExtent: extent depth: 1!
  24370. setExtent: extent depth: bitsPerPixel
  24371.     "Create a virtual bit map with the given extent and bitsPerPixel."
  24372.  
  24373.     width _ extent x.
  24374.     width < 0 ifTrue: [width _ 0].
  24375.     height _ extent y.
  24376.     height < 0 ifTrue: [height _ 0].
  24377.     depth _ bitsPerPixel.
  24378.     bits _ Bitmap new: self bitsSize!
  24379. setExtent: extent offset: aPoint
  24380.     "Create a virtual bit map with the givcen extent and offset."
  24381.  
  24382.     ^ (self setExtent: extent depth: 1) offset: aPoint!
  24383. setExtent: extent offset: aPoint bits: aBitmap 
  24384.     "Should be rewritten -- most users are obsolete"
  24385.     ^ (self setExtent: extent offset: aPoint) bits: aBitmap 
  24386. !
  24387. spread: rect from: sourceForm by: scale direction: dir
  24388.     | port |
  24389.     port _ BitBlt toForm: self.
  24390.     dir == #horiz
  24391.     ifTrue:
  24392.         [0 to: width-1 do: 
  24393.             [:i |  "slice up original area"
  24394.             port copy: (i@0 extent: 1@height)
  24395.                 from: rect topLeft+((i asFloat/scale) truncated@0)
  24396.                 in: sourceForm fillColor: nil rule: Form over]]
  24397.     ifFalse:
  24398.         [0 to: height-1 do: 
  24399.             [:i |  "slice up original area"
  24400.             port copy: (0@i extent: width@1)
  24401.                 from: rect topLeft+(0@(i asFloat/scale) truncated)
  24402.                 in: sourceForm fillColor: nil rule: Form over]]! !
  24403.  
  24404. !Form methodsFor: 'palette access'!
  24405. gray
  24406.     ^ Color gray!
  24407. highLight  "Color fromUser"
  24408.     "A default color that will at least reverse most bits"
  24409.  
  24410.     ^ Color quickHighLight: depth!
  24411. someColor: colorIndex
  24412.     "Map 0 to white, 1 to black, and 2...nColors throughout the 
  24413.     remaining color space for this pixel depth"
  24414.  
  24415.     ^ (Color allColorsForDepth: depth) atWrap: colorIndex! !
  24416.  
  24417. !Form methodsFor: 'bitmap, color test'!
  24418. bits
  24419.     "Answer the receiver's Bitmap containing its bits."
  24420.  
  24421.     ^ bits!
  24422. bits: aBitmap 
  24423.     "Reset the Bitmap containing the receiver's bits."
  24424.  
  24425.     bits _ aBitmap!
  24426. bitsSize
  24427.     | pixPerWord |
  24428.     depth == nil ifTrue: [depth _ 1].
  24429.     pixPerWord _ 32 // depth.
  24430.     ^ width + pixPerWord - 1 // pixPerWord * height!
  24431. depth
  24432.     ^ depth!
  24433. depth: bitsPerPixel
  24434.     (bitsPerPixel > 32 or:
  24435.         [(bitsPerPixel bitAnd: bitsPerPixel-1) ~= 0])
  24436.         ifTrue: [self halt: 'bitsPerPixel must be 1, 2, 4, 8, 16 or 32'].
  24437.     depth _ bitsPerPixel!
  24438. newColorMap 
  24439.     "Return an uninitialized color map array appropriate to this depth form.
  24440.     Note that RBG forms may want 4k or 32k maps instead of the min 512"
  24441.     ^ Bitmap new: (1 bitShift: (depth min: 9))!
  24442. peripheralColor
  24443.     "Return most common peripheral color,
  24444.     as sampled at 4 corners and 3 edges
  24445.     (this is so that the corners of round rectangles
  24446.     will win over the edges)"
  24447.     | perim samples |
  24448.     perim _ self boundingBox insetBy: (0@0 corner: 1@1).
  24449.     samples _ #(topLeft topCenter topRight rightCenter bottomRight bottomLeft leftCenter) collect:
  24450.         [:locName | self pixelValueAt: (perim perform: locName)].
  24451.     ^ samples asBag sortedElements first key! !
  24452.  
  24453. !Form methodsFor: 'transitions'!
  24454. fadeImage: otherImage at: topLeft
  24455.     indexAndMaskDo: indexAndMaskBlock
  24456.     "This fade uses halftones as a blending hack.
  24457.     Zeros in the halftone produce the original image (self), and 
  24458.     ones in the halftone produce the 'otherImage'.
  24459.     IndexAndMaskBlock gets evaluated prior to each cycle,
  24460.     and the resulting boolean determines whether to continue cycling."
  24461.     | index imageRect maskForm tempForm resultForm |
  24462.     imageRect _ otherImage boundingBox.
  24463.     resultForm _ self copy: (topLeft extent: imageRect extent).
  24464.     maskForm _ Form extent: 32@32.
  24465.     index _ 0.
  24466.     [indexAndMaskBlock value: (index _ index+1) value: maskForm]
  24467.     whileTrue:
  24468.         [maskForm reverse.
  24469.         resultForm copyBits: imageRect from: resultForm at: 0@0
  24470.             clippingBox: imageRect rule: Form over fillColor: maskForm.
  24471.         maskForm reverse.
  24472.         resultForm copyBits: imageRect from: otherImage at: 0@0
  24473.             clippingBox: imageRect rule: Form under fillColor: maskForm.
  24474.         self copyBits: imageRect from: resultForm at: topLeft
  24475.                 clippingBox: self boundingBox rule: Form over fillColor: nil]!
  24476. fadeImageCoarse: otherImage at: topLeft
  24477.     "Display fadeImageCoarse: (Form fromDisplay: (40@40 extent: 300@300)) reverse at: 40@40"
  24478.     | pix j |
  24479.     ^ self fadeImage: otherImage at: topLeft indexAndMaskDo:
  24480.         [:i :mask |
  24481.         i=1 ifTrue: [pix _ (1 bitShift: depth) - 1.
  24482.                     1 to: 8//depth-1 do: [:q | pix _ pix bitOr: (pix bitShift: depth*4)]].
  24483.         i <= 16 ifTrue:
  24484.         [j _ i-1//4+1.
  24485.         (0 to: 28 by: 4) do: [:k |
  24486.             mask bits at: j+k
  24487.                 put: ((mask bits at: j+k) bitOr: (pix bitShift: i-1\\4*depth))].
  24488.         "mask display." true]
  24489.         ifFalse: [false]]!
  24490. fadeImageFine: otherImage at: topLeft
  24491.     "Display fadeImageFine: (Form fromDisplay: (40@40 extent: 300@300)) reverse at: 40@40"
  24492.     | pix j ii |
  24493.     ^ self fadeImage: otherImage at: topLeft indexAndMaskDo:
  24494.         [:i :mask |
  24495.         i=1 ifTrue: [pix _ (1 bitShift: depth) - 1.
  24496.                     1 to: 8//depth-1 do:
  24497.                         [:q | pix _ pix bitOr: (pix bitShift: depth*4)]].
  24498.         i <= 16 ifTrue:
  24499.         [ii _ #(0 10 2 8 7 13 5 15 1 11 3 9 6 12 4 14) at: i.
  24500.         j _ ii//4+1.
  24501.         (0 to: 28 by: 4) do:
  24502.             [:k | mask bits at: j+k put:
  24503.                 ((mask bits at: j+k) bitOr: (pix bitShift: ii\\4*depth))].
  24504.         true]
  24505.         ifFalse: [false]]!
  24506. fadeImageHor: otherImage at: topLeft
  24507.     "Display fadeImageHor: (Form fromDisplay: (10@10 extent: 300@300)) reverse at: 10@10"
  24508.     ^ self fadeImage: otherImage at: topLeft indexAndMaskDo:
  24509.         [:i :mask |
  24510.         mask fill: (0@(mask height//2-i) extent: mask width@(i*2)) fillColor: Color black.
  24511.         (i*2) <= mask width]!
  24512. fadeImageHorFine: otherImage at: topLeft
  24513.     "Display fadeImageHorFine: (Form fromDisplay: (10@10 extent: 300@300)) reverse at: 10@10"
  24514.     ^ self fadeImage: otherImage at: topLeft indexAndMaskDo:
  24515.         [:i :mask |
  24516.         mask fill: (0@(i-1) extent: mask width@1) fillColor: Color black.
  24517.         mask fill: (0@(i-1+16) extent: mask width@1) fillColor: Color black.
  24518.         (i*2) <= mask width]!
  24519. fadeImageSquares: otherImage at: topLeft 
  24520.     "Display fadeImageSquares: (Form fromDisplay: (40@40 extent: 300@300)) reverse at: 40@40"
  24521.     ^ self fadeImage: otherImage at: topLeft indexAndMaskDo:
  24522.         [:i :mask |
  24523.         mask fill: ((16-i) asPoint extent: (i*2) asPoint) fillColor: Color black.
  24524.         i <= 16]!
  24525. fadeImageVert: otherImage at: topLeft
  24526.     "Display fadeImageVert: (Form fromDisplay: (10@10 extent: 300@300)) reverse at: 10@10"
  24527.     ^ self fadeImage: otherImage at: topLeft indexAndMaskDo:
  24528.         [:i :mask |
  24529.         mask fill: ((mask width//2//depth-i*depth)@0 extent: i*2*depth@mask height) fillColor: Color black.
  24530.         i <= (mask width//depth)]!
  24531. pageImage: otherImage at: topLeft corner: corner
  24532.     "Produce a page-turning illusion that gradually reveals otherImage
  24533.     located at topLeft in this form.  Corner specifies which corner, as
  24534.         1=topLeft, 2=topRight, 3=bottomRight, 4=bottomLeft."
  24535.     | bb maskForm resultForm delta p maskLoc maskRect stepSize cornerSel smallRect |
  24536.     stepSize _ 10.
  24537.     bb _ otherImage boundingBox.
  24538.     resultForm _ self copy: (topLeft extent: bb extent).
  24539.     maskForm _ Form extent: ((otherImage width min: otherImage height) + stepSize) asPoint.
  24540.  
  24541.     "maskLoc _ starting loc rel to topLeft"
  24542.     otherImage width > otherImage height
  24543.         ifTrue: ["wide image; motion is horizontal."
  24544.                 (corner between: 2 and: 3) not ifTrue:
  24545.                     ["motion is to the right"
  24546.                     delta _ 1@0.
  24547.                     maskLoc _ bb topLeft - (corner = 1
  24548.                         ifTrue: [maskForm width@0]
  24549.                         ifFalse: [maskForm width@stepSize])]
  24550.                     ifFalse:
  24551.                     ["motion is to the left"
  24552.                     delta _ -1@0.
  24553.                     maskLoc _ bb topRight - (corner = 2
  24554.                         ifTrue: [0@0]
  24555.                         ifFalse: [0@stepSize])]]
  24556.         ifFalse: ["tall image; motion is vertical."
  24557.                 corner <= 2 ifTrue:
  24558.                     ["motion is downward"
  24559.                     delta _ 0@1.
  24560.                     maskLoc _ bb topLeft - (corner = 1
  24561.                         ifTrue: [0@maskForm height]
  24562.                         ifFalse: [stepSize@maskForm height])]
  24563.                     ifFalse:
  24564.                     ["motion is upward"
  24565.                     delta _ 0@-1.
  24566.                     maskLoc _ bb bottomLeft - (corner = 3
  24567.                         ifTrue: [stepSize@0]
  24568.                         ifFalse: [0@0])]].
  24569.  
  24570.     "Build a solid triangle in the mask form"
  24571.     (Pen newOnForm: maskForm) do: [:p |
  24572.         corner even  "Draw 45-degree line"
  24573.             ifTrue: [p place: 0@0; turn: 135; go: maskForm width*3//2]
  24574.             ifFalse: [p place: 0@(maskForm height-1); turn: 45; go: maskForm width*3//2]].
  24575.     maskForm smear: delta negated distance: maskForm width.
  24576.     "Copy the mask to full resolution for speed.  Make it be the reversed
  24577.     so that it can be used for ORing in the page-corner color"
  24578.     maskForm _ (Form extent: maskForm extent depth: otherImage depth)
  24579.         copyBits: maskForm boundingBox from: maskForm at: 0@0
  24580.         colorMap: (Bitmap with: 16rFFFFFFFF with: 0).
  24581.  
  24582.     "Now move the triangle maskForm across the resultForm selecting the
  24583.     triangular part of otherImage to display, and across the resultForm,
  24584.     selecting the part of the original image to erase."
  24585.     cornerSel _ #(topLeft topRight bottomRight bottomLeft) at: corner.
  24586.     1 to: (otherImage width + otherImage height // stepSize)+1 do:
  24587.         [:i |        "Determine the affected square"
  24588.         maskRect _ (maskLoc extent: maskForm extent) intersect: bb.
  24589.         ((maskLoc x*delta x) + (maskLoc y*delta y)) < 0 ifTrue:
  24590.             [smallRect _ 0@0 extent: (maskRect width min: maskRect height) asPoint.
  24591.             maskRect _ smallRect align: (smallRect perform: cornerSel)
  24592.                                 with: (maskRect perform: cornerSel)].
  24593.  
  24594.         "AND otherForm with triangle mask, and OR into result"
  24595.         resultForm copyBits: bb from: otherImage at: 0@0
  24596.                 clippingBox: maskRect rule: Form over fillColor: nil.
  24597.         resultForm copyBits: maskForm boundingBox from: maskForm at: maskLoc
  24598.                 clippingBox: maskRect rule: Form erase fillColor: nil.
  24599.         resultForm copyBits: maskForm boundingBox from: maskForm at: maskLoc
  24600.                 clippingBox: maskRect rule: Form under fillColor: Color lightBrown.
  24601.  
  24602.         "Now update Display in a single BLT."
  24603.         self copyBits: maskRect from: resultForm at: topLeft + maskRect topLeft
  24604.                 clippingBox: self boundingBox rule: Form over fillColor: nil.
  24605.         maskLoc _ maskLoc + (delta*stepSize)]
  24606. "
  24607. 1 to: 4 do: [:corner | Display pageImage:
  24608.                 (Form fromDisplay: (10@10 extent: 200@300)) reverse
  24609.             at: 10@10 corner: corner]
  24610. "
  24611. !
  24612. slideImage: otherImage at: topLeft delta: delta
  24613.     "Display slideImage: (Form fromDisplay: (40@40 extent: 300@300)) reverse
  24614.         at: 40@40 delta: 3@-4"
  24615.     | bb nSteps clipRect |
  24616.     bb _ otherImage boundingBox.
  24617.     clipRect _ topLeft extent: otherImage extent.
  24618.     nSteps _ 1.
  24619.     delta x = 0 ifFalse: [nSteps _ nSteps max: (bb width//delta x abs) + 1].
  24620.     delta y = 0 ifFalse: [nSteps _ nSteps max: (bb height//delta y abs) + 1].
  24621.     1 to: nSteps do:
  24622.             [:i | self copyBits: bb from: otherImage
  24623.                 at: delta*(i-nSteps) + topLeft
  24624.                 clippingBox: clipRect rule: Form over fillColor: nil]!
  24625. wipeImage: otherImage at: topLeft delta: delta
  24626.     "Display wipeImage: (Form fromDisplay: (40@40 extent: 300@300)) reverse
  24627.         at: 40@40 delta: 0@-2"
  24628.     | wipeRect bb nSteps |
  24629.     bb _ otherImage boundingBox.
  24630.     wipeRect _ delta x = 0
  24631.         ifTrue:
  24632.         [delta y = 0 ifTrue: [nSteps _ 1. bb "allow 0@0"] ifFalse: [
  24633.         nSteps _ bb height//delta y abs + 1.  "Vertical movement"
  24634.         delta y > 0
  24635.             ifTrue: [bb topLeft extent: bb width@delta y]
  24636.             ifFalse: [bb bottomLeft+delta extent: bb width@delta y negated]]]
  24637.         ifFalse:
  24638.         [nSteps _ bb width//delta x abs + 1.  "Horizontal movement"
  24639.         delta x > 0
  24640.             ifTrue: [bb topLeft extent: delta x@bb height]
  24641.             ifFalse: [bb topRight+delta extent: delta x negated@bb height]].
  24642.     ^ self wipeImage: otherImage at: topLeft rectForIndex:
  24643.         [:i | i <= nSteps
  24644.             ifTrue: [wipeRect translateBy: (i-1)*delta]
  24645.             ifFalse: [nil]]!
  24646. wipeImage: otherImage at: topLeft rectForIndex: rectForIndexBlock
  24647.     | index thisRect clipRect |
  24648.     index _ 0.
  24649.     clipRect _ topLeft extent: otherImage extent.
  24650.     [(thisRect _ rectForIndexBlock value: (index _ index+1)) == nil]
  24651.     whileFalse:
  24652.         [thisRect do:
  24653.             [:r | self copyBits: r from: otherImage at: topLeft + r topLeft
  24654.                 clippingBox: clipRect rule: Form over fillColor: nil]].!
  24655. zoomInTo: otherImage at: topLeft
  24656.     "Display zoomInTo: (Form fromDisplay: (40@40 extent: 300@300)) reverse at: 40@40"
  24657.     ^ self wipeImage: otherImage at: topLeft rectForIndex:
  24658.         [:i | i <= 16
  24659.             ifTrue: [otherImage center - (otherImage extent*i//32)
  24660.                         extent: otherImage extent*i//16]
  24661.             ifFalse: [nil]]!
  24662. zoomOutTo: otherImage at: topLeft
  24663.     "Display zoomOutTo: (Form fromDisplay: (40@40 extent: 300@300)) reverse at: 40@40"
  24664.     ^ self wipeImage: otherImage at: topLeft rectForIndex:
  24665.         [:i | i <= 16
  24666.             ifTrue: [(otherImage center - (otherImage extent*(17-i)//32)
  24667.                         extent: otherImage extent*(17-i)//16)
  24668.                     areasOutside:
  24669.                     (otherImage center - (otherImage extent*(16-i)//32)
  24670.                         extent: otherImage extent*(16-i)//16)]
  24671.             ifFalse: [nil]]! !
  24672.  
  24673. !Form methodsFor: 'coloring'!
  24674. clear
  24675.     "Reset the receiver to all white.   Created by Alan for his Ob prototype, 2/96, and now also used in the Obj world, though perhaps one might think about some forms clearing to other than pure white?!!"
  24676.  
  24677.         self fillWhite! !
  24678. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  24679.  
  24680. Form class
  24681.     instanceVariableNames: 'whiteMask darkGrayMask grayMask blackMask lightGrayMask veryLightGrayMask '!
  24682.  
  24683. !Form class methodsFor: 'instance creation'!
  24684. dotOfSize: diameter
  24685.     "Create a form which contains a round black dot."
  24686.     | radius form bite circle |
  24687.     radius _ diameter//2.
  24688.     form _ Form extent: diameter@diameter offset: (0@0) - (radius@radius).    
  24689.     diameter <= 9 ifTrue: "special case for speed"
  24690.         [form fillBlack.
  24691.         bite _ diameter//3.
  24692.         form fillWhite: (0@0 extent: bite@1).
  24693.         form fillWhite: (0@(diameter-1) extent: bite@1).
  24694.         form fillWhite: (diameter-bite@0 extent: bite@1).
  24695.         form fillWhite: (diameter-bite@(diameter-1) extent: bite@1).
  24696.         form fillWhite: (0@0 extent: 1@bite).
  24697.         form fillWhite: (0@(diameter-bite) extent: 1@bite).
  24698.         form fillWhite: (diameter-1@0 extent: 1@bite).
  24699.         form fillWhite: (diameter-1@(diameter-bite) extent: 1@bite).
  24700.         ^ form].
  24701.  
  24702.     radius _ diameter-1//2.  "so circle fits entirely"
  24703.     (Circle new center: radius@radius radius: radius) displayOn: form.
  24704.     form convexShapeFill: form black.    "fill the circle with black"
  24705.     ^ form
  24706.  
  24707.     "(Form dotOfSize: 8) displayAt: Sensor cursorPoint"!
  24708. extent: extentPoint
  24709.     "Answer an instance of me with blank bitmap."
  24710.  
  24711.     ^ self basicNew setExtent: extentPoint!
  24712. extent: extentPoint depth: bitsPerPixel
  24713.     "Answer an instance of me with blank bitmap."
  24714.  
  24715.     ^ self basicNew setExtent: extentPoint depth: bitsPerPixel!
  24716. extent: extentPoint fromArray: anArray offset: offsetPoint 
  24717.     "Answer an instance of me with bitmap initialized from anArray."
  24718.  
  24719.     ^ (self basicNew setExtent: extentPoint offset: offsetPoint)
  24720.         initFromArray: anArray!
  24721. extent: extentPoint fromStipple: fourNibbles
  24722.     "Answer an instance of me with bitmap initialized from
  24723.     a repeating 4x4 bit stipple encoded in a 16-bit constant."
  24724.     | nibble |
  24725.     ^ (self basicNew setExtent: extentPoint)
  24726.         initFromArray: ((1 to: 4) collect:
  24727.                 [:i | nibble _ (fourNibbles bitShift: -4*(4-i)) bitAnd: 16rF.
  24728.                 16r11111111 * nibble])  "fill 32 bits with each 4-bit nibble"!
  24729. extent: extentPoint offset: offsetPoint 
  24730.     "Answer an instance of me with a blank bitmap."
  24731.  
  24732.     ^ (self basicNew setExtent: extentPoint)
  24733.         offset: offsetPoint!
  24734. fromDisplay: aRectangle 
  24735.     "Answer an instance of me with bitmap initialized from the area of the 
  24736.     display screen defined by aRectangle."
  24737.  
  24738.     ^ (self extent: aRectangle extent depth: Display depth)
  24739.         fromDisplay: aRectangle!
  24740. fromDisplay: aRectangle using: oldForm
  24741.     "Like fromDisplay: only if oldForm is the right size, copy into it and answer it instead."
  24742.  
  24743.     ((oldForm ~~ nil) and: [oldForm extent = aRectangle extent])
  24744.         ifTrue:
  24745.             [oldForm fromDisplay: aRectangle.
  24746.              ^ oldForm]
  24747.         ifFalse:
  24748.             [^ self fromDisplay: aRectangle]!
  24749. fromTripletOfLiterals: aTriplet
  24750.     | extentDoublet offsetDoublet |
  24751.     extentDoublet _ aTriplet at: 1.
  24752.     offsetDoublet _ aTriplet at: 3.
  24753.     ^ self extent: (extentDoublet at: 1) @ (extentDoublet at: 2) fromArray: (aTriplet at: 2) offset: ((offsetDoublet at: 1) @ (offsetDoublet at: 2))!
  24754. fromUser
  24755.     "Answer an instance of me with bitmap initialized from the area of the 
  24756.     display screen designated by the user. The grid for selecting an area is 
  24757.     1@1."
  24758.  
  24759.     ^self fromUser: 1 @ 1!
  24760. fromUser: aPoint 
  24761.     "Answer an instance of me with bitmap initialized from the area of the 
  24762.     display screen designated by the user. The grid for selecting an area is 
  24763.     aPoint."
  24764.  
  24765.     ^ self fromDisplay: (Rectangle fromUser: aPoint)! !
  24766.  
  24767. !Form class methodsFor: 'mode constants'!
  24768. and
  24769.     "Answer the integer denoting the logical 'and' combination rule."
  24770.  
  24771.     ^1!
  24772. blend
  24773.     "Answer the integer denoting BitBlt's alpha blend combination rule."
  24774.     ^24!
  24775. erase
  24776.     "Answer the integer denoting mode erase."
  24777.  
  24778.     ^4!
  24779. erase1bitShape
  24780.     "Answer the integer denoting mode erase."
  24781.  
  24782.     ^ 17!
  24783. over
  24784.     "Answer the integer denoting mode over."
  24785.  
  24786.     ^3!
  24787. paint
  24788.     "Answer the integer denoting the 'paint' combination rule."
  24789.  
  24790.     ^16!
  24791. reverse
  24792.     "Answer the integer denoting mode reverse."
  24793.  
  24794.     ^6!
  24795. under
  24796.     "Answer the integer denoting mode under."
  24797.  
  24798.     ^7! !
  24799.  
  24800. !Form class methodsFor: 'default colors'!
  24801. black
  24802.     "This message should be sent to Display, or other destForm"
  24803.  
  24804.     ^ Display black!
  24805. darkGray
  24806.     "This message should be sent to Display, or other destForm"
  24807.  
  24808.     ^ Display darkGray!
  24809. gray
  24810.     "This message should be sent to Display, or other destForm"
  24811.  
  24812.     ^ Color gray!
  24813. lightGray
  24814.     "This message should be sent to Display, or other destForm"
  24815.  
  24816.     ^ Display lightGray!
  24817. white
  24818.     "This message should be sent to Display, or other destForm"
  24819.  
  24820.     ^ Display white! !
  24821.  
  24822. !Form class methodsFor: 'examples'!
  24823. exampleBorder    "Form exampleBorder"
  24824.     "This example demonstrates the border finding algorithm. Start
  24825.     by having the user sketch on the screen (end with option-click) and then select a rectangular
  24826.     area of the screen which includes all of the area to be filled. Finally,
  24827.     (with crosshair cursor), the user points at the interior of the region to be
  24828.     outlined, and the region begins with that place as its seed."
  24829.     | f r interiorPoint |
  24830.     Form exampleSketch.        "sketch a little area with an enclosed region"
  24831.     r _ Rectangle fromUser.
  24832.     f _ Form fromDisplay: r.
  24833.     Cursor crossHair showWhile:
  24834.         [interiorPoint _ Sensor waitButton - r origin].
  24835.     Cursor execute showWhile:
  24836.         [f shapeBorder: Color blue width: 2 interiorPoint: interiorPoint
  24837.             sharpCorners: false internal: false].
  24838.     f displayOn: Display at: r origin    !
  24839. exampleEdits
  24840.     "In Form category editing are messages edit and bitEdit that make it possible to 
  24841.     create editors on instances of Form. 
  24842.      
  24843.     This is the general form editor:
  24844.     | f | 
  24845.     f _ Form fromUser. 
  24846.     f edit. 
  24847.      
  24848.     This is the general bit editor:
  24849.     | f | 
  24850.     f _ Form fromUser. 
  24851.     f bitEdit."!
  24852. exampleMagnify
  24853.  
  24854.     | f m |
  24855.     f _ Form fromUser.
  24856.     m _ f magnify: f boundingBox by: 5 @ 5.
  24857.     m displayOn: Display at: Sensor waitButton
  24858.  
  24859.     "Form exampleMagnify."!
  24860. exampleShrink
  24861.  
  24862.     | f s |
  24863.     f _ Form fromUser.
  24864.     s _ f shrink: f boundingBox by: 2 @ 5.
  24865.     s displayOn: Display at: Sensor waitButton    
  24866.  
  24867.     "Form exampleShrink."!
  24868. exampleSketch
  24869.     "This is a simple drawing algorithm to get a sketch on the display screen.
  24870.     Draws whenever mouse button down.  Ends with option-click."
  24871.     | aPen color |
  24872.     aPen _ Pen new.
  24873.     color _ 0.
  24874.     [Sensor yellowButtonPressed]
  24875.         whileFalse:
  24876.         [aPen place: Sensor cursorPoint; color: (color _ color + 1).
  24877.         [Sensor redButtonPressed]
  24878.             whileTrue: [aPen goto: Sensor cursorPoint]].
  24879.     Sensor waitNoButton.
  24880.  
  24881.     "Form exampleSketch"!
  24882. exampleSpaceFill    "Form exampleSpaceFill"
  24883.     "This example demonstrates the area filling algorithm. Starts by having
  24884.     the user sketch on the screen (ended by option-click) and then select a rectangular
  24885.     area of the screen which includes all of the area to be filled. Finally,
  24886.     (with crosshair cursor), the user points at the interior of some region to be
  24887.     filled, and the filling begins with that place as its seed."
  24888.     | f r interiorPoint |
  24889.     Form exampleSketch.        "sketch a little area with an enclosed region"
  24890.     r _ Rectangle fromUser.
  24891.     f _ Form fromDisplay: r.
  24892.     Cursor crossHair showWhile:
  24893.         [interiorPoint _ Sensor waitButton - r origin].
  24894.     Cursor execute showWhile:
  24895.         [f shapeFill: Color gray interiorPoint: interiorPoint].
  24896.     f displayOn: Display at: r origin    !
  24897. makeStar  "See the similar example in OpaqueForm"
  24898.     | sampleForm pen |
  24899.     sampleForm _ Form extent: 50@50.  "Make a form"
  24900.     pen _ Pen newOnForm: sampleForm.
  24901.     pen place: 24@50; turn: 18.        "Draw a 5-pointed star on it."
  24902.     1 to: 5 do: [:i | pen go: 19; turn: 72; go: 19; turn: -144].
  24903.     ^ sampleForm
  24904. "
  24905. Form makeStar follow: [Sensor cursorPoint]
  24906.                 while: [Sensor noButtonPressed]
  24907. "!
  24908. tinyText: aText scale: m
  24909.     "(Form tinyText: 'Hi There!!  These caps are 5 high, and
  24910. the lower-case are 3 high.  Not bad, eh?' asText allBold scale: 2) display"
  24911.     | f1 tiny grays |
  24912.     f1 _ aText asDisplayText form.
  24913.     tiny _ Form extent: f1 extent//m depth: 8.
  24914.     grays _ (0 to: m*m) collect: [:i | 39 - (i*(39-16)//(m*m))].
  24915.     0 to: tiny width-1 do:
  24916.         [:x | 0 to: tiny height-1 do:
  24917.             [:y | tiny pixelValueAt: x@y
  24918.                 put: (grays at: (f1 sumBitsAt: (x*m)@(y*m) cellSize: m) + 1)]].
  24919.     ^ tiny!
  24920. toothpaste: diam        "Display restoreAfter: [Form toothpaste: 30]"
  24921.     "Draws wormlike lines by laying down images of spheres.
  24922.     See Ken Knowlton, Computer Graphics, vol. 15 no. 4 p352.
  24923.     Draw with mouse button down; terminate by option-click."
  24924.     | facade ball filter point queue port color q colors |
  24925.     colors _ Display depth = 1
  24926.         ifTrue: [Array with: Color black]
  24927.         ifFalse: [Color red wheel: 20].
  24928.     facade _ Form extent: diam@diam offset: (diam//-2) asPoint.
  24929.     (Form dotOfSize: diam) displayOn: facade
  24930.             at: (diam//2) asPoint clippingBox: facade boundingBox
  24931.             rule: Form under fillColor: Color veryLightGray.
  24932.     #(1 2 3) do:
  24933.         [:x |  "simulate facade by circles of gray"
  24934.         (Form dotOfSize: x*diam//5) displayOn: facade
  24935.             at: (diam*2//5) asPoint clippingBox: facade boundingBox
  24936.             rule: Form under
  24937.             fillColor: (Color perform: 
  24938.                     (#(black gray lightGray white veryLightGray) at: x))].
  24939.     ball _ Form dotOfSize: diam.
  24940.     color _ 1.
  24941.     [ true ] whileTrue:
  24942.         [port _ BitBlt toForm: Display.
  24943.         "Expand 1-bit forms to any pixel depth"
  24944.         port colorMap: (Bitmap with: 0 with: 16rFFFFFFFF).
  24945.         queue _ SharedQueue new: 32.
  24946.         16 timesRepeat: [queue nextPut: -20@-20].
  24947.         Sensor waitButton.
  24948.         Sensor yellowButtonPressed ifTrue: [^ self].
  24949.         filter _ Sensor cursorPoint.
  24950.         [Sensor redButtonPressed or: [queue size > 0]] whileTrue:
  24951.             [filter _ filter * 4 + Sensor cursorPoint // 5.
  24952.             point _ Sensor redButtonPressed
  24953.                 ifTrue: [filter] ifFalse: [-20@-20].
  24954.             port copyForm: ball to: point rule: Form paint
  24955.                     fillColor: (colors atWrap: color*9).
  24956.             (q _ queue next) == nil ifTrue: [^ self].    "exit"
  24957.             port copyForm: facade to: q rule: Form erase.
  24958.             Sensor redButtonPressed ifTrue: [queue nextPut: point]].
  24959.         color _ color + 1]!
  24960. xorHack: size  "Display restoreAfter: [Form xorHack: 256]"
  24961.     "Draw a smiley face or stick figure, and end with option-click.
  24962.     Thereafter image gets 'processed' as long as you have button down.
  24963.     If you stop at just the right time, you'll see you figure upside down,
  24964.     and at the end of a full cycle, you'll see it perfectly restored.
  24965.     Dude -- this works in color too!!"
  24966.     | rect form i bb |
  24967.     rect _ 5@5 extent: size@size.
  24968.     Display fillWhite: rect; border: (rect expandBy: 2) width: 2.
  24969.     Display border: (rect topRight - (0@2) extent: rect extent*2 + 4) width: 2.
  24970.     Form exampleSketch.
  24971.     form _ Form fromDisplay: rect.
  24972.     bb _ form boundingBox.
  24973.     i _ 0.
  24974.     [Sensor yellowButtonPressed] whileFalse:
  24975.         [[Sensor redButtonPressed] whileTrue:
  24976.             [i _ i + 1.
  24977.             (Array with: 0@1 with: 0@-1 with: 1@0 with: -1@0) do:
  24978.                 [:d | form copyBits: bb from: form at: d
  24979.                     clippingBox: bb rule: Form reverse fillColor: nil].
  24980.             form displayAt: rect topLeft.
  24981.             i+2\\size < 4 ifTrue: [(Delay forMilliseconds: 300) wait]].
  24982.         (form magnify: form boundingBox by: 2@2) displayAt: rect topRight + (2@0).
  24983.         Sensor waitButton].! !
  24984.  
  24985. !Form class methodsFor: 'screen dump'!
  24986. screenDump
  24987.     | form f |
  24988.     form _ Form fromDisplay: Display boundingBox.
  24989.     f _ FileStream fileNamed: 'STScreen', Time millisecondClockValue printString.
  24990.     form bigMacPaintOn: f.
  24991.     f close
  24992.  
  24993. "Form screenDump"! !
  24994.  
  24995. !Form class methodsFor: 'miscellaneous'!
  24996. randomTransitionSelector
  24997.     "Return a two-argument transition selector, chosen randomly.  7/25/96 sw"
  24998.  
  24999.     ^ #(fadeImageCoarse:at: fadeImageFine:at: fadeImageHor:at: fadeImageHorFine:at: fadeImageSquares:at: fadeImageVert:at: zoomInTo:at: zoomOutTo:at:) atRandom
  25000.  
  25001. " slideImage:at:delta: wipeImage:at:delta: "! !Object subclass: #FormButtonCache
  25002.     instanceVariableNames: 'offset form value initialState '
  25003.     classVariableNames: ''
  25004.     poolDictionaries: ''
  25005.     category: 'Graphics-Editors'!
  25006. FormButtonCache comment:
  25007. 'My instances are used to save information needed to construct the switch in a menu for a FormEditor. A collection of my instances is stored as a class variable of FormMenuView.'!
  25008.  
  25009. !FormButtonCache methodsFor: 'accessing'!
  25010. form
  25011.     "Answer the receiver's form, the image of the button on the screen."
  25012.  
  25013.     ^form!
  25014. form: aForm
  25015.     "Set the receiver's form to be the argument."
  25016.  
  25017.     form _ aForm!
  25018. initialState
  25019.     "Answer the receiver's initial state, on or off."
  25020.  
  25021.     ^initialState!
  25022. initialState: aBoolean
  25023.     "Set the receiver's initial state, on or off, to be the argument."
  25024.  
  25025.     initialState _ aBoolean!
  25026. offset
  25027.     "Answer the receiver's offset, its relative position for displaying the 
  25028.     button."
  25029.  
  25030.     ^offset!
  25031. offset: anInteger
  25032.     "Set the receiver's offset."
  25033.  
  25034.     offset _ anInteger!
  25035. value
  25036.     "Answer the receiver's value, the keyboard key that selects the button."
  25037.  
  25038.     ^value!
  25039. value: aCharacter
  25040.     "Set the receiver's key character."
  25041.  
  25042.     value _ aCharacter! !MouseMenuController subclass: #FormEditor
  25043.     instanceVariableNames: 'form tool grid togglegrid mode previousTool color unNormalizedColor xgridOn ygridOn '
  25044.     classVariableNames: 'YgridKey OverKey YellowButtonMenu RepeatCopyKey SingleCopyKey InKey BlackKey OutKey LineKey TogglexGridKey FlashCursor DarkGrayKey ChangeGridsKey GrayKey SelectKey UnderKey ReverseKey WhiteKey BlockKey LightGrayKey CurveKey BitEditKey YellowButtonMessages EraseKey ToggleyGridKey '
  25045.     poolDictionaries: ''
  25046.     category: 'Graphics-Editors'!
  25047. FormEditor comment:
  25048. 'I represent the basic editor for creating and modifying Forms. This is intended to be an easy to use general-purpose picture (bitMap) editor. I am a kind of MouseMenuController that creates a yellow button menu for accepting and canceling edits. My instances give up control if the cursor is outside the FormView or if a key on the keyboard is pressed.'!
  25049.  
  25050. !FormEditor methodsFor: 'initialize-release'!
  25051. initialize
  25052.  
  25053.     super initialize.
  25054.     self setVariables.
  25055.     self initializeYellowButtonMenu!
  25056. release
  25057.     "Break the cycle between the Controller and its view. It is usually not 
  25058.     necessary to send release provided the Controller's view has been properly 
  25059.     released independently."
  25060.  
  25061.     super release.
  25062.     form _ nil! !
  25063.  
  25064. !FormEditor methodsFor: 'basic control sequence'!
  25065. controlInitialize
  25066.  
  25067.     Cursor blank show.
  25068.     self normalizeColor: unNormalizedColor.
  25069.     sensor waitNoButton!
  25070. controlTerminate
  25071.     "Resets the cursor to be the normal Smalltalk cursor."
  25072.  
  25073.     Cursor normal show.
  25074.     view updateDisplay! !
  25075.  
  25076. !FormEditor methodsFor: 'control defaults'!
  25077. controlActivity
  25078.  
  25079.     super controlActivity.
  25080.     self dragForm!
  25081. isControlActive
  25082.  
  25083.     ^super isControlActive & sensor blueButtonPressed not 
  25084.         & sensor keyboardPressed not! !
  25085.  
  25086. !FormEditor methodsFor: 'editing tools'!
  25087. block
  25088.     "Allow the user to fill a rectangle with the gray tone and mode currently 
  25089.     selected."
  25090.  
  25091.     | rectangle |
  25092.     rectangle _ Rectangle fromUser: grid.
  25093.     rectangle isNil 
  25094.         ifFalse: [Display
  25095.                     fill: (rectangle intersect: view insetDisplayBox)
  25096.                     rule: mode
  25097.                     fillColor: color]!
  25098. changeGridding
  25099.     "Allow the user to change the values of the horizontal and/or vertical 
  25100.     grid modules. Does not change the primary tool."
  25101.  
  25102.     | response gridInteger |
  25103.     response _ 
  25104.         self promptRequest: 'Current horizontal gridding is: ' 
  25105.                         , togglegrid x printString 
  25106.                         , '.
  25107. Type new horizontal gridding.'.
  25108.     response isEmpty
  25109.         ifFalse: 
  25110.             [gridInteger _ Integer readFromString: response.
  25111.             togglegrid x: ((gridInteger max: 1) min: Display extent x)].
  25112.     response _ 
  25113.         self promptRequest: 'Current vertical gridding is: ' 
  25114.                         , togglegrid y printString 
  25115.                         , '.
  25116. Type new vertical gridding.'.
  25117.     response isEmpty
  25118.         ifFalse: 
  25119.             [gridInteger _ Integer readFromString: response.
  25120.             togglegrid y: ((gridInteger max: 1) min: Display extent y)].
  25121.     xgridOn ifTrue: [grid x: togglegrid x].
  25122.     ygridOn ifTrue: [grid y: togglegrid y].
  25123.     tool _ previousTool!
  25124. changeTool: aCharacter 
  25125.     "Change the value of the instance variable tool to be the tool 
  25126.     corresponding to aCharacter. Typically sent from a Switch in a 
  25127.     FormMenuView."
  25128.  
  25129.     previousTool _ tool.
  25130.     tool _ self selectTool: aCharacter.
  25131.     (#(singleCopy repeatCopy line curve block) includes: tool)
  25132.         ifFalse:
  25133.             [self perform: tool]!
  25134. colorBlack
  25135.     "Set the mask (color) to black. Leaves the tool set in its previous state."
  25136.  
  25137.     self setColor: Color black!
  25138. colorDarkGray
  25139.     "Set the mask (color) to dark gray. Leaves the tool set in its previous 
  25140.     state."
  25141.  
  25142.     self setColor: Color darkGray!
  25143. colorGray
  25144.     "Set the mask (color) to gray. Leaves the tool set in its previous state."
  25145.  
  25146.     self setColor: Color gray!
  25147. colorLightGray
  25148.     "Set the mask (color) to light gray. Leaves the tool set in its previous 
  25149.     state."
  25150.  
  25151.     self setColor: Color lightGray!
  25152. colorWhite
  25153.     "Set the mask (color) to white. Leaves the tool set in its previous state."
  25154.  
  25155.     self setColor: Color white!
  25156. curve
  25157.     "Conic-section specified by three points designated by: first point--press 
  25158.     red button second point--release red button third point--click red button. 
  25159.     The resultant curve on the display is displayed according to the current 
  25160.     form and mode."
  25161.  
  25162.     | firstPoint secondPoint thirdPoint curve |
  25163.     "sensor noButtonPressed ifTrue: [^self]."
  25164.     firstPoint _ self cursorPoint.
  25165.     form
  25166.         displayOn: Display
  25167.         at: firstPoint
  25168.         clippingBox: view insetDisplayBox
  25169.         rule: (Display depth > 1 ifTrue: [Form paint]
  25170.                                         ifFalse: [mode])
  25171.         fillColor: color.
  25172.     secondPoint _ self trackFormUntil: [sensor noButtonPressed].
  25173.     form
  25174.         displayOn: Display
  25175.         at: secondPoint
  25176.         clippingBox: view insetDisplayBox
  25177.         rule: Form reverse
  25178.         fillColor: color.
  25179.     thirdPoint _ self trackFormUntil: [sensor redButtonPressed]..
  25180.     form
  25181.         displayOn: Display
  25182.         at: thirdPoint
  25183.         clippingBox: view insetDisplayBox
  25184.         rule: (Display depth > 1 ifTrue: [Form paint]
  25185.                                         ifFalse: [mode])
  25186.         fillColor: color.
  25187.     form
  25188.         displayOn: Display
  25189.         at: secondPoint
  25190.         clippingBox: view insetDisplayBox
  25191.         rule: Form reverse
  25192.         fillColor: color.
  25193.     curve _ Curve new.
  25194.     curve firstPoint: firstPoint.
  25195.     curve secondPoint: secondPoint.
  25196.     curve thirdPoint: thirdPoint.
  25197.     curve form: form.
  25198.     curve
  25199.         displayOn: Display
  25200.         at: 0 @ 0
  25201.         clippingBox: view insetDisplayBox
  25202.         rule: (Display depth > 1 ifTrue: [Form paint]
  25203.                                         ifFalse: [mode])
  25204.         fillColor: color.
  25205.     sensor waitNoButton!
  25206. eraseMode
  25207.     "Set the mode for the tools that copy the form onto the display to erase. 
  25208.     Leaves the tool set in its previous state."
  25209.  
  25210.     mode _ 4.
  25211.     tool _ previousTool!
  25212. fileInForm
  25213.     "Ask the user for a file name and then recalls the Form in that file as 
  25214.     the current source Form (form). Does not change the tool."
  25215.  
  25216.     | inName |
  25217.     inName _ self promptRequest: 'type a name for recalling a source Form . . . '.
  25218.     (FileDirectory isLegalFileName: inName) 
  25219.         ifTrue: [form _ Form readFrom: inName].
  25220.     tool _ previousTool!
  25221. fileOutForm
  25222.     "Ask the user for a file name and then save the current source form 
  25223.     (form) under that name. Does not change the tool."
  25224.  
  25225.     | outName |
  25226.     outName _ self promptRequest: 'type a name for saving the source Form . . . '.
  25227.     FileDirectory convertName: outName with: [ :vol :name |
  25228.         (vol isLegalFileName: name)
  25229.             ifTrue: [(vol includesKey: name) 
  25230.                     ifTrue: [(self confirm: 
  25231.                                     'Okay to write over old file?')
  25232.                                 ifTrue: [form writeOn: outName]]
  25233.                     ifFalse: [form writeOn: outName]]].
  25234.     tool _ previousTool!
  25235. line
  25236.     "Line is specified by two points from the mouse: first point--press red 
  25237.     button; second point--release red button. The resultant line is displayed 
  25238.     according to the current form and mode."
  25239.  
  25240.     | firstPoint endPoint |
  25241.     firstPoint _ self cursorPoint.
  25242.     endPoint _ self rubberBandFrom: firstPoint until: [sensor noButtonPressed].
  25243.     (Line from: firstPoint to: endPoint withForm: form)
  25244.         displayOn: Display
  25245.         at: 0 @ 0
  25246.         clippingBox: view insetDisplayBox
  25247.         rule: (Display depth > 1 ifTrue: [Form paint]
  25248.                                         ifFalse: [mode])
  25249.         fillColor: color!
  25250. magnify
  25251.     "Allow for bit editing of an area of the Form. The user designates a 
  25252.     rectangular area that is scaled by 5 to allow individual screens dots to be 
  25253.     modified. Red button is used to set a bit to black, and yellow button is 
  25254.     used to set a bit to white. Editing continues until the user depresses any 
  25255.     key on the keyboard."
  25256.  
  25257.     | smallRect smallForm scaleFactor tempRect |
  25258.     scaleFactor _ 8@8.
  25259.     smallRect _ (Rectangle fromUser: grid) intersect: view insetDisplayBox.
  25260.     smallRect isNil ifTrue: [^self].
  25261.     smallForm _ Form fromDisplay: smallRect.
  25262.  
  25263.     "Do this computation here in order to be able to save the existing display screen."
  25264.     tempRect _ BitEditor locateMagnifiedView: smallForm scale: scaleFactor.
  25265.     BitEditor
  25266.         openScreenViewOnForm: smallForm 
  25267.         at: smallRect topLeft 
  25268.         magnifiedAt: tempRect topLeft 
  25269.         scale: scaleFactor.
  25270.     tool _ previousTool!
  25271. newSourceForm
  25272.     "Allow the user to define a new source form for the FormEditor. Copying 
  25273.     the source form onto the display is the primary graphical operation. 
  25274.     Resets the tool to be repeatCopy."
  25275.     | dForm interiorPoint interiorColor |
  25276.     dForm _ Form fromUser: grid.
  25277.     "sourceForm must be only 1 bit deep"
  25278.     interiorPoint _ dForm extent // 2.
  25279.     interiorColor _ Color colorFromPixelValue:
  25280.         (dForm pixelValueAt: interiorPoint) depth: dForm depth.
  25281.     form _ (dForm makeBWForm: interiorColor) reverse
  25282.                 findShapeAroundSeedBlock:
  25283.                     [:f | f pixelValueAt: interiorPoint put: 1].
  25284.     form _ form trimToPixelValue: 1 orNot: false.
  25285.     tool _ previousTool!
  25286. overMode
  25287.     "Set the mode for the tools that copy the form onto the display to over. 
  25288.     Leaves the tool set in its previous state."
  25289.  
  25290.     mode _ Form over.
  25291.     tool _ previousTool!
  25292. repeatCopy
  25293.     "As long as the red button is pressed, copy the source form onto the 
  25294.     display screen."
  25295.  
  25296.     [sensor redButtonPressed]
  25297.         whileTrue: 
  25298.             [form
  25299.                 displayOn: Display
  25300.                 at: self cursorPoint
  25301.                 clippingBox: view insetDisplayBox
  25302.                 rule: (Display depth > 1 ifTrue: [Form paint]
  25303.                                         ifFalse: [mode])
  25304.                 fillColor: color]!
  25305. reverseMode
  25306.     "Set the mode for the tools that copy the form onto the display to reverse. 
  25307.     Leaves the tool set in its previous state."
  25308.  
  25309.     mode _ Form reverse.
  25310.     tool _ previousTool!
  25311. setColor: aColor
  25312.     "Set the mask (color) to aColor.
  25313.     Hacked to invoke color chooser if not B/W screen.
  25314.     Leaves the tool set in its previous state."
  25315.  
  25316.     self normalizeColor:  (Display depth > 1
  25317.                             ifTrue: [Color fromUser]
  25318.                             ifFalse: [aColor]).
  25319.     tool _ previousTool!
  25320. singleCopy 
  25321.     "If the red button is clicked, copy the source form onto the display 
  25322.     screen."
  25323.  
  25324.     form
  25325.         displayOn: Display
  25326.         at: self cursorPoint
  25327.         clippingBox: view insetDisplayBox
  25328.         rule: (Display depth > 1 ifTrue: [Form paint]
  25329.                                         ifFalse: [mode])
  25330.         fillColor: color.
  25331.     sensor waitNoButton!
  25332. togglexGridding
  25333.     "Turn x (horizontal) gridding off, if it is on, and turns it on, if it is off. 
  25334.     Does not change the primary tool."
  25335.  
  25336.     xgridOn
  25337.         ifTrue: 
  25338.             [grid x: 1.
  25339.             xgridOn _ false]
  25340.         ifFalse: 
  25341.             [grid x: togglegrid x.
  25342.             xgridOn _ true].
  25343.     tool _ previousTool!
  25344. toggleyGridding
  25345.     "Turn y (vertical) gridding off, if it is on, and turns it on, if it is off. 
  25346.     Does not change the primary tool."
  25347.  
  25348.     ygridOn
  25349.         ifTrue: 
  25350.             [grid y: 1.
  25351.             ygridOn _ false]
  25352.         ifFalse: 
  25353.             [grid y: togglegrid y.
  25354.             ygridOn _ true].
  25355.     tool _ previousTool!
  25356. underMode
  25357.     "Set the mode for the tools that copy the form onto the display to under. 
  25358.     Leaves the tool set in its previous state."
  25359.  
  25360.     mode _ Form under.
  25361.     tool _ previousTool! !
  25362.  
  25363. !FormEditor methodsFor: 'menu messages'!
  25364. accept
  25365.     "The edited information should now be accepted by the view."
  25366.  
  25367.     view updateDisplay.
  25368.     view accept!
  25369. cancel
  25370.     "The edited information should be forgotten by the view."
  25371.  
  25372.     view cancel!
  25373. fileOut
  25374.     Cursor normal showWhile:
  25375.     [model writeOnFileNamed:
  25376.         (FillInTheBlank request: 'Enter file name'
  25377.                 initialAnswer: 'Filename.form')]
  25378. !
  25379. redButtonActivity 
  25380.     "Refer to the comment in MouseMenuController|redButtonActivity."
  25381.  
  25382.     self perform: tool! !
  25383.  
  25384. !FormEditor methodsFor: 'cursor'!
  25385. cursorPoint
  25386.     "Answer the mouse coordinate data gridded according to the receiver's 
  25387.     grid."
  25388.  
  25389.     ^sensor cursorPoint grid: grid! !
  25390.  
  25391. !FormEditor methodsFor: 'private'!
  25392. dragForm
  25393.  
  25394.     tool = #block
  25395.         ifTrue:
  25396.             [Cursor origin show.
  25397.             [sensor anyButtonPressed
  25398.                 or: [sensor keyboardPressed
  25399.                 or: [self viewHasCursor not]]]
  25400.                 whileFalse: [].
  25401.             ^self cursorPoint]
  25402.         ifFalse:
  25403.             [^self trackFormUntil:
  25404.                 [sensor anyButtonPressed
  25405.                     or: [sensor keyboardPressed
  25406.                     or: [self viewHasCursor not]]]]!
  25407. initializeYellowButtonMenu
  25408.  
  25409.     self yellowButtonMenu: YellowButtonMenu
  25410.         yellowButtonMessages: YellowButtonMessages!
  25411. normalizeColor: aColor
  25412.  
  25413.     unNormalizedColor _ aColor.
  25414.     color _ unNormalizedColor originate: view insetDisplayBox origin on: Display !
  25415. promptRequest: outputMessage 
  25416.     "Answers with a string typed by the user on the keyboard. keyboard
  25417.     input is terminated by a line feed character. Typing feedback happens
  25418.     in a window that is at least 100 bits wide and 50 bits high."
  25419.  
  25420.     | answer |
  25421.     FillInTheBlank
  25422.         request: outputMessage
  25423.         displayAt: view insetDisplayBox topCenter + (0@80)
  25424.         centered: true
  25425.         action: [:answer] 
  25426.         initialAnswer: ''.
  25427.     ^answer!
  25428. rubberBandFrom: startPoint until: aBlock
  25429.  
  25430.     | endPoint previousEndPoint |
  25431.     previousEndPoint _ startPoint.
  25432.     [aBlock value] whileFalse:
  25433.         [(endPoint _ self cursorPoint) = previousEndPoint 
  25434.             ifFalse:
  25435.             [(Line from: startPoint to: previousEndPoint withForm: form)
  25436.                 displayOn: Display
  25437.                 at: 0 @ 0
  25438.                 clippingBox: view insetDisplayBox
  25439.                 rule: Form reverse
  25440.                 fillColor: Display black.
  25441.             (Line from: startPoint to: endPoint withForm: form)
  25442.                 displayOn: Display
  25443.                 at: 0 @ 0
  25444.                 clippingBox: view insetDisplayBox
  25445.                 rule: Form reverse
  25446.                 fillColor: Display black.
  25447.             previousEndPoint  _ endPoint]].
  25448.     (Line from: startPoint to: previousEndPoint withForm: form)
  25449.         displayOn: Display
  25450.         at: 0 @ 0
  25451.         clippingBox: view insetDisplayBox
  25452.         rule: Form reverse
  25453.         fillColor: Display black.
  25454.     ^endPoint!
  25455. selectTool: aCharacter
  25456.     "A new tool has been selected. It is denoted by aCharacter. Set the tool.
  25457.     This code is written out in long hand (i.e., rather than dispatching on a
  25458.     table of options) so that it is obvious what is happening."
  25459.     
  25460.     aCharacter =  SingleCopyKey    ifTrue: [^#singleCopy].
  25461.     aCharacter =  RepeatCopyKey    ifTrue: [^#repeatCopy].
  25462.     aCharacter =  LineKey            ifTrue: [^#line].                    
  25463.     aCharacter =  CurveKey            ifTrue: [^#curve].                
  25464.     aCharacter =  BlockKey            ifTrue: [^#block].        
  25465.     aCharacter =  SelectKey            ifTrue: [^#newSourceForm].        
  25466.     aCharacter =  OverKey            ifTrue: [^#overMode].
  25467.     aCharacter =  UnderKey            ifTrue: [^#underMode].
  25468.     aCharacter =  ReverseKey        ifTrue: [^#reverseMode].
  25469.     aCharacter =  EraseKey            ifTrue: [^#eraseMode].
  25470.     aCharacter =  ChangeGridsKey    ifTrue: [^#changeGridding].
  25471.     aCharacter =  TogglexGridKey    ifTrue: [^#togglexGridding].
  25472.     aCharacter =  ToggleyGridKey    ifTrue: [^#toggleyGridding].
  25473.     aCharacter =  BitEditKey            ifTrue: [^#magnify].            
  25474.     aCharacter =  WhiteKey            ifTrue: [^#colorWhite].            
  25475.     aCharacter =  LightGrayKey        ifTrue: [^#colorLightGray].            
  25476.     aCharacter =  GrayKey            ifTrue: [^#colorGray].                
  25477.     aCharacter =  DarkGrayKey        ifTrue: [^#colorDarkGray].            
  25478.     aCharacter =  BlackKey            ifTrue: [^#colorBlack].                
  25479.     aCharacter =  OutKey            ifTrue: [^#fileOutForm].            
  25480.     aCharacter =  InKey                ifTrue: [^#fileInForm]!
  25481. setVariables
  25482.     tool _ #repeatCopy.
  25483.     previousTool _ tool.
  25484.     grid _ 1 @ 1.
  25485.     togglegrid _ 8 @ 8.
  25486.     xgridOn _ false.
  25487.     ygridOn _ false.
  25488.     mode _ Form over.
  25489.     form _ Form extent: 8 @ 8.
  25490.     form fillBlack.
  25491.     unNormalizedColor _ color _ Form black.
  25492. !
  25493. trackFormUntil: aBlock
  25494.  
  25495.     | previousPoint cursorPoint |
  25496.     previousPoint _ self cursorPoint.
  25497.     form displayOn: Display at: previousPoint rule: Form reverse.
  25498.     [aBlock value] whileFalse:
  25499.         [cursorPoint _ self cursorPoint.
  25500.         (FlashCursor or: [cursorPoint ~= previousPoint])
  25501.             ifTrue:
  25502.             [form displayOn: Display at: previousPoint rule: Form reverse.
  25503.             form displayOn: Display at: cursorPoint rule: Form reverse.
  25504.             previousPoint _ cursorPoint]].
  25505.     form displayOn: Display at: previousPoint rule: Form reverse.
  25506.     ^previousPoint! !
  25507. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  25508.  
  25509. FormEditor class
  25510.     instanceVariableNames: ''!
  25511.  
  25512. !FormEditor class methodsFor: 'class initialization'!
  25513. flashCursor: aBoolean
  25514.  
  25515.     FlashCursor _ aBoolean
  25516.  
  25517.     "FormEditor flashCursor: true"!
  25518. initialize
  25519.  
  25520.     FlashCursor _ false.
  25521.     self setKeyboardMap.
  25522.     YellowButtonMenu _ PopUpMenu labels: 'accept
  25523. cancel
  25524. file out' lines: #(2).
  25525.     YellowButtonMessages _ #(accept cancel fileOut)
  25526.  
  25527.     "FormEditor initialize"! !
  25528.  
  25529. !FormEditor class methodsFor: 'instance creation'!
  25530. openFullScreenForm
  25531.     "Create and schedule an instance of me on the form whose extent is the 
  25532.     extent of the display screen."
  25533.  
  25534.     | topView |
  25535.     topView _ self createFullScreenForm.
  25536.     topView controller 
  25537.         openDisplayAt: (topView viewport extent//2)
  25538.  
  25539.     "FormEditor openFullScreenForm."!
  25540. openOnForm: aForm
  25541.     "Create and schedule an instance of me on the form aForm."
  25542.  
  25543.     | topView |
  25544.     topView _ self createOnForm: aForm.
  25545.     topView controller open
  25546.  
  25547. ! !
  25548.  
  25549. !FormEditor class methodsFor: 'examples'!
  25550. formFromDisplay
  25551.     "Create an instance of me on a new form designated by the user at a
  25552.     location designated by the user."
  25553.  
  25554.     Form fromUser edit
  25555.  
  25556.     "FormEditor formFromDisplay"!
  25557. fullScreen
  25558.     "Create an instance of me on a new form that fills the full size of the
  25559.     display screen."
  25560.  
  25561.     FormEditor openFullScreenForm
  25562.  
  25563.     "FormEditor fullScreen"!
  25564. newForm
  25565.     "Create an instance of me on a new form at a location designated by the user. "
  25566.  
  25567.     (Form extent: 400 @ 200 depth: Display depth) edit
  25568.  
  25569.     "FormEditor newForm"! !
  25570.  
  25571. !FormEditor class methodsFor: 'private'!
  25572. createFullScreenForm
  25573.     "Create a StandardSystemView for a FormEditor on the form whole screen."
  25574.     | formView formEditor menuView topView extent aForm |
  25575.     aForm _ Form extent: (Display extent x @ (Display extent y - 112)) depth: Display depth.
  25576.     formView _ FormHolderView new model: aForm.
  25577.     formView borderWidthLeft: 0 right: 0 top: 0 bottom: 1.
  25578.     formEditor _ formView controller.
  25579.     menuView _ FormMenuView new makeFormEditorMenu model: formEditor.
  25580.     formEditor model: menuView controller.
  25581.     topView _ FormEditorView new.
  25582.     topView backgroundColor: #veryLightGray.
  25583.     topView model: aForm.
  25584.     topView addSubView: formView.
  25585.     topView 
  25586.         addSubView: menuView
  25587.         align: menuView viewport topCenter
  25588.         with: formView viewport bottomCenter + (0@16).
  25589.     topView window: 
  25590.         (formView viewport 
  25591.             merge: (menuView viewport expandBy: (16 @ 0 corner: 16@16))).
  25592.     topView label: 'Form Editor'.
  25593.     extent _ topView viewport extent.
  25594.     topView minimumSize: extent.
  25595.     topView maximumSize: extent.
  25596.     ^topView
  25597.  
  25598. !
  25599. createOnForm: aForm
  25600.     "Create a StandardSystemView for a FormEditor on the form aForm."
  25601.  
  25602.     | formView formEditor menuView aView topView extent topViewBorder |
  25603.     topViewBorder _ 2.
  25604.     formView _ FormHolderView new model: aForm.
  25605.     formEditor _ formView controller.
  25606.     menuView _ FormMenuView new makeFormEditorMenu model: formEditor.
  25607.     formEditor model: aForm.
  25608.     aView _ View new.
  25609.     aView model: aForm.
  25610.     aView addSubView: formView.
  25611.     aView 
  25612.         addSubView: menuView
  25613.         align: menuView viewport topCenter
  25614.         with: formView viewport bottomCenter + (0@16).
  25615.     aView window: 
  25616.         ((formView viewport 
  25617.             merge: (menuView viewport expandBy: (16 @ 0 corner: 16@16))) 
  25618.           expandBy: (0@topViewBorder corner: 0@0)).
  25619.     aView window extent > formView viewport extent
  25620.         ifTrue: [formView borderWidthLeft: 1 right: 1 top: 0 bottom: 1]
  25621.         ifFalse: [formView borderWidthLeft: 0 right: 0 top: 0 bottom: 1].
  25622.     topView _ FormEditorView new.
  25623.     topView backgroundColor: #veryLightGray.
  25624.     topView addSubView: aView.
  25625.     topView label: 'Form Editor'.
  25626.     topView borderWidth: topViewBorder.
  25627.     extent _ topView viewport extent.
  25628.     topView minimumSize: extent.
  25629.     topView maximumSize: extent.
  25630.     ^topView!
  25631. setKeyboardMap
  25632.     "Keyboard Mapping."
  25633.  
  25634.     SelectKey_$a.
  25635.     SingleCopyKey_$s.            "tools"
  25636.     RepeatCopyKey_$d.
  25637.     LineKey_$f.
  25638.     CurveKey_$g.
  25639.     BlockKey_$h.
  25640.     OverKey_$j.                "modes"
  25641.     UnderKey_$k.
  25642.     ReverseKey_$l.
  25643.     EraseKey_$;.
  25644.     InKey_$'.                    "file In"
  25645.     BitEditKey_$z.
  25646.     WhiteKey_$x.                "colors"
  25647.     LightGrayKey_$c.
  25648.     GrayKey_$v.
  25649.     DarkGrayKey_$b.
  25650.     BlackKey_$n.
  25651.     TogglexGridKey_$m.        "gridding"
  25652.     ToggleyGridKey_$,.
  25653.     ChangeGridsKey_$..
  25654.     OutKey_$/                    "file Out"! !
  25655.  
  25656. FormEditor initialize!
  25657. StandardSystemView subclass: #FormEditorView
  25658.     instanceVariableNames: ''
  25659.     classVariableNames: ''
  25660.     poolDictionaries: ''
  25661.     category: 'Graphics-Editors'!
  25662.  
  25663. !FormEditorView methodsFor: 'as yet unclassified'!
  25664. cacheBitsAsTwoTone
  25665.     ^ false! !FormView subclass: #FormHolderView
  25666.     instanceVariableNames: 'displayedForm '
  25667.     classVariableNames: ''
  25668.     poolDictionaries: ''
  25669.     category: 'Graphics-Views'!
  25670. FormHolderView comment:
  25671. 'I represent a view of a Form. Editing takes place by modifying a working version of the Form. The message accept is used to copy the working version into the Form; the message cancel copies the Form into the working version.'!
  25672.  
  25673. !FormHolderView methodsFor: 'initialize-release'!
  25674. release
  25675.  
  25676.     super release.
  25677.     displayedForm release.
  25678.     displayedForm _ nil! !
  25679.  
  25680. !FormHolderView methodsFor: 'model access'!
  25681. changeValueAt: location put: anInteger 
  25682.     "Refer to the comment in FormView|changeValueAt:put:."
  25683.  
  25684.     displayedForm pixelValueAt: location put: anInteger.
  25685.     displayedForm changed: self!
  25686. model: aForm
  25687.  
  25688.     super model: aForm.
  25689.     displayedForm _ aForm deepCopy!
  25690. workingForm
  25691.     "Answer the form that is currently being displayed--the working version 
  25692.     in which edits are carried out."
  25693.  
  25694.     ^displayedForm! !
  25695.  
  25696. !FormHolderView methodsFor: 'displaying'!
  25697. displayView 
  25698.     "Display the Form associated with this View according to the rule and
  25699.     fillColor specifed by this class."
  25700.  
  25701.     | oldOffset |
  25702.     oldOffset _ displayedForm offset.
  25703.     displayedForm offset: 0@0.
  25704.     displayedForm
  25705.         displayOn: Display
  25706.         transformation: self displayTransformation
  25707.         clippingBox: self insetDisplayBox
  25708.         rule: self rule
  25709.         fillColor: self fillColor.
  25710.     displayedForm offset: oldOffset!
  25711. updateDisplay
  25712.     "The working version is redefined by copying the bits displayed in the 
  25713.     receiver's display area."
  25714.  
  25715.     displayedForm fromDisplay: self displayBox.
  25716.     displayedForm changed: self! !
  25717.  
  25718. !FormHolderView methodsFor: 'menu messages'!
  25719. accept 
  25720.     "Refer to the comment in FormView|accept."
  25721.     model
  25722.         copyBits: displayedForm boundingBox
  25723.         from: displayedForm
  25724.         at: 0 @ 0
  25725.         clippingBox: model boundingBox
  25726.         rule: Form over
  25727.         fillColor: nil.
  25728.     model changed: self!
  25729. cancel 
  25730.     "Refer to the comment in FormView|cancel."
  25731.  
  25732.     displayedForm become: model deepCopy.
  25733.     displayedForm changed: self.
  25734.     self display! !FormView subclass: #FormInspectView
  25735.     instanceVariableNames: 'offset '
  25736.     classVariableNames: ''
  25737.     poolDictionaries: ''
  25738.     category: 'Graphics-Views'!
  25739.  
  25740. !FormInspectView methodsFor: 'as yet unclassified'!
  25741. defaultControllerClass 
  25742.     "Refer to the comment in View|defaultControllerClass."
  25743.  
  25744.     ^  NoController!
  25745. displayTranformation
  25746.     displayTransformation == nil
  25747.         ifTrue: [displayTransformation _ self computeDisplayTransformation].
  25748.     displayTransformation setScale: 1@1 translation: displayTransformation translation.
  25749.     ^ displayTransformation!
  25750. displayView 
  25751.     "Display the form as a value in an inspector.  8/11/96 sw"
  25752.     "Defeated form scaling for HS FormInspector.  8/20/96 di"
  25753.     | oldOffset |
  25754.     Display fill: self insetDisplayBox fillColor: Color white.
  25755.     model selectionIndex == 0 ifTrue: [^ self].
  25756.     oldOffset _ model selection offset.
  25757.     offset == nil ifFalse: [model selection offset: offset asPoint].
  25758.     model selection
  25759.         displayOn: Display
  25760.         transformation: (WindowingTransformation
  25761.             scale: 1@1
  25762.             translation: self displayTransformation translation)
  25763.         clippingBox: self insetDisplayBox
  25764.         rule: self rule
  25765.         fillColor: self fillColor.
  25766.     model selection offset: oldOffset!
  25767. lock
  25768.     super lock.
  25769.     displayTransformation  setScale: 1@1 translation: displayTransformation translation!
  25770. offset: anOffset
  25771.     offset _ anOffset! !Controller subclass: #FormMenuController
  25772.     instanceVariableNames: ''
  25773.     classVariableNames: ''
  25774.     poolDictionaries: ''
  25775.     category: 'Graphics-Editors'!
  25776. FormMenuController comment:
  25777. 'I represent a Controller that takes control if a key on the keyboard is depressed or if the cursor is within my rectangular area.'!
  25778.  
  25779. !FormMenuController methodsFor: 'control defaults'!
  25780. controlActivity
  25781.     "Pass control to a subView corresponding to a pressed keyboard key or to
  25782.     a mouse button pressed, if any."
  25783.  
  25784.     sensor keyboardPressed
  25785.         ifTrue: [self processMenuKey]
  25786.         ifFalse: [self controlToNextLevel]!
  25787. isControlActive
  25788.     "Answer false if the blue mouse button is pressed and the cursor is
  25789.     outside of the inset display box of the Controller's view; answer true,
  25790.     otherwise."
  25791.  
  25792.     ^sensor keyboardPressed |
  25793.         (view containsPoint: sensor cursorPoint) & sensor blueButtonPressed not!
  25794. isControlWanted
  25795.     "Answer true if the cursor is inside the inset display box (see 
  25796.     View|insetDisplayBox) of the receiver's view, and answer false, 
  25797.     otherwise. It is sent by Controller|controlNextLevel in order to determine 
  25798.     whether or not control should be passed to this receiver from the
  25799.     Controller of the superView of this receiver's view."
  25800.  
  25801.     ^sensor keyboardPressed | self viewHasCursor!
  25802. processMenuKey
  25803.     "The user typed a key on the keyboard. Give control to the subView that 
  25804.     is selected by this key."
  25805.  
  25806.     | aView |
  25807.     aView _ view subViewContainingCharacter: sensor keyboard.
  25808.     aView ~~ nil
  25809.         ifTrue: [aView controller sendMessage]! !View subclass: #FormMenuView
  25810.     instanceVariableNames: ''
  25811.     classVariableNames: 'BorderForm SpecialBorderForm FormButtons '
  25812.     poolDictionaries: ''
  25813.     category: 'Graphics-Editors'!
  25814. FormMenuView comment:
  25815. 'I represent a View whose subViews are Switches (and Buttons and OneOnSwitches) whose actions set the mode, color, and tool for editing a Form on the screen. The default controller of my instances is FormMenuController.'!
  25816.  
  25817. !FormMenuView methodsFor: 'initialize-release'!
  25818. makeFormEditorMenu
  25819.  
  25820.     | button buttonCache form aSwitchView aSwitchController|
  25821.     "Now get those forms into the subviews"
  25822.     self makeButton: 1.                    "form source"
  25823.     self makeConnections: (2 to: 6).        "tools"
  25824.     self makeConnections: (7 to: 10).        "modes"
  25825.     self makeButton: 11.                    "filing in"
  25826.     self makeButton: 12.                    "bit editing"
  25827.     self makeColorConnections: (13 to: 17).        "colors"
  25828.     self makeGridSwitch: 18.                    "toggle x"
  25829.     self makeGridSwitch: 19.                    "toggle y"
  25830.     self makeButton: 20.                    "setting grid"
  25831.     self makeButton: 21                    "filing out"! !
  25832.  
  25833. !FormMenuView methodsFor: 'subView access'!
  25834. subViewContainingCharacter: aCharacter
  25835.     "Answer the receiver's subView that corresponds to the key, aCharacter. 
  25836.     Answer nil if no subView is selected by aCharacter."
  25837.  
  25838.     self subViews reverseDo: 
  25839.         [:aSubView |
  25840.         (aSubView containsKey: aCharacter) ifTrue: [^aSubView]].
  25841.     ^nil    
  25842. ! !
  25843.  
  25844. !FormMenuView methodsFor: 'controller access'!
  25845. defaultControllerClass 
  25846.     "Refer to the comment in View|defaultControllerClass."
  25847.  
  25848.     ^FormMenuController! !
  25849.  
  25850. !FormMenuView methodsFor: 'private'!
  25851. makeButton: index
  25852.  
  25853.     | button buttonCache aSwitchView|
  25854.     buttonCache _ FormButtons at: index.
  25855.     button _ Button newOff.
  25856.     button onAction: [model changeTool: buttonCache value].
  25857.     aSwitchView _ self makeViews: buttonCache for: button.
  25858.     aSwitchView controller: IndicatorOnSwitchController new!
  25859. makeColorConnections: indexInterval
  25860.  
  25861.     | connector button buttonCache aSwitchView |
  25862.     connector _ Object new.        "A dummy model for connecting dependents"
  25863.     indexInterval do:
  25864.         [:index |
  25865.         buttonCache _ FormButtons at: index.
  25866.         buttonCache initialState = #true
  25867.             ifTrue: [button _ OneOnSwitch newOn]
  25868.             ifFalse: [button _ OneOnSwitch newOff].
  25869.         button onAction: [model changeTool: buttonCache value].
  25870.         button connection: connector.
  25871.         aSwitchView _ self makeViews: buttonCache for: button.
  25872.         aSwitchView highlightForm: BorderForm.
  25873.         aSwitchView borderWidthLeft: 1 right: 0 top: 1 bottom: 1.
  25874.         aSwitchView controller selector: #turnOn].
  25875.     aSwitchView highlightForm: SpecialBorderForm.
  25876.     aSwitchView borderWidth: 1!
  25877. makeConnections: indexInterval
  25878.  
  25879.     | connector button buttonCache aSwitchView |
  25880.     connector _ Object new.        "A dummy model for connecting dependents."
  25881.     indexInterval do:
  25882.         [:index |
  25883.         buttonCache _ FormButtons at: index.
  25884.         buttonCache initialState = #true
  25885.             ifTrue: [button _ OneOnSwitch newOn]
  25886.             ifFalse: [button _ OneOnSwitch newOff].
  25887.         button onAction: [model changeTool: buttonCache value].
  25888.         button connection: connector.
  25889.         aSwitchView _ self makeViews: buttonCache for: button.
  25890.         aSwitchView borderWidthLeft: 1 right: 0 top: 1 bottom: 1.
  25891.         aSwitchView controller selector: #turnOn].
  25892.     aSwitchView borderWidth: 1!
  25893. makeGridSwitch: index
  25894.  
  25895.     | button buttonCache |
  25896.     buttonCache _ FormButtons at: index.
  25897.     buttonCache initialState = #true
  25898.         ifTrue: [button _ Switch newOn]
  25899.         ifFalse: [button _ Switch newOff].
  25900.     button onAction: [model changeTool: buttonCache value].
  25901.     button offAction: [model changeTool: buttonCache value].
  25902.     self makeViews: buttonCache for: button!
  25903. makeSwitch: index
  25904.  
  25905.     | button buttonCache |
  25906.     buttonCache _ FormButtons at: index.
  25907.     buttonCache initialState = #true
  25908.         ifTrue: [button _ Switch newOn]
  25909.         ifFalse: [button _ Switch newOff].
  25910.     button onAction: [model changeTool: buttonCache value].
  25911.     self makeViews: buttonCache for: button!
  25912. makeViews: cache for: aSwitch
  25913.  
  25914.     | form aSwitchView |
  25915.     form _ cache form.
  25916.     aSwitchView _ SwitchView new model: aSwitch.
  25917.     aSwitchView key: cache value.
  25918.     aSwitchView label: form.
  25919.     aSwitchView window: (0@0 extent: form extent).
  25920.     aSwitchView translateBy: cache offset.
  25921.     aSwitchView borderWidth: 1.
  25922.     self addSubView: aSwitchView.
  25923.     ^aSwitchView! !
  25924. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  25925.  
  25926. FormMenuView class
  25927.     instanceVariableNames: ''!
  25928.  
  25929. !FormMenuView class methodsFor: 'class initialization'!
  25930. fileOut   "FormMenuView fileOut"
  25931.     "Save the FormEditor icons"
  25932.     | names |
  25933.     names _ 
  25934.         #('select.form.' 'singlecopy.form.' 'repeatcopy.form.' 'line.form.' 'curve.form.'
  25935.         'block.form' 'over.form.' 'under.form.' 'reverse.form.' 'erase.form.' 'in.form.'
  25936.         'magnify.form.' 'white.form' 'lightgray.form' 'gray.form' 'darkgray.form' 'black.form'
  25937.         'xgrid.form.' 'ygrid.form.' 'togglegrids.form.' 'out.form.' ).
  25938.     1 to: 21 do:  [:i |  (FormButtons at: i) writeOn: (names at: i)].
  25939.     SpecialBorderForm writeOn: 'specialborderform.form'.
  25940.     BorderForm writeOn: 'borderform.form'!
  25941. initialize
  25942.     "The forms for the menu are typically stored on files. In order to avoid
  25943.     reading them every time, they are stored in a collection that is a class
  25944.     variable, along with the offset, tool value, and initial visual state (on or
  25945.     off), that makes up the view of the form in the menu view."
  25946.  
  25947.     | offsets keys names formButton states |
  25948.     offsets _ OrderedCollection new: 21.
  25949.     #( 0 64 96 128 160 192 256 288 320 352 420) do: [:i | offsets addLast: i@0]. "First row"
  25950.     #( 0 64 96 128 160 192 256 304 352 420) do: [:i | offsets addLast: i@48].        "Second row"
  25951.     offsets _ offsets asArray.
  25952.     keys _ #($a $s $d $f $g $h $j $k $l $; $' $z $x $c $v $b $n $m $, $. $/ ).    "Keyboard"
  25953.     states _
  25954.         #(false false true false false false true false false false false false false
  25955.         false false false true false false false false ).        "Initial states of buttons"
  25956.     names _ 
  25957.         #('select.form.' 'singlecopy.form.' 'repeatcopy.form.' 'line.form.' 'curve.form.'
  25958.         'block.form' 'over.form.' 'under.form.' 'reverse.form.' 'erase.form.' 'in.form.'
  25959.         'magnify.form.' 'white.form' 'lightgray.form' 'gray.form' 'darkgray.form' 'black.form'
  25960.         'xgrid.form.' 'ygrid.form.' 'togglegrids.form.' 'out.form.' ).    "Files of button images"
  25961.     FormButtons _ OrderedCollection new.
  25962.     1 to: 21 do: 
  25963.         [:index | 
  25964.         formButton _ FormButtonCache new.
  25965.         formButton form: (Form readFromFileNamed: (names at: index)).
  25966.         formButton offset: (offsets at: index).
  25967.         formButton value: (keys at: index).
  25968.         formButton initialState: (states at: index).
  25969.         FormButtons addLast: formButton].
  25970.     SpecialBorderForm  _ Form readFromFileNamed: 'specialborderform.form'.
  25971.     BorderForm _ Form readFromFileNamed: 'borderform.form'
  25972.  
  25973.     "FormMenuView initialize"! !
  25974.  
  25975. FormMenuView initialize!
  25976. View subclass: #FormView
  25977.     instanceVariableNames: 'rule mask '
  25978.     classVariableNames: ''
  25979.     poolDictionaries: ''
  25980.     category: 'Graphics-Views'!
  25981. FormView comment:
  25982. 'I represent a view of a Form.'!
  25983.  
  25984. !FormView methodsFor: 'accessing'!
  25985. fillColor
  25986.     "Answer an instance of class Form that is the mask used when displaying 
  25987.     the receiver's model (a Form) on the display screen (see BitBlt for the 
  25988.     meaning of this mask)."
  25989.  
  25990.     ^ mask!
  25991. fillColor: aForm 
  25992.     "Set the display mask for displaying the receiver's model to be the 
  25993.     argument, aForm."
  25994.  
  25995.     mask _ aForm!
  25996. mask
  25997.     "Answer an instance of class Form that is the mask used when displaying 
  25998.     the receiver's model (a Form) on the display screen (see BitBlt for the 
  25999.     meaning of this mask)."
  26000.  
  26001.     ^ mask!
  26002. rule
  26003.     "Answer a number from 0 to 15 that indicates which of the sixteen 
  26004.     display rules (logical function of two boolean values) is to be used when 
  26005.     copying the receiver's model (a Form) onto the display screen."
  26006.  
  26007.     rule == nil
  26008.         ifTrue: [^self defaultRule]
  26009.         ifFalse: [^rule]!
  26010. rule: anInteger 
  26011.     "Set the display rule for the receiver to be the argument, anInteger."
  26012.  
  26013.     rule _ anInteger! !
  26014.  
  26015. !FormView methodsFor: 'controller access'!
  26016. defaultControllerClass 
  26017.     "Refer to the comment in View|defaultControllerClass."
  26018.  
  26019.     ^  FormEditor! !
  26020.  
  26021. !FormView methodsFor: 'model access'!
  26022. changeValueAt: location put: anInteger
  26023.     "The receiver's model is a form which has an array of bits. Change the 
  26024.     bit at index, location, to be anInteger (either 1 or 0). Inform all objects 
  26025.     that depend on the model that it has changed."
  26026.  
  26027.     model pixelValueAt: location put: anInteger.
  26028.     model changed: self! !
  26029.  
  26030. !FormView methodsFor: 'window access'!
  26031. defaultWindow 
  26032.     "Refer to the comment in View|defaultWindow."
  26033.  
  26034.     ^(Rectangle origin: 0 @ 0 extent: model extent)
  26035.         expandBy: borderWidth!
  26036. windowBox
  26037.     "For comaptibility with Control manager (see senders)"
  26038.     ^ self insetDisplayBox! !
  26039.  
  26040. !FormView methodsFor: 'displaying'!
  26041. displayOn: aPort
  26042.     model displayOnPort: aPort at: self displayBox origin!
  26043. displayView 
  26044.     "Refer to the comment in View|displayView."
  26045.  
  26046.     | oldOffset |
  26047.     super displayView.
  26048.     insideColor == nil ifFalse: [Display fill: self insetDisplayBox fillColor: insideColor].
  26049.     oldOffset _ model offset.
  26050.     model offset: 0@0.
  26051.     model
  26052.         displayOn: Display
  26053.         transformation: self displayTransformation
  26054.         clippingBox: self insetDisplayBox
  26055.         rule: self rule
  26056.         fillColor: self fillColor.
  26057.     model offset: oldOffset!
  26058. uncacheBits
  26059.     "Placed vacuously here so that when ControlManager>>restore calls uncacheBits for a project with no windows, we don't hang.  1/24/96 sw"! !
  26060.  
  26061. !FormView methodsFor: 'updating'!
  26062. update: aFormView 
  26063.     "Refer to the comment in View|update:."
  26064.  
  26065.     self == aFormView ifFalse: [self display]! !
  26066.  
  26067. !FormView methodsFor: 'menu messages'!
  26068. accept
  26069.     "The receiver's model is set to the working version, the one in which 
  26070.     edits are carried out."
  26071.  
  26072.     ^self!
  26073. cancel
  26074.     "Set the working form to be a copy of the model."
  26075.  
  26076.     ^self! !
  26077.  
  26078. !FormView methodsFor: 'private'!
  26079. defaultRule 
  26080.     "The default display rule is 3=over or storing."
  26081.  
  26082.     ^Form over! !
  26083. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  26084.  
  26085. FormView class
  26086.     instanceVariableNames: ''!
  26087.  
  26088. !FormView class methodsFor: 'examples'!
  26089. exampleOne
  26090.     "Frame a Form (specified by the user) with a border of 2 bits in width and display it offset 60 x 40 from the cornor of the display screen. "
  26091.     | f view |
  26092.     f _ Form fromUser.
  26093.     view _ self new model: f.
  26094.     view translateBy: 60 @ 40.
  26095.     view borderWidth: 2.
  26096.     view display.
  26097.     view release
  26098.  
  26099.     "FormView exampleOne"!
  26100. exampleTwo
  26101.     "Frame a Form (specified by the user) that is scaled by 2. The border is 2 bits in width. Displays at location 60, 40."
  26102.     | f view |
  26103.     f _ Form fromUser.
  26104.     view _ self new model: f.
  26105.     view scaleBy: 2.0.
  26106.     view translateBy: 60 @ 40.
  26107.     view borderWidth: 2.
  26108.     view display.
  26109.     view release
  26110.  
  26111.     "FormView exampleTwo"! !Number subclass: #Fraction
  26112.     instanceVariableNames: 'numerator denominator '
  26113.     classVariableNames: ''
  26114.     poolDictionaries: ''
  26115.     category: 'Numeric-Numbers'!
  26116. Fraction comment:
  26117. 'I represent some rational number as a fraction. All public arithmetic operations answer reduced fractions.'!
  26118.  
  26119. !Fraction methodsFor: 'arithmetic'!
  26120. * aFraction
  26121.  
  26122.     (aFraction isMemberOf: Fraction)
  26123.         ifTrue: [^(Fraction 
  26124.                     numerator: numerator * aFraction 
  26125.     "Refer to the comment in Number|*." numerator
  26126.                     denominator: denominator * aFraction denominator)
  26127.                     reduced]
  26128.         ifFalse: [^self retry: #* coercing: aFraction]!
  26129. + aFraction
  26130.  
  26131.     | commonDenominator newNumerator |
  26132.     (aFraction isMemberOf: Fraction)
  26133.         ifTrue: 
  26134.             [denominator = aFraction 
  26135.     "Refer to the comment in Number|+." denominator 
  26136.                 ifTrue: [^(Fraction 
  26137.                             numerator: numerator + aFraction numerator
  26138.                             denominator: denominator) reduced].
  26139.             commonDenominator _ denominator lcm: aFraction denominator.
  26140.             newNumerator _ numerator 
  26141.                                 * (commonDenominator / denominator) 
  26142.                                 + (aFraction numerator * 
  26143.                                     (commonDenominator / aFraction denominator)).
  26144.             ^(Fraction 
  26145.                 numerator: newNumerator 
  26146.                 denominator: commonDenominator) reduced]
  26147.         ifFalse: [^self retry: #+ coercing: aFraction]!
  26148. - aFraction
  26149.  
  26150.     (aFraction isMemberOf: Fraction)
  26151.         ifTrue: [^self + aFraction 
  26152.     "Refer to the comment in Number|-." negated]
  26153.         ifFalse: [^self retry: #- coercing: aFraction]!
  26154. / aFraction
  26155.  
  26156.     (aFraction isMemberOf: Fraction)
  26157.         ifTrue: [^self * aFraction 
  26158.     "Refer to the comment in Number|/." reciprocal]
  26159.         ifFalse: [^self retry: #/ coercing: aFraction]!
  26160. negated 
  26161.     "Refer to the comment in Number|negated."
  26162.  
  26163.     ^Fraction numerator: numerator negated denominator: denominator!
  26164. reciprocal 
  26165.     "Refer to the comment in Number|reciprocal."
  26166.  
  26167.     numerator = 0 ifTrue: [self error: '0 has no reciprocal'].
  26168.     numerator = 1 ifTrue: [^denominator].
  26169.     numerator = -1 ifTrue: [^denominator negated].
  26170.     ^Fraction numerator: denominator denominator: numerator! !
  26171.  
  26172. !Fraction methodsFor: 'comparing'!
  26173. < aFraction
  26174.  
  26175.     (aFraction isMemberOf: Fraction)
  26176.         ifTrue: [aFraction numerator = 0
  26177.                 ifTrue: [^numerator < 0]
  26178.                 ifFalse: [^self - aFraction < 0]]
  26179.         ifFalse: [^self retry: #< coercing: aFraction]!
  26180. = aFraction
  26181.  
  26182.     aFraction isNil ifTrue: [^false].
  26183.     (aFraction isMemberOf: Fraction)
  26184.         ifTrue: [aFraction numerator = 0
  26185.                 ifTrue: [^numerator = 0]
  26186.                 ifFalse: [^aFraction numerator = numerator 
  26187.                             and: [aFraction denominator = denominator]]]
  26188.         ifFalse: [^self retry: #= coercing: aFraction]!
  26189. hash
  26190.     "Hash is reimplemented because = is implemented."
  26191.  
  26192.     ^numerator bitXor: denominator! !
  26193.  
  26194. !Fraction methodsFor: 'truncation and round off'!
  26195. truncated 
  26196.     "Refer to the comment in Number|truncated."
  26197.  
  26198.     ^numerator quo: denominator! !
  26199.  
  26200. !Fraction methodsFor: 'coercing'!
  26201. coerce: aNumber 
  26202.     "Refer to the comment in Number|coerce:."
  26203.  
  26204.     ^aNumber asFraction!
  26205. generality 
  26206.     "Refer to the comment in Number|generality."
  26207.  
  26208.     ^60! !
  26209.  
  26210. !Fraction methodsFor: 'converting'!
  26211. asFloat
  26212.     "Answer a Float that represents the same value as does the receiver."
  26213.  
  26214.     ^numerator asFloat / denominator asFloat!
  26215. asFraction    
  26216.     "Answer the receiver itself."
  26217.  
  26218.     ^self! !
  26219.  
  26220. !Fraction methodsFor: 'printing'!
  26221. printOn: aStream
  26222.     self asFloat printOn: aStream
  26223.     "aStream nextPut: $(.
  26224.     numerator printOn: aStream.
  26225.     aStream nextPut: $/.
  26226.     denominator printOn: aStream.
  26227.     aStream nextPut: $)"! !
  26228.  
  26229. !Fraction methodsFor: 'private'!
  26230. denominator
  26231.  
  26232.     ^denominator!
  26233. numerator
  26234.  
  26235.     ^numerator!
  26236. reduced
  26237.  
  26238.     | gcd numer denom |
  26239.     numerator = 0 ifTrue: [^0].
  26240.     gcd _ numerator gcd: denominator.
  26241.     numer _ numerator // gcd.
  26242.     denom _ denominator // gcd.
  26243.     denom = 1 ifTrue: [^numer].
  26244.     ^Fraction numerator: numer denominator: denom!
  26245. setNumerator: n denominator: d
  26246.  
  26247.     d = 0
  26248.         ifTrue: [self error: 'denominator cannot be zero']
  26249.         ifFalse: 
  26250.             [numerator _ n asInteger.
  26251.             denominator _ d asInteger abs. "keep sign in numerator"
  26252.             d < 0 ifTrue: [numerator _ numerator negated]]! !
  26253. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  26254.  
  26255. Fraction class
  26256.     instanceVariableNames: ''!
  26257.  
  26258. !Fraction class methodsFor: 'instance creation'!
  26259. numerator: numInteger denominator: denInteger 
  26260.     "Answer an instance of me (denInteger/numInteger)."
  26261.  
  26262.     ^self new setNumerator: numInteger denominator: denInteger! !ListController subclass: #GeneralListController
  26263.     instanceVariableNames: ''
  26264.     classVariableNames: ''
  26265.     poolDictionaries: ''
  26266.     category: 'Interface-Support'!
  26267.  
  26268. !GeneralListController methodsFor: 'menu messages'!
  26269. aReadThis
  26270.     "When a list pane in a complex window has fairly simple action, you can use an instance of GeneralListController directly.  You don't need to make a separate class for your kind of list pane.
  26271.     The model makes and holds the YellowButtonMenu and the YellowButtonMessages and submits them to this instance using yellowButtonMenu: aSystemMenu yellowButtonMessages: anArray.  Having specialized menus is the usual reason for a new subclass for each pane.
  26272.     When the user clicks on a list item, redButtonActivity sends changeModelSelection: which sends toggleListIndex: to the model.
  26273.     "!
  26274. menuMessageReceiver
  26275.     "Send all menu messages to the model!!"
  26276.     ^ model! !ListView subclass: #GeneralListView
  26277.     instanceVariableNames: 'controllerClass '
  26278.     classVariableNames: ''
  26279.     poolDictionaries: ''
  26280.     category: 'Interface-Support'!
  26281.  
  26282. !GeneralListView methodsFor: 'everything'!
  26283. aReadThis
  26284.     "When a list pane in a complex window has fairl simple action, you can use an instance of GeneralListView directly.  You don't need to make a separate class for your kind of list pane.
  26285.     The usual reason for having a special class is to supply the default controller class.  Here we normally us GeneralListController.  However, the user can submit his own class to controllerClass: and use that."!
  26286. controllerClass: anObject
  26287.     controllerClass _ anObject!
  26288. defaultControllerClass 
  26289.     "Refer to the comment in View|defaultControllerClass."
  26290.  
  26291.     controllerClass == nil ifTrue: [self error: 'No one told me about my controller'].
  26292.     ^controllerClass!
  26293. emphasizeView
  26294.     "Give the model a chance to update its parts"
  26295.     model changed: #emphasize.
  26296. ! !OrderedCollection variableSubclass: #GraphicSymbol
  26297.     instanceVariableNames: ''
  26298.     classVariableNames: ''
  26299.     poolDictionaries: ''
  26300.     category: 'Graphics-Symbols'!
  26301. GraphicSymbol comment:
  26302. 'I represent a structured picture built from primitive display objects and other instances of me.'!
  26303.  
  26304. !GraphicSymbol methodsFor: 'displaying'!
  26305. displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm 
  26306.     "Display the receiver on the Display where aTransformation is provided 
  26307.     as an argument, rule is anInteger and mask is aForm. No translation. 
  26308.     Information to be displayed must be confined to the area that intersects 
  26309.     with clipRect."
  26310.  
  26311.     self do: 
  26312.         [:element | 
  26313.         element
  26314.             displayOn: aDisplayMedium
  26315.             transformation: aTransformation
  26316.             clippingBox: clipRect
  26317.             rule: anInteger
  26318.             fillColor: aForm]!
  26319. displayTransformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
  26320.     "Display the receiver where aTransformation is provided as an argument, 
  26321.     rule is anInteger and mask is aForm. No translation. Information to be 
  26322.     displayed must be confined to the area that intersects with clipRect."
  26323.  
  26324.     self displayOn: Display transformation: aTransformation clippingBox: clipRect
  26325.         rule: anInteger fillColor: aForm! !Object subclass: #GraphicSymbolInstance
  26326.     instanceVariableNames: 'transformation graphicSymbol '
  26327.     classVariableNames: ''
  26328.     poolDictionaries: ''
  26329.     category: 'Graphics-Symbols'!
  26330. GraphicSymbolInstance comment:
  26331. 'I represent a display transformation of a GraphicSymbol. Multiple copies of a GraphicSymbol can be displayed at different positions and scales on the screen by making appropriate, multiple, instances of me.'!
  26332.  
  26333. !GraphicSymbolInstance methodsFor: 'accessing'!
  26334. graphicSymbol
  26335.     "Answer the graphic symbol that the receiver displays."
  26336.  
  26337.     ^graphicSymbol!
  26338. graphicSymbol: aGraphicSymbol 
  26339.     "Set the argument, aGraphicSymbol, to be the graphic symbol that the 
  26340.     receiver displays."
  26341.  
  26342.     graphicSymbol _ aGraphicSymbol! !
  26343.  
  26344. !GraphicSymbolInstance methodsFor: 'transforming'!
  26345. transformation
  26346.     "Answer the receiver's display transformation."
  26347.  
  26348.     ^transformation!
  26349. transformation: aWindowingTransformation 
  26350.     "Set the argument, aWindowingTransformation, to be the receiver's 
  26351.     display transformation."
  26352.  
  26353.     transformation _ aWindowingTransformation! !
  26354.  
  26355. !GraphicSymbolInstance methodsFor: 'displaying'!
  26356. displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm 
  26357.     "Display the graphic symbol on the Display according to the arguments 
  26358.     of this message."
  26359.  
  26360.     graphicSymbol
  26361.         displayOn: aDisplayMedium
  26362.         transformation: (aTransformation compose: transformation)
  26363.         clippingBox: clipRect
  26364.         rule: anInteger
  26365.         fillColor: aForm!
  26366. displayTransformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
  26367.     "Display the graphic symbol according to the arguments of this message."
  26368.  
  26369.     self displayOn: Display transformation: aTransformation clippingBox: clipRect
  26370.         rule: anInteger fillColor: aForm! !
  26371. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  26372.  
  26373. GraphicSymbolInstance class
  26374.     instanceVariableNames: ''!
  26375.  
  26376. !GraphicSymbolInstance class methodsFor: 'examples'!
  26377. example
  26378.     "Simply evaluate the method and two GraphicSymbolInstances, each
  26379.     displaying a transformation of the same graphic symbol, will be
  26380.     presented on the screen. Clears the screen to white."
  26381.  
  26382.     | gate instance1 instance2 trans1 trans2 line arc f|
  26383.     Display fillWhite.            "clear the Screen."
  26384.     f _ Form extent: 2@2.
  26385.     f fillBlack.
  26386.     gate_ GraphicSymbol new.        "make a logic gate out of lines and arcs."
  26387.     line_Line new.  line beginPoint: -20@-20.  line endPoint: 0@-20. line form: f.
  26388.     gate add: line.
  26389.  
  26390.     line_Line new.  line beginPoint: -20@20.  line endPoint: 0@20. line form: f.
  26391.     gate add: line.
  26392.  
  26393.     line_Line new.  line beginPoint: 0@-40.  line endPoint: 0@40. line form: f.
  26394.     gate add: line.
  26395.  
  26396.     arc _ Arc new. arc center: 0@0 radius: 40 quadrant: 1.
  26397.     arc form: f.
  26398.     gate add: arc.
  26399.  
  26400.     arc _ Arc new. arc center: 0@0 radius: 40 quadrant: 4.
  26401.     arc form: f.
  26402.     gate add: arc.
  26403.  
  26404.             "one instance at 1/2 scale."
  26405.     trans1_WindowingTransformation identity.    
  26406.     trans1_ trans1 scaleBy: 0.5@0.5.
  26407.     trans1_ trans1 translateBy: 100@100.
  26408.  
  26409.             "the other instance at 2 times scale"
  26410.     trans2_WindowingTransformation identity.    
  26411.     trans2_ trans2 scaleBy: 2.0@2.0.
  26412.     trans2_ trans2 translateBy: 200@200.
  26413.  
  26414.     instance1 _ GraphicSymbolInstance new.
  26415.     instance1 transformation: trans1.
  26416.     instance1 graphicSymbol: gate.
  26417.  
  26418.     instance2 _ GraphicSymbolInstance new.
  26419.     instance2 transformation: trans2.
  26420.     instance2 graphicSymbol: gate.
  26421.  
  26422.             "display both instances of the logic gate"
  26423.     instance1 displayOn: Display
  26424.                     transformation: WindowingTransformation identity
  26425.                     clippingBox: Display boundingBox
  26426.                     rule: Form under
  26427.                     fillColor: nil.
  26428.     instance2 displayOn: Display
  26429.                     transformation: WindowingTransformation identity
  26430.                     clippingBox: Display boundingBox
  26431.                     rule: Form under
  26432.                     fillColor: nil
  26433.  
  26434.     "GraphicSymbolInstance example"! !SelectionMenu subclass: #HierarchicalMenu
  26435.     instanceVariableNames: 'deeperMenus '
  26436.     classVariableNames: ''
  26437.     poolDictionaries: ''
  26438.     category: 'Interface-Menus'!
  26439.  
  26440. !HierarchicalMenu methodsFor: 'deeper menu creation'!
  26441. deeperMenus: menuArray
  26442.     deeperMenus _ menuArray! !
  26443.  
  26444. !HierarchicalMenu methodsFor: 'marker management'!
  26445. manageMarker
  26446.     "startUp a deeper menu if the cursor goes out to the right"
  26447.     | aPoint |
  26448.     aPoint _ Sensor cursorPoint.
  26449.     (frame inside containsPoint: aPoint)
  26450.         ifTrue: [self markerOn: aPoint.  ^ selections at: selection].
  26451.     selection = 0 ifTrue: [^ nil].
  26452.     (aPoint x > frame inside right and: [(deeperMenus at: selection) notNil])
  26453.         ifTrue: [^ (deeperMenus at: selection) startUp].
  26454.     self markerOff.
  26455.     ^ nil! !
  26456. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  26457.  
  26458. HierarchicalMenu class
  26459.     instanceVariableNames: ''!
  26460. HierarchicalMenu class comment:
  26461. 'Created by Dan Ingalls back in 1985-6, but not currently maintained or used.'!
  26462.  
  26463. !HierarchicalMenu class methodsFor: 'example'!
  26464. example  "HierarchicalMenu example"
  26465.     ^ (HierarchicalMenu
  26466.         labelList: #('one' ('two...' 'buckle' 'my' 'shoe') 'three' ('four...' 'close' 'the' 'door'))
  26467.         selections: #('one' ('buckle' 'my' 'shoe') 'three' ('close' 'the' 'door')))
  26468.         startUpWithCaption: 'Give it a whirl'! !
  26469.  
  26470. !HierarchicalMenu class methodsFor: 'instance creation'!
  26471. labelList: labelList lines: lines selections: selections
  26472.     | topLabels topSelections deeperMenus item j |
  26473.     topLabels _ OrderedCollection new.
  26474.     topSelections _ OrderedCollection new.
  26475.     deeperMenus _ OrderedCollection new.
  26476.     j _ 0.
  26477.     1 to: labelList size do:
  26478.         [:i | item _ labelList at: i.
  26479.         (item isMemberOf: Array)
  26480.             ifTrue: [topLabels addLast: item first.
  26481.                     deeperMenus addLast:
  26482.                     (HierarchicalMenu labelList: (item copyFrom: 2 to: item size)
  26483.                         selections: (selections at: i))]
  26484.             ifFalse: [topLabels addLast: item.
  26485.                     deeperMenus addLast: nil].
  26486.         
  26487.         topSelections addLast: (selections at: i)].
  26488.     ^ (super labelList: topLabels asArray lines: lines selections: topSelections asArray)
  26489.         deeperMenus: deeperMenus asArray! !StandardFileStream subclass: #HtmlFileStream
  26490.     instanceVariableNames: ''
  26491.     classVariableNames: ''
  26492.     poolDictionaries: 'FilePool '
  26493.     category: 'System-Files'!
  26494.  
  26495. !HtmlFileStream methodsFor: 'as yet unclassified'!
  26496. aComment
  26497.     "This stream writes legal HTML.  Invoke it with:
  26498.  
  26499. ((FileStream fileNamed: 'changes.html') asHtml) fileOutChanges
  26500.  
  26501.     Meant to masquerade as a StandardFileStream.  Use all the normal methods (for best looks, use method:, methodHeader:, methodBody:, for code).  Use verbatim: to put stuff directly.  Use command: to put out <br>, etc.  Command: it supplies the brackets <>, in normal streams it ignores the data, could be used to bold in Text by recognising 'b', '/b', etc.  Caller should use header and trailer."
  26502.     "Override nextPut and do the < > & character transformation.  nextPutAll: calls nextPut."
  26503.  
  26504.     "Reading expects HTML file and produces normal Smalltalk code."!
  26505. command: aString
  26506.     "Append HTML commands directly without translation.  Caller should not include < or >.  Note that font change info comes through here!!  4/5/96 tk"
  26507.  
  26508.     (aString includes: $<) ifTrue: [self error: 'Do not put < or > in arg'].
  26509.         "We do the wrapping with <> here!!  Don't put it in aString."
  26510.     ^ self verbatim: '<', aString, '>'!
  26511. header
  26512.     "append the HTML header.  Be sure to call trailer after you put out the data.
  26513.     4/4/96 tk"
  26514.     | cr f |
  26515.     cr _ String with: Character cr.
  26516.     self command: 'HTML'; verbatim: cr.
  26517.     self command: 'HEAD'; verbatim: cr.
  26518.     self command: 'TITLE'.
  26519.     self nextPutAll: '"', self name, '"'.
  26520.     self command: '/TITLE'; verbatim: cr.
  26521.     self command: '/HEAD'; verbatim: cr.
  26522.     self command: 'BODY'; verbatim: cr.
  26523.  
  26524.     "Write out tab.gif because it is used when source code is written as html"
  26525. (StandardFileStream isAFileNamed: 'tab.gif') ifFalse: [
  26526.     f _ FileStream fileNamed: 'tab.gif'.
  26527.     f nextPutAll: 'GIF89a≡   !!∙,@äÅY!!■clip2gif v.0.4 by Yves Piguet;'.
  26528.     f close].
  26529. !
  26530. nextChunk
  26531.     "Answer the contents of the receiver, up to the next terminator character (!!).  Imbedded terminators are doubled.  Undo and strip out all Html stuff in the stream and convert the characters back.  4/12/96 tk"
  26532.     | out char did rest |
  26533.     self skipSeparators.    "Absorb <...><...> also"
  26534.     out _ WriteStream on: (String new: 500).
  26535.     [self atEnd] whileFalse: [
  26536.         self peek = $< ifTrue: [self unCommand].    "Absorb <...><...>"
  26537.         (char _ self next) = $&
  26538.             ifTrue: [
  26539.                 rest _ self upTo: $;.
  26540.                 did _ out position.
  26541.                 rest = 'lt' ifTrue: [out nextPut: $<].
  26542.                 rest = 'gt' ifTrue: [out nextPut: $>].
  26543.                 rest = 'amp' ifTrue: [out nextPut: $&].
  26544.                 did = out position ifTrue: [
  26545.                     self error: 'new HTML char encoding'.
  26546.                     "Please add it to this code"]]
  26547.             ifFalse: [char = $!!    "terminator"
  26548.                 ifTrue: [
  26549.                     self peek = $!! ifFalse: [^ out contents].
  26550.                     out nextPut: self next]    "pass on one $!!"
  26551.                 ifFalse: [out nextPut: char]]
  26552.         ].
  26553.     ^ out contents!
  26554. nextPut: char
  26555.     "Put a character on the file, but translate it first. 4/6/96 tk"
  26556.     char = $< ifTrue: [^ super nextPutAll: '<'].
  26557.     char = $> ifTrue: [^ super nextPutAll: '>'].
  26558.     char = $& ifTrue: [^ super nextPutAll: '&'].
  26559.     char asciiValue = 13 "return" ifTrue: [
  26560.             self command: 'br'].
  26561.     char = $    "tab" ifTrue: [self command: 'IMG SRC="tab.gif" ALT="    "'].
  26562.     ^ super nextPut: char!
  26563. nextPutAll: aString
  26564.     "Write the whole string, translating as we go. 4/6/96 tk"
  26565.     "Slow, but faster than using aString asHtml?"
  26566.  
  26567.     aString do: [:each | self nextPut: each].!
  26568. skipSeparators
  26569.     "Bsides the normal spacers, also skip any <...>, html commands.
  26570.     4/12/96 tk"
  26571.     | did |
  26572.     [did _ self position.
  26573.         super skipSeparators.
  26574.         self unCommand.    "Absorb <...><...>"
  26575.         did = self position] whileFalse.    "until no change"
  26576. !
  26577. trailer
  26578.     "append the HTML trailer.  Call this just before file close.
  26579.     4/4/96 tk"
  26580.     | cr |
  26581.     cr _ String with: Character cr.
  26582.     self command: '/BODY'; verbatim: cr.
  26583.     self command: '/HTML'; verbatim: cr.
  26584. !
  26585. verbatim: aString
  26586.     "Do not attempt to translate the characters.  Use this to override translation in nextPutAll:.  User may write HTML directly to the file with this."
  26587.  
  26588.     ^ super nextPutAll: aString
  26589.     "very tricky!! depends on the fact that StandardFileStream nextPutAll: does not call nextPut, but does a direct write."! !Dictionary subclass: #IdentityDictionary
  26590.     instanceVariableNames: ''
  26591.     classVariableNames: ''
  26592.     poolDictionaries: ''
  26593.     category: 'Collections-Unordered'!
  26594.  
  26595. !IdentityDictionary methodsFor: 'private'!
  26596. scanFor: key from: start to: finish
  26597.     "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches the key. Answer the index of that slot or zero if no slot is found within the given range of indices."
  26598.  
  26599.     | element |
  26600.     "this speeds up a common case: key is in the first slot"
  26601.     ((element _ array at: start) == nil or: [element key == key])
  26602.         ifTrue: [ ^ start ].
  26603.  
  26604.     start + 1 to: finish do: [ :index |
  26605.         ((element _ array at: index) == nil or: [element key == key])
  26606.             ifTrue: [ ^ index ].
  26607.     ].
  26608.     ^ 0! !SwitchController subclass: #IndicatorOnSwitchController
  26609.     instanceVariableNames: ''
  26610.     classVariableNames: ''
  26611.     poolDictionaries: ''
  26612.     category: 'Interface-Menus'!
  26613. IndicatorOnSwitchController comment:
  26614. 'I am a SwitchController that keeps the view (typically a SwitchView) highlighted while the model (typically a Switch) carries out the selected behavior.'!
  26615.  
  26616. !IndicatorOnSwitchController methodsFor: 'basic control sequence'!
  26617. sendMessage 
  26618.     "Refer to the comment in SwitchController|sendMessage."
  26619.  
  26620.     arguments size = 0
  26621.         ifTrue: [view indicatorOnDuring: [model perform: selector]]
  26622.         ifFalse: [view indicatorOnDuring: 
  26623.                     [model perform: selector withArguments: arguments]]! !DisplayObject subclass: #InfiniteForm
  26624.     instanceVariableNames: 'patternForm '
  26625.     classVariableNames: ''
  26626.     poolDictionaries: ''
  26627.     category: 'Graphics-Display Objects'!
  26628. InfiniteForm comment:
  26629. 'I represent a Form obtained by replicating a pattern form indefinitely in all directions.'!
  26630.  
  26631. !InfiniteForm methodsFor: 'accessing'!
  26632. asForm
  26633.     ^ patternForm!
  26634. offset 
  26635.     "Refer to the comment in DisplayObject|offset."
  26636.  
  26637.     ^0 @ 0! !
  26638.  
  26639. !InfiniteForm methodsFor: 'displaying'!
  26640. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
  26641.     "This is the real display message, but it doesn't get used until the new
  26642.     display protocol is installed."
  26643.     | targetBox patternBox |
  26644.     (patternForm class == Pattern)
  26645.         ifTrue:
  26646.             ["Use patternForm as a mask for BitBlt"
  26647.             aDisplayMedium fill: clipRectangle 
  26648.                 rule: ruleInteger fillColor: patternForm.
  26649.             ^ self].
  26650.     (patternForm isKindOf: Form)
  26651.         ifFalse:
  26652.             ["A Color-like thing.  Use patternForm as a mask for BitBlt"
  26653.             aDisplayMedium fill: clipRectangle 
  26654.                 rule: ruleInteger fillColor: patternForm]
  26655.         ifTrue:
  26656.             ["Do it iteratively"
  26657.             targetBox _ aDisplayMedium boundingBox intersect: clipRectangle.
  26658.             patternBox _ patternForm boundingBox.
  26659.             (targetBox left truncateTo: patternBox width)
  26660.                 to: targetBox right - 1 by: patternBox width do:
  26661.                 [:x |
  26662.                 (targetBox top truncateTo: patternBox height)
  26663.                     to: targetBox bottom - 1 by: patternBox height do:
  26664.                     [:y |
  26665.                     patternForm displayOn: aDisplayMedium
  26666.                         at: x @ y
  26667.                         clippingBox: clipRectangle
  26668.                         rule: ruleInteger
  26669.                         fillColor: aForm]]]!
  26670. displayOnPort: aPort at: aDisplayPoint
  26671.     "Only implemented for 16x16 patterns"
  26672.     aPort fill: aPort clipRect fillColor: patternForm rule: Form over! !
  26673.  
  26674. !InfiniteForm methodsFor: 'display box access'!
  26675. computeBoundingBox 
  26676.     "Refer to the comment in DisplayObject|computeBoundingBox."
  26677.  
  26678.     ^0 @ 0 corner: SmallInteger maxVal @ SmallInteger maxVal! !
  26679.  
  26680. !InfiniteForm methodsFor: 'private'!
  26681. form: aForm
  26682.  
  26683.     patternForm _ aForm! !
  26684. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  26685.  
  26686. InfiniteForm class
  26687.     instanceVariableNames: ''!
  26688.  
  26689. !InfiniteForm class methodsFor: 'instance creation'!
  26690. with: aForm 
  26691.     "Answer an instance of me whose pattern form is the argument, aForm."
  26692.  
  26693.     ^self new form: aForm! !Object subclass: #InputSensor
  26694.     instanceVariableNames: ''
  26695.     classVariableNames: 'InterruptWatcherProcess InterruptSemaphore CurrentCursor '
  26696.     poolDictionaries: ''
  26697.     category: 'Kernel-Processes'!
  26698. InputSensor comment:
  26699. 'I represent an interface to the user input devices. There is at least one instance of me named Sensor in the system.'!
  26700.  
  26701. !InputSensor methodsFor: 'keyboard'!
  26702. flushKeyboard
  26703.     "Remove all characters from the keyboard buffer."
  26704.  
  26705.     [self keyboardPressed]
  26706.         whileTrue: [self keyboard]!
  26707. kbdTest    "Sensor kbdTest"
  26708.     | char |
  26709.     [char = $x] whileFalse: 
  26710.         [[self keyboardPressed] whileFalse: [].
  26711.         char _ self characterForKeycode: self keyboard.
  26712.         char asciiValue printString , '  ' displayAt: 10@10]!
  26713. keyboard
  26714.     "Answer the next character from the keyboard."
  26715.  
  26716.     ^ self characterForKeycode: self primKbdNext!
  26717. keyboardPeek
  26718.     "Answer the next character in the keyboard buffer without removing it, or nil if it is empty."
  26719.  
  26720.     ^ self characterForKeycode: self primKbdPeek!
  26721. keyboardPressed
  26722.     "Answer true if keystrokes are available."
  26723.  
  26724.     ^self primKbdPeek notNil! !
  26725.  
  26726. !InputSensor methodsFor: 'modifier keys'!
  26727. commandKeyPressed
  26728.     "Answer whether the command key on the keyboard is being held down."
  26729.  
  26730.     ^ self primMouseButtons anyMask: 64!
  26731. controlKeyPressed
  26732.     "Answer whether the control key on the keyboard is being held down."
  26733.  
  26734.     ^ self primMouseButtons anyMask: 16!
  26735. leftShiftDown
  26736.     "Answer whether the shift key on the keyboard is being held down. The name of this message is a throwback to the Alto, which had independent left and right shift keys."
  26737.  
  26738.     ^ self primMouseButtons anyMask: 8!
  26739. optionKeyPressed
  26740.     "Answer whether the option key on the keyboard is being held down."
  26741.  
  26742.     ^ self primMouseButtons anyMask: 32! !
  26743.  
  26744. !InputSensor methodsFor: 'mouse'!
  26745. anyButtonPressed
  26746.     "Answer whether a mouse button is being pressed."
  26747.  
  26748.     ^self buttons > 0!
  26749. blueButtonPressed
  26750.     "Answer whether only the blue mouse button is being pressed."
  26751.  
  26752.     ^self buttons = 1!
  26753. mousePoint
  26754.     "Answer a Point indicating the coordinates of the current mouse location."
  26755.  
  26756.     ^self primMousePt!
  26757. noButtonPressed
  26758.     "Answer whether any mouse button is not being pressed."
  26759.  
  26760.     ^self anyButtonPressed == false!
  26761. redButtonPressed
  26762.     "Answer whether only the red mouse button is being pressed."
  26763.  
  26764.     ^self buttons = 4!
  26765. waitButton
  26766.     "Wait for the user to press any mouse button and then answer with the 
  26767.     current location of the cursor."
  26768.  
  26769.     [self anyButtonPressed] whileFalse.
  26770.     ^self cursorPoint!
  26771. waitClickButton
  26772.     "Wait for the user to click (press and then release) any mouse button and 
  26773.     then answer with the current location of the cursor."
  26774.  
  26775.     self waitButton.
  26776.     ^self waitNoButton!
  26777. waitNoButton
  26778.     "Wait for the user to release any mouse button and then answer with the 
  26779.     current location of the cursor."
  26780.  
  26781.     [self anyButtonPressed] whileTrue.
  26782.     ^self cursorPoint!
  26783. yellowButtonPressed
  26784.     "Answer whether only the yellow mouse button is being pressed."
  26785.  
  26786.     ^self buttons = 2! !
  26787.  
  26788. !InputSensor methodsFor: 'cursor'!
  26789. currentCursor
  26790.     "Answer the instance of Cursor currently displayed."
  26791.  
  26792.     ^CurrentCursor!
  26793. currentCursor: newCursor 
  26794.     "Set newCursor to be the displayed Cursor form."
  26795.  
  26796.     CurrentCursor _ newCursor.
  26797.     Cursor currentCursor: CurrentCursor.!
  26798. cursorPoint
  26799.     "Answer a Point indicating the cursor location."
  26800.  
  26801.     ^self mousePoint!
  26802. cursorPoint: aPoint 
  26803.     "Set aPoint to be the current cursor location."
  26804.  
  26805.     ^self primCursorLocPut: aPoint! !
  26806.  
  26807. !InputSensor methodsFor: 'joystick'!
  26808. joystickButtons: index
  26809.  
  26810.     ^ ((self primReadJoystick: index) bitShift: -22) bitAnd: 16r71f
  26811.     !
  26812. joystickOn: index
  26813.  
  26814.     ^ (((self primReadJoystick: index) bitShift: -27) bitAnd: 1) !!= 0
  26815.     !
  26816. joystickXY: index
  26817.  
  26818.     | inputWord x y |
  26819.     inputWord _ self primReadJoystick: index.
  26820.     x _ (inputWord bitAnd: 16r7ff) - 16r400.
  26821.     y _ ((inputWord bitShift: -11) bitAnd: 16r7ff) - 16r400.
  26822.     ^ x@y
  26823.     !
  26824. testJoystick: index
  26825.     "Sensor testJoystick: 3"
  26826.  
  26827.     | f pt buttons status |
  26828.     f _ Form extent: 110@50.
  26829.     [Sensor anyButtonPressed] whileFalse: [
  26830.         pt _ Sensor joystickXY: index.
  26831.         buttons _ Sensor joystickButtons: index.
  26832.         status _
  26833. 'xy: ', pt printString, '
  26834. buttons: ', buttons hex.
  26835.         f fillWhite.
  26836.         status asParagraph displayOn: f at: 10@10.
  26837.         f displayOn: Display at: 10@10.
  26838.     ].
  26839. ! !
  26840.  
  26841. !InputSensor methodsFor: 'user interrupts'!
  26842. installInterruptWatcher
  26843.     "Initialize the interrupt watcher process. Terminate the old process if any."
  26844.     "Sensor installInterruptWatcher"
  26845.  
  26846.     InterruptWatcherProcess == nil ifFalse: [InterruptWatcherProcess terminate].
  26847.     InterruptSemaphore _ Semaphore new.
  26848.     InterruptWatcherProcess _ [self userInterruptWatcher] newProcess.
  26849.     InterruptWatcherProcess priority: Processor lowIOPriority.
  26850.     InterruptWatcherProcess resume.
  26851.     self primInterruptSemaphore: InterruptSemaphore.!
  26852. setInterruptKey: anInteger
  26853.     "Register the given keycode as the user interrupt key."
  26854.  
  26855.     self primSetInterruptKey: anInteger.
  26856. !
  26857. userInterruptWatcher
  26858.     "Wait for user interrupts and open a notifier on the active process when one occurs."
  26859.  
  26860.     [true] whileTrue: [
  26861.         InterruptSemaphore wait.
  26862.         SoundPlayer shutDown.
  26863.         [ScheduledControllers interruptName: 'User Interrupt'] fork.
  26864.     ].
  26865. ! !
  26866.  
  26867. !InputSensor methodsFor: 'private'!
  26868. buttons
  26869.  
  26870.     ^ self primMouseButtons bitAnd: 7!
  26871. characterForKeycode: keycode
  26872.     "Map the given keycode to a Smalltalk character object. Encoding:
  26873.         A keycode is 12 bits:   <4 modifer bits><8 bit ISO character>
  26874.         Modifier bits are:       <command><option><control><shift>"
  26875.  
  26876.     "NOTE: the command and option keys are specific to the Macintosh and may not have equivalents on other platforms."
  26877.  
  26878.     keycode = nil ifTrue: [ ^nil ].
  26879.     keycode class = Character ifTrue: [ ^keycode ].  "to smooth the transition!!"
  26880.     ^ Character value: (keycode bitAnd: 16rFF)!
  26881. primCursorLocPut: aPoint
  26882.     "If the primitive fails, try again with a rounded point."
  26883.  
  26884.     <primitive: 91>
  26885.     ^ self primCursorLocPutAgain: aPoint rounded!
  26886. primCursorLocPutAgain: aPoint
  26887.     "Do nothing if primitive is not implemented."
  26888.  
  26889.     <primitive: 91>
  26890.     ^ self!
  26891. primInterruptSemaphore: aSemaphore 
  26892.     "Primitive. Install the argument as the semaphore to be signalled whenever the user presses the interrupt key. The semaphore will be signaled once each time the interrupt key is pressed."
  26893.  
  26894.     <primitive: 134>
  26895.     ^self primitiveFailed!
  26896. primKbdNext
  26897.     <primitive: 108>
  26898.     ^ nil!
  26899. primKbdPeek
  26900.     <primitive: 109>
  26901.     ^ nil!
  26902. primMouseButtons
  26903.     <primitive: 107>
  26904.     ^ 0!
  26905. primMousePt
  26906.     "Primitive. Poll the mouse to find out its position. Return a Point. Fail if
  26907.     event-driven tracking is used instead of polling. Optional. See Object
  26908.     documentation whatIsAPrimitive."
  26909.  
  26910.     <primitive: 90>
  26911.     ^ 0@0!
  26912. primReadJoystick: index
  26913.     "Return the joystick input word for the joystick with the given index in the range [1..16]. Returns zero if the index does not correspond to a currently installed joystick."
  26914.  
  26915.     <primitive: 146>
  26916.     ^ 0
  26917.  
  26918.     !
  26919. primSetInterruptKey: anInteger
  26920.     "Primitive. Register the given keycode as the user interrupt key. The low byte of the keycode is the ISO character and its next four bits are the Smalltalk modifer bits <cmd><opt><ctrl><shift>."
  26921.  
  26922.     <primitive: 133>
  26923.     ^self primitiveFailed! !
  26924. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  26925.  
  26926. InputSensor class
  26927.     instanceVariableNames: ''!
  26928.  
  26929. !InputSensor class methodsFor: 'public'!
  26930. default
  26931.     "Answer the default system InputSensor, Sensor."
  26932.  
  26933.     ^ Sensor!
  26934. startUp
  26935.     
  26936.     self default installInterruptWatcher.! !Object subclass: #InputState
  26937.     instanceVariableNames: 'x y bitState lshiftState rshiftState ctrlState lockState metaState keyboardQueue deltaTime baseTime timeProtect redButtonQueue redButtonPollCnt '
  26938.     classVariableNames: 'RshiftKey InputProcess LshiftKey BitMin InputSemaphore BitMax MinPollCnt LockKey CtrlKey '
  26939.     poolDictionaries: ''
  26940.     category: 'Kernel-Processes'!
  26941. InputState comment:
  26942. 'I represent the state of the user input devices.'!
  26943.  
  26944. !InputState methodsFor: 'initialize-release'!
  26945. install
  26946.     "Initialize and connect the receiver to the hardware. Terminate the old 
  26947.     input process if any."
  26948.  
  26949.     InputProcess == nil ifFalse: [InputProcess terminate].
  26950.     self initState.
  26951.     InputSemaphore _ Semaphore new.
  26952.     InputProcess _ [self run] newProcess.
  26953.     InputProcess priority: Processor lowIOPriority.
  26954.     InputProcess resume.
  26955.     self primInputSemaphore: InputSemaphore! !
  26956.  
  26957. !InputState methodsFor: 'keyboard'!
  26958. keyboardNext
  26959.     "Remove and answer the next key in the keyboard buffer."
  26960.  
  26961.     ^keyboardQueue next!
  26962. keyboardPeek
  26963.     "Answer the next key in the keyboard buffer but do not remove it."
  26964.  
  26965.     ^keyboardQueue peek!
  26966. leftShiftDown
  26967.     "Answer whether the left shift key is down."
  26968.  
  26969.     ^lshiftState ~= 0! !
  26970.  
  26971. !InputState methodsFor: 'mouse'!
  26972. mouseButtons
  26973.     "Answer the status of the mouse buttons: an Integer between 0 and 7."
  26974.  
  26975.     "If queue has a new value and the front queue value has been polled enough, move on to the next mouse button movement.  Set a minimum number of times it must be polled before it will change." 
  26976.     (redButtonPollCnt _ redButtonPollCnt - 1) <= 0 ifTrue: [
  26977.         redButtonQueue size >= 2 ifTrue: [
  26978.                 redButtonQueue removeFirst.  "remove old value"
  26979.                 redButtonPollCnt _ MinPollCnt.
  26980.                 bitState _ (bitState bitAnd: 8r376) bitOr: redButtonQueue first]
  26981.             ifFalse: [redButtonPollCnt _ -1.    "keep it pinned"]].
  26982.     ^bitState bitAnd: 7!
  26983. mousePoint
  26984.     "Answer the coordinates of the mouse location."
  26985.  
  26986.     ^self primMousePt! !
  26987.  
  26988. !InputState methodsFor: 'cursor'!
  26989. cursorPoint: aPoint 
  26990.     "Set the current cursor position to be aPoint.  But don't actually do it,
  26991.     since Macintosh cursors don't relocate too well."
  26992.  
  26993.     "self primCursorLocPut: aPoint.
  26994.     x _ aPoint x.
  26995.     y _ aPoint y"! !
  26996.  
  26997. !InputState methodsFor: 'time'!
  26998. currentTime
  26999.     "Answer the time on the system clock in milliseconds since midnight. "
  27000.     
  27001.     timeProtect critical: [deltaTime = 0
  27002.             ifFalse: 
  27003.                 [baseTime _ baseTime + deltaTime.
  27004.                 deltaTime _ 0]].
  27005.     ^baseTime! !
  27006.  
  27007. !InputState methodsFor: 'private'!
  27008. bitState: mask incoming: value
  27009.     "Set bitState according to the incoming new value.  This covers the mouse buttons 1,2,4 and five keyset bits.  We queue up the red button bit, so that no mouse clicks are lost."
  27010.     mask = 1 ifFalse: ["yellow, blue, keyset"
  27011.         value = 1
  27012.             ifTrue: [bitState _ bitState bitOr: mask]
  27013.             ifFalse: [bitState _ bitState bitAnd: -1 - mask]]
  27014.       ifTrue: ["Red button on mouse"
  27015.         "bitState must be always the same as the first value on the queue"
  27016.         redButtonQueue addLast: value.
  27017.         "poll the method mouseButtons will advance the queue"]!
  27018. initState
  27019.  
  27020.     timeProtect _ Semaphore forMutualExclusion.
  27021.     timeProtect critical: [deltaTime _ baseTime _ 0].
  27022.     x _ y _ 0.
  27023.     keyboardQueue _ SharedQueue new: 50.
  27024.     ctrlState _ lshiftState _ rshiftState _ lockState _ metaState _ 0.
  27025.     bitState _ 0.
  27026.     redButtonQueue _ OrderedCollection new: 20.
  27027.     redButtonPollCnt _ MinPollCnt.
  27028.     redButtonQueue add: (bitState bitAnd: 1).  "Must always agree"!
  27029. keyAt: index put: value
  27030.  
  27031.     | mask |
  27032.     index < 8r200
  27033.       ifTrue:  "Not a potential special character"
  27034.         [value ~= 0 ifTrue:
  27035.             [(index = $. asciiValue and: [ctrlState ~= 0])
  27036.                 ifTrue: [[ScheduledControllers interruptName: 'User Interrupt'] fork. ^self].
  27037.             "(index = $z asciiValue and: [ctrlState ~= 0])
  27038.                 ifTrue: [ScheduledControllers scheduleFromKeyPress: ScheduledControllers bottomController.
  27039.                         ^ self].
  27040.             (index = $a asciiValue and: [ctrlState ~= 0])
  27041.                 ifTrue: [ScheduledControllers scheduleFromKeyPress: ScheduledControllers penultimateController.
  27042.                         ^ self]."
  27043.             ^keyboardQueue nextPut: (KeyboardEvent code: index meta: metaState)]]
  27044.       ifFalse:
  27045.         [index = CtrlKey
  27046.           ifTrue: [ctrlState _ value bitShift: 1]
  27047.           ifFalse:
  27048.             [index = LshiftKey
  27049.               ifTrue: [lshiftState _ value]
  27050.               ifFalse:
  27051.                 [index = RshiftKey
  27052.                   ifTrue: [rshiftState _ value]
  27053.                   ifFalse:
  27054.                     [index = LockKey
  27055.                       ifTrue: [lockState _ value bitShift: 2]
  27056.                       ifFalse:
  27057.                         [(index >= BitMin and: [index <= BitMax])
  27058.                           ifTrue:
  27059.                             [mask _ 1 bitShift: index - BitMin.
  27060.                             self bitState: mask incoming: value]
  27061.                           ifFalse:
  27062.                             [value ~= 0 ifTrue:
  27063.                                 [keyboardQueue nextPut:
  27064.                                     (KeyboardEvent code: index meta: metaState)]]]]]].
  27065.         metaState _ (ctrlState bitOr: (lshiftState bitOr: rshiftState)) bitOr: lockState]!
  27066. nextEvent: type with: param
  27067.     "Process a single input event, aside from mouse X/Y.
  27068.      2/8/96 sw: remove the hard-coded use of HFSMacVolume"
  27069.  
  27070.     | highTime lowTime |
  27071.     type = 0  "Delta time"
  27072.         ifTrue: 
  27073.             [timeProtect critical: [deltaTime _ deltaTime + param]]
  27074.         ifFalse:
  27075.             [type = 3    "Key down"
  27076.                 ifTrue: [self keyAt: param put: 1]
  27077.                 ifFalse:
  27078.                     [type = 4    "Key up"
  27079.                         ifTrue: [self keyAt: param put: 0]
  27080.                         ifFalse:
  27081.                             [type = 5    "Reset time"
  27082.                                 ifTrue:
  27083.                                     [InputSemaphore wait.
  27084.                                     highTime _ self primInputWord.
  27085.                                     InputSemaphore wait.
  27086.                                     lowTime _ self primInputWord.
  27087.                                     timeProtect critical:
  27088.                                         [baseTime _ (highTime bitShift: 16) + lowTime.
  27089.                                          deltaTime _ 0]]
  27090.                                 ifFalse: [type = 7    "Diskette insert"
  27091.                                         ifTrue: ["[FileDirectory concreteFileDirectoryClass mount: param] forkAt: Processor userInterruptPriority"]
  27092.                                         ifFalse:
  27093.                                             [[Transcript show: 'Bad event type dectected in InputState nextEvent:with:'; cr] forkAt: Processor userInterruptPriority]]]]] !
  27094. primCursorLocPut: aPoint 
  27095.     "Primitive. Move the cursor to the screen location specified by the
  27096.     argument, aPoint. Fail if the argument is not a Point. Essential. See
  27097.     Object documentation whatIsAPrimitive."
  27098.  
  27099.     <primitive: 91>
  27100.     ^self primCursorLocPutAgain: aPoint rounded!
  27101. primCursorLocPutAgain: aPoint 
  27102.     "Primitive. By this time, aPoint better be an integer or get out of here.
  27103.     See InputState|primCursorLocPut."
  27104.  
  27105.     <primitive: 91>
  27106.     ^self primitiveFailed!
  27107. primInputSemaphore: aSemaphore 
  27108.     "Primitive. Install the argument, aSemaphore, as the object to be signalled
  27109.     whenever an input event occurs. The semaphore will be signaled once
  27110.     for every word placed in the input buffer by an I/O device. Fail if the
  27111.     argument is neither a Semaphore nor nil. Essential. See Object
  27112.     documentation whatIsAPrimitive."
  27113.  
  27114.     <primitive: 93>
  27115.     ^self primitiveFailed!
  27116. primInputWord
  27117.     "Primitive. Return the next word from the input buffer and remove the
  27118.     word from the buffer. This message should be sent just after the input
  27119.     semaphore finished a wait (was sent a signal by an I/O device). Fail if
  27120.     the input buffer is empty. Essential. See Object documentation
  27121.     whatIsAPrimitive."
  27122.  
  27123.     <primitive: 95>
  27124.     ^self primitiveFailed!
  27125. primMousePt
  27126.     "Primitive. Poll the mouse to find out its position. Answer a Point. Fail if
  27127.     event-driven tracking is used instead of polling. Optional. See Object
  27128.     documentation whatIsAPrimitive."
  27129.  
  27130.     <primitive: 90>
  27131.     ^x @ y!
  27132. primSampleInterval: anInteger 
  27133.     "Primitive. Set the minimum time span between event driven mouse
  27134.     position samples. The argument, anInteger, is a number of milliseconds.
  27135.     Fail if the argument is not a SmallInteger. Essential. See Object
  27136.     documentation whatIsAPrimitive."
  27137.  
  27138.     <primitive: 94>
  27139.     ^self primitiveFailed!
  27140. run
  27141.     "This is the loop that actually processes input events."
  27142.  
  27143.     | word type param |
  27144.     [true]
  27145.         whileTrue: 
  27146.             [InputSemaphore wait.
  27147.             "Test for mouse X/Y events here to avoid an activation."
  27148.             word _ self primInputWord.
  27149.             type _ word bitShift: -12.
  27150.             param _ word bitAnd: 4095.
  27151.             type = 1
  27152.                 ifTrue: 
  27153.                     [x _ param "Mouse X"]
  27154.                 ifFalse: 
  27155.                     [type = 2
  27156.                         ifTrue: [y _ param "Mouse Y"]
  27157.                         ifFalse: [self nextEvent: type with: param]]]! !
  27158. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  27159.  
  27160. InputState class
  27161.     instanceVariableNames: ''!
  27162.  
  27163. !InputState class methodsFor: 'class initialization'!
  27164. initialize
  27165.     "Define parameters."
  27166.  
  27167.     BitMin _ 8r200.  "Min mouse/keyset bit code"
  27168.     BitMax _ 8r207.  "Max mouse/keyset bit code"
  27169.     LshiftKey _ 8r210.
  27170.     RshiftKey _ 8r211.
  27171.     CtrlKey _ 8r212.
  27172.     LockKey _ 8r213.
  27173.     MinPollCnt _ 3.
  27174.  
  27175.     "InputState initialize"!
  27176. process
  27177.     ^ InputProcess!
  27178. semaphore
  27179.     ^ InputSemaphore! !
  27180.  
  27181. InputState initialize!
  27182. StringHolderController subclass: #InspectCodeController
  27183.     instanceVariableNames: ''
  27184.     classVariableNames: ''
  27185.     poolDictionaries: ''
  27186.     category: 'Interface-Inspector'!
  27187. InspectCodeController comment:
  27188. 'I am a kind of StringHolderController (a ParagraphEditor that adds the doIt, printIt, accept, and cancel commands). I modify the response to accept by treating the text in the view as an expression to be evaluated. The result of the evaluation is stored as the value of the model"s currently selected variable.'!
  27189.  
  27190. !InspectCodeController methodsFor: 'menu messages'!
  27191. accept
  27192.  
  27193.     | result |
  27194.     (model isUnlocked or: [model selectionUnmodifiable])
  27195.         ifTrue: [^view flash].
  27196.     self controlTerminate.
  27197.     result _ model doItReceiver class evaluatorClass new
  27198.                 evaluate: (ReadStream on: paragraph string)
  27199.                 in: model doItContext
  27200.                 to: model doItReceiver
  27201.                 notifying: self
  27202.                 ifFail:  [self controlInitialize. ^nil].
  27203.     result == #failedDoit
  27204.         ifFalse: 
  27205.             [model replaceSelectionValue: result.
  27206.             self selectFrom: 1 to: paragraph text size.
  27207.             self deselect.
  27208.             self replaceSelectionWith: result printString asText.
  27209.             self selectAt: 1.
  27210.             super accept].
  27211.     self controlInitialize! !StringHolderView subclass: #InspectCodeView
  27212.     instanceVariableNames: ''
  27213.     classVariableNames: ''
  27214.     poolDictionaries: ''
  27215.     category: 'Interface-Inspector'!
  27216. InspectCodeView comment:
  27217. 'I am a StringHolderView of the value of the selected variable of the object observed by an Inspector. InspectCodeController is my default controller.'!
  27218.  
  27219. !InspectCodeView methodsFor: 'controller access'!
  27220. defaultControllerClass
  27221.  
  27222.     ^InspectCodeController! !BrowserListController subclass: #InspectListController
  27223.     instanceVariableNames: ''
  27224.     classVariableNames: 'InspectListYellowButtonMenu InspectListYellowButtonMessages '
  27225.     poolDictionaries: ''
  27226.     category: 'Interface-Inspector'!
  27227. InspectListController comment:
  27228. 'I am a kind of LockedListController for the listView of an InspectorView that creates a yellow button menu so that messages can be sent to the list selection (an object) to create and schedule an InspectView on it.'!
  27229.  
  27230. !InspectListController methodsFor: 'initialize-release'!
  27231. initialize
  27232.  
  27233.     super initialize.
  27234.     self initializeYellowButtonMenu! !
  27235.  
  27236. !InspectListController methodsFor: 'menu messages'!
  27237. browseClass
  27238.     "Create and schedule a class browser on the class of the current inspected.  1/25/96 sw"
  27239.  
  27240.     self controlTerminate.
  27241.     Browser newOnClass: self classOfSelection theNonMetaClass.
  27242.     self controlInitialize!
  27243. browseFull
  27244.     "Create and schedule a full Browser and then select the class of the master object being inspected.  1/25/96 sw"
  27245.  
  27246.     BrowserView browseFullForClass: self classOfSelection method: nil from: self!
  27247. classOfSelection
  27248.     "Answer the class of the receiver's current selection.  1/25/96 sw"
  27249.  
  27250.     model selectionUnmodifiable ifTrue: [^ model object class].
  27251.     ^ model selection class!
  27252. inspectSelection
  27253.     "Create and schedule an Inspector on the receiver's model's currently 
  27254.     selected object."
  27255.  
  27256.     model selectionIndex = 0
  27257.         ifTrue: [^view flash].
  27258.     self controlTerminate.
  27259.     ^model selection inspect!
  27260. referencesToSelection
  27261.     "Open a browser on all references to the selected instance variable, if that's what currently selected.  1/25/96 sw"
  27262.  
  27263.     | aClass sel |
  27264.  
  27265.     model selectionUnmodifiable ifTrue: [^ view flash].
  27266.     (aClass _ model object class) isVariable ifTrue: [^ view flash].
  27267.     self controlTerminate.
  27268.  
  27269.     sel _ aClass allInstVarNames at: model selectionIndex - 2.
  27270.     aClass browseAllAccessesTo: sel! !
  27271.  
  27272. !InspectListController methodsFor: 'private'!
  27273. changeModelSelection: anInteger 
  27274.     model toggleIndex: anInteger!
  27275. initializeYellowButtonMenu
  27276.  
  27277.     self 
  27278.         yellowButtonMenu: InspectListYellowButtonMenu
  27279.         yellowButtonMessages: InspectListYellowButtonMessages! !
  27280. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  27281.  
  27282. InspectListController class
  27283.     instanceVariableNames: ''!
  27284.  
  27285. !InspectListController class methodsFor: 'class initialization'!
  27286. initialize
  27287.     "1/25/96 sw: added references and browse items."
  27288.  
  27289.     InspectListYellowButtonMenu _ PopUpMenu labels: 'inspect
  27290. references
  27291. browse full
  27292. browse class'
  27293.     lines: #(1 2).
  27294.     InspectListYellowButtonMessages _ 
  27295.         #(inspectSelection referencesToSelection browseFull browseClass )
  27296.  
  27297.     "InspectListController initialize"! !
  27298.  
  27299. InspectListController initialize!
  27300. ListView subclass: #InspectListView
  27301.     instanceVariableNames: ''
  27302.     classVariableNames: ''
  27303.     poolDictionaries: ''
  27304.     category: 'Interface-Inspector'!
  27305. InspectListView comment:
  27306. 'I am a ListView whose items are the instance variables of the object observed by the Inspect that I view. InspectListController is my default controller.'!
  27307.  
  27308. !InspectListView methodsFor: 'updating'!
  27309. update: aSymbol
  27310.  
  27311.     aSymbol == #inspectObject
  27312.         ifTrue: 
  27313.             [self list: model fieldList.
  27314.             selection _ model selectionIndex.
  27315.             self displayView].
  27316.     aSymbol == #selection ifTrue: [self moveSelectionBox: model selectionIndex]! !
  27317.  
  27318. !InspectListView methodsFor: 'controller access'!
  27319. defaultControllerClass
  27320.  
  27321.     ^InspectListController! !
  27322.  
  27323. !InspectListView methodsFor: 'model access'!
  27324. model: anInspector
  27325.  
  27326.     super model: anInspector.
  27327.     self list: model fieldList.
  27328.     selection _ model selectionIndex! !StringHolder subclass: #Inspector
  27329.     instanceVariableNames: 'object selectionIndex '
  27330.     classVariableNames: ''
  27331.     poolDictionaries: ''
  27332.     category: 'Interface-Inspector'!
  27333. Inspector comment:
  27334. 'I represent a query path into the internal representation of an object. As a StringHolder, the string I represent is the value of the currently selected variable of the observed object.'!
  27335.  
  27336. !Inspector methodsFor: 'accessing'!
  27337. baseFieldList
  27338.     "Answer an Array consisting of 'self'
  27339.     and the instance variable names of the inspected object."
  27340.  
  27341.     ^ (Array with: 'self' with: 'all inst vars')
  27342.             , object class allInstVarNames!
  27343. fieldList
  27344.     "Answer the base field list plus an abbreviated list of indices."
  27345.  
  27346.     object class isVariable ifFalse: [^ self baseFieldList].
  27347.     ^ self baseFieldList ,
  27348.         (object basicSize <= (self i1 + self i2)
  27349.             ifTrue: [(1 to: object basicSize)
  27350.                         collect: [:i | i printString]]
  27351.             ifFalse: [(1 to: self i1) , (object basicSize-(self i2-1) to: object basicSize)
  27352.                         collect: [:i | i printString]])!
  27353. i1
  27354.     "This is the max index shown before skipping to the 
  27355.     last i2 elements of very long arrays"
  27356.     ^ 100!
  27357. i2
  27358.     "This is the number of elements to show at the end
  27359.     of very long arrays"
  27360.     ^ 10!
  27361. inspect: anObject 
  27362.     "Initialize the receiver so that it is inspecting anObject. There is no 
  27363.     current selection."
  27364.  
  27365.     self initialize.
  27366.     object _ anObject.
  27367.     selectionIndex _ 0.
  27368.     contents _ ''!
  27369. object
  27370.     "Answer the object being inspected by the receiver."
  27371.  
  27372.     ^object!
  27373. object: anObject 
  27374.     "Set anObject to be the object being inspected by the receiver."
  27375.  
  27376.     anObject == object
  27377.         ifTrue: [self update]
  27378.         ifFalse:
  27379.             [self inspect: anObject.
  27380.             self changed: #inspectObject]!
  27381. update
  27382.     "Reshow contents, assuming selected value may have changed."
  27383.  
  27384.     selectionIndex = 0
  27385.         ifFalse:
  27386.             [contents _ self selection printString.
  27387.             self changed: #selection]! !
  27388.  
  27389. !Inspector methodsFor: 'selecting'!
  27390. replaceSelectionValue: anObject 
  27391.     "The receiver has a list of variables of its inspected object. One of these 
  27392.     is selected. The value of the selected variable is set to the value, 
  27393.     anObject."
  27394.     | basicIndex |
  27395.     selectionIndex = 1 ifTrue: [^ object].
  27396.     object class isVariable
  27397.         ifFalse: [^ object instVarAt: selectionIndex - 2 put: anObject].
  27398.     basicIndex _ selectionIndex - 2 - object class instSize.
  27399.     (object basicSize <= (self i1 + self i2)  or: [basicIndex <= self i1])
  27400.         ifTrue: [^object basicAt: basicIndex put: anObject]
  27401.         ifFalse: [^object basicAt: object basicSize - (self i1 + self i2) + basicIndex
  27402.                     put: anObject]!
  27403. selection
  27404.     "The receiver has a list of variables of its inspected object.
  27405.     One of these is selected. Answer the value of the selected variable."
  27406.     | basicIndex |
  27407.     selectionIndex = 1 ifTrue: [^ object].
  27408.     selectionIndex = 2 ifTrue: [^ object longPrintString].
  27409.     (selectionIndex - 2) <= object class instSize
  27410.         ifTrue: [^ object instVarAt: selectionIndex - 2].
  27411.     basicIndex _ selectionIndex - 2 - object class instSize.
  27412.     (object basicSize <= (self i1 + self i2)  or: [basicIndex <= self i1])
  27413.         ifTrue: [^ object basicAt: basicIndex]
  27414.         ifFalse: [^ object basicAt: object basicSize - (self i1 + self i2) + basicIndex]!
  27415. selectionIndex
  27416.     "The receiver has a list of variables of its inspected object. One of these 
  27417.     is selected. Answer the index into the list of the selected variable."
  27418.  
  27419.     ^selectionIndex!
  27420. selectionUnmodifiable
  27421.     "Answer if the current selected variable is modifiable via acceptance in the code pane.  For most inspectors, no selection and a selection of self (selectionIndex = 1) are unmodifiable"
  27422.  
  27423.     ^ selectionIndex <= 2!
  27424. toggleIndex: anInteger
  27425.     "The receiver has a list of variables of its inspected object. One of these 
  27426.     is selected. If anInteger is the index of this variable, then deselect it. 
  27427.     Otherwise, make the variable whose index is anInteger be the selected 
  27428.     item."
  27429.  
  27430.     selectionIndex = anInteger
  27431.         ifTrue: 
  27432.             ["same index, turn off selection"
  27433.             selectionIndex _ 0.
  27434.             contents _ '']
  27435.         ifFalse:
  27436.             ["different index, new selection"
  27437.             selectionIndex _ anInteger.
  27438.             contents _ self selection printString].
  27439.     self changed: #selection.! !
  27440.  
  27441. !Inspector methodsFor: 'code'!
  27442. doItReceiver
  27443.     "Answer the object that should be informed of the result of evaluating a
  27444.     text selection."
  27445.  
  27446.     ^object! !
  27447. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  27448.  
  27449. Inspector class
  27450.     instanceVariableNames: ''!
  27451.  
  27452. !Inspector class methodsFor: 'instance creation'!
  27453. inspect: anObject 
  27454.     "Answer an instance of me to provide an inspector for anObject."
  27455.  
  27456.     ^self new inspect: anObject! !StringHolder subclass: #InspectorTrash
  27457.     instanceVariableNames: 'inspectedObject '
  27458.     classVariableNames: ''
  27459.     poolDictionaries: ''
  27460.     category: 'Interface-Inspector'!
  27461. InspectorTrash comment:
  27462. 'This is here only to allow the trash area at the bottom of an inspector.  It is basically a StringHolder except that it knows what about the object being inspect and so can accept doIt and printIt with that object as the receiver.'!
  27463.  
  27464. !InspectorTrash methodsFor: 'code'!
  27465. doItReceiver
  27466.     ^ inspectedObject!
  27467. inspectedObject
  27468.     ^ inspectedObject!
  27469. inspectedObject: io
  27470.     inspectedObject _ io! !
  27471. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  27472.  
  27473. InspectorTrash class
  27474.     instanceVariableNames: ''!
  27475.  
  27476. !InspectorTrash class methodsFor: 'instance creation'!
  27477. for: x
  27478.     ^ self new inspectedObject: x! !StandardSystemView subclass: #InspectorView
  27479.     instanceVariableNames: ''
  27480.     classVariableNames: ''
  27481.     poolDictionaries: ''
  27482.     category: 'Interface-Inspector'!
  27483. InspectorView comment:
  27484. 'I am a StandardSystemView that provides initialization methods (messages to myself) to create and schedule the interface to an object Inspector. I have two subViews, an InspectListView and an InspectCodeView.'!
  27485.  
  27486. !InspectorView methodsFor: 'miscellaneous'!
  27487. initialExtent
  27488.     "Answer the desired extent for the receiver when it is first opened on the screen.  5/22/96 sw"
  27489.  
  27490.     ^ 250 @ 200! !
  27491. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  27492.  
  27493. InspectorView class
  27494.     instanceVariableNames: ''!
  27495.  
  27496. !InspectorView class methodsFor: 'instance creation'!
  27497. dictionaryInspector: anInspector 
  27498.     "Answer an instance of me on the model, anInspector. The instance 
  27499.     consists of an InspectListView and an InspectCodeView."
  27500.  
  27501.     | anInspectorView anInspectorListView aCodeView |
  27502.     anInspectorView _ View new.
  27503.         anInspectorView model: anInspector.
  27504.         anInspectorListView _ InspectListView new.
  27505.         anInspectorListView model: anInspector;
  27506.                 controller: DictionaryListController new.
  27507.         anInspectorListView window: (0 @ 0 extent: 40 @ 40).
  27508.         anInspectorListView borderWidthLeft: 2 right: 0 top: 2 bottom: 2.
  27509.     anInspectorView addSubView: anInspectorListView.
  27510.     aCodeView _ self buildCodeView: anInspector.
  27511.     anInspectorView
  27512.         addSubView: aCodeView
  27513.         align: aCodeView viewport topLeft
  27514.         with: anInspectorListView viewport topRight.
  27515.     ^anInspectorView!
  27516. formDictionaryInspector: anInspector 
  27517.     "Answer an instance of me on the model, anInspector. The instance 
  27518.     consists of an InspectListView and an InspectFormView  6/28/96 sw."
  27519.  
  27520.     | anInspectorView anInspectorListView aFormView |
  27521.     anInspectorView _ View new.
  27522.         anInspectorView model: anInspector.
  27523.         anInspectorListView _ InspectListView new.
  27524.         anInspectorListView model: anInspector;
  27525.                 controller: DictionaryListController new.
  27526.         anInspectorListView window: (0 @ 0 extent: 40 @ 40).
  27527.         anInspectorListView borderWidthLeft: 2 right: 0 top: 2 bottom: 2.
  27528.     anInspectorView addSubView: anInspectorListView.
  27529.     aFormView _ self buildFormView: anInspector.
  27530.     anInspectorView
  27531.         addSubView: aFormView
  27532.         align: aFormView viewport topLeft
  27533.         with: anInspectorListView viewport topRight.
  27534.     ^anInspectorView!
  27535. inspector: anInspector 
  27536.     "Answer an instance of me on the model, anInspector. The instance 
  27537.     consists of an InspectListView and an InspectCodeView."
  27538.  
  27539.     | anInspectorView anInspectorListView aCodeView |
  27540.     anInspectorView _ View new.
  27541.     anInspectorView model: anInspector.
  27542.     anInspectorListView _ self buildInspectListView: anInspector.
  27543.     anInspectorView addSubView: anInspectorListView.
  27544.     aCodeView _ self buildCodeView: anInspector.
  27545.     anInspectorView
  27546.         addSubView: aCodeView
  27547.         align: aCodeView viewport topLeft
  27548.         with: anInspectorListView viewport topRight.
  27549.     ^anInspectorView!
  27550. inspectorWithTrash: anInspector 
  27551.     "Create an inspector with an extra 'trash' view at the bottom,
  27552.     where you can type expressions that don't interfere with
  27553.     inspecting the various selectable fields."
  27554.  
  27555.     | inspectorView aTrashView threeView |
  27556.     threeView _ View new model: anInspector object.
  27557.     inspectorView _ self inspector: anInspector.
  27558.     threeView addSubView: inspectorView.
  27559.     aTrashView _ self buildTrashView: anInspector.
  27560.     threeView
  27561.         addSubView: aTrashView
  27562.         align: aTrashView viewport topLeft
  27563.         with: inspectorView viewport bottomLeft.
  27564.     ^ threeView!
  27565. open: anInspectView
  27566.     "Create and schedule an instance of me on the model, anInspector. "
  27567.     self open: anInspectView withLabel: anInspectView model class name!
  27568. open: anInspectView withLabel: aLabel
  27569.     "Create and schedule an instance of me on the model, anInspector. "
  27570.     | topView |
  27571.     topView _ self new.
  27572.     topView addSubView: anInspectView.
  27573.     topView label: aLabel.
  27574.     topView minimumSize: 180 @ 120.
  27575.     topView controller open! !
  27576.  
  27577. !InspectorView class methodsFor: 'private'!
  27578. buildCodeView: anInspector
  27579.     | inspectCodeView |
  27580.  
  27581.     inspectCodeView _ InspectCodeView new.
  27582.     inspectCodeView model: anInspector.
  27583.     inspectCodeView window: (0 @ 0 extent: 75 @ 40).
  27584.     inspectCodeView borderWidthLeft: 2 right: 2 top: 2 bottom: 2.
  27585.     ^ inspectCodeView!
  27586. buildFormView: anInspector
  27587.     "Build a view which will show a form in the right side of the Inspector.   6/28/96 sw"
  27588.  
  27589.     | inspectFormView |
  27590.  
  27591.     inspectFormView _ FormInspectView new.
  27592.     inspectFormView model: anInspector.
  27593.     inspectFormView window: (0 @ 0 extent: 75 @ 40).
  27594.     inspectFormView borderWidthLeft: 2 right: 2 top: 2 bottom: 2.
  27595.     ^ inspectFormView!
  27596. buildInspectListView: anInspector
  27597.  
  27598.     | anInspectListView |
  27599.  
  27600.     anInspectListView _ InspectListView new.
  27601.     anInspectListView model: anInspector.
  27602.     anInspectListView window: (0 @ 0 extent: 40 @ 40).
  27603.     anInspectListView borderWidthLeft: 2 right: 0 top: 2 bottom: 2.
  27604.  
  27605.     ^ anInspectListView!
  27606. buildScheduledView: anInspector
  27607.     "This is old code referred to in benchmarks - may be deleted"
  27608.     | anInspectorView topView |
  27609.     anInspectorView _ self inspector: anInspector.
  27610.     topView _ StandardSystemView new.
  27611.     topView model: anInspector.
  27612.     topView addSubView: anInspectorView.
  27613.     topView label: anInspector object class name.
  27614.     topView minimumSize: 180 @ 120.
  27615.     ^topView!
  27616. buildTrashView: anInspector
  27617.     | inspectTrashView |
  27618.  
  27619.     inspectTrashView _ StringHolderView new.
  27620.     inspectTrashView model: (InspectorTrash for: anInspector object).
  27621.     inspectTrashView controller turnLockingOff.
  27622.     inspectTrashView window: (0 @ 0 extent: 115 @ 20).
  27623.     inspectTrashView borderWidthLeft: 2 right: 2 top: 0 bottom: 2.
  27624.  
  27625.     ^ inspectTrashView! !InstructionStream subclass: #InstructionPrinter
  27626.     instanceVariableNames: 'stream oldPC '
  27627.     classVariableNames: ''
  27628.     poolDictionaries: ''
  27629.     category: 'Kernel-Methods'!
  27630. InstructionPrinter comment:
  27631. 'My instances can print the object code of a CompiledMethod in symbolic format. They print into an instance variable, stream, and uses oldPC to determine how many bytes to print in the listing. The inherited variable, sender, is used in an ugly way to hold the method being printed.'!
  27632.  
  27633. !InstructionPrinter methodsFor: 'initialize-release'!
  27634. printInstructionsOn: aStream 
  27635.     "Append to the stream, aStream, a description of each bytecode in the 
  27636.     instruction stream."
  27637.     
  27638.     | end |
  27639.     stream _ aStream.
  27640.     end _ self method endPC.
  27641.     oldPC _ pc.
  27642.     [pc <= end]
  27643.         whileTrue: [super interpretNextInstructionFor: self]! !
  27644.  
  27645. !InstructionPrinter methodsFor: 'instruction decoding'!
  27646. blockReturnTop
  27647.     "Print the Return Top Of Stack bytecode."
  27648.  
  27649.     self print: 'blockReturn'!
  27650. doDup
  27651.     "Print the Duplicate Top Of Stack bytecode."
  27652.  
  27653.     self print: 'dup'!
  27654. doPop
  27655.     "Print the Remove Top Of Stack bytecode."
  27656.  
  27657.     self print: 'pop'!
  27658. jump: offset
  27659.     "Print the Unconditional Jump bytecode."
  27660.  
  27661.     self print: 'jumpTo: ' , (pc + offset) printString!
  27662. jump: offset if: condition 
  27663.     "Print the Conditional Jump bytecode."
  27664.  
  27665.     self print: 
  27666.         (condition
  27667.             ifTrue: ['jumpTrue: ']
  27668.             ifFalse: ['jumpFalse: '])
  27669.             , (pc + offset) printString!
  27670. methodReturnConstant: value 
  27671.     "Print the Return Constant bytecode."
  27672.  
  27673.     self print: 'return: ' , value printString!
  27674. methodReturnReceiver
  27675.     "Print the Return Self bytecode."
  27676.  
  27677.     self print: 'returnSelf'!
  27678. methodReturnTop
  27679.     "Print the Return Top Of Stack bytecode."
  27680.  
  27681.     self print: 'returnTop'!
  27682. popIntoLiteralVariable: anAssociation 
  27683.     "Print the Remove Top Of Stack And Store Into Literal Variable bytecode."
  27684.  
  27685.     self print: 'popIntoLit: ' , anAssociation key!
  27686. popIntoReceiverVariable: offset 
  27687.     "Print the Remove Top Of Stack And Store Into Instance Variable 
  27688.     bytecode."
  27689.  
  27690.     self print: 'popIntoRcvr: ' , offset printString!
  27691. popIntoTemporaryVariable: offset 
  27692.     "Print the Remove Top Of Stack And Store Into Temporary Variable 
  27693.     bytecode."
  27694.  
  27695.     self print: 'popIntoTemp: ' , offset printString!
  27696. pushActiveContext
  27697.     "Print the Push Active Context On Top Of Its Own Stack bytecode."
  27698.  
  27699.     self print: 'pushThisContext: '!
  27700. pushConstant: value
  27701.     "Print the Push Constant, value, on Top Of Stack bytecode."
  27702.  
  27703.     self print: 'pushConstant: ' , value printString!
  27704. pushLiteralVariable: anAssociation
  27705.     "Print the Push Contents Of anAssociation On Top Of Stack bytecode."
  27706.  
  27707.     self print: 'pushLit: ' , anAssociation key!
  27708. pushReceiver
  27709.     "Print the Push Active Context's Receiver on Top Of Stack bytecode."
  27710.  
  27711.     self print: 'self'!
  27712. pushReceiverVariable: offset
  27713.     "Print the Push Contents Of the Receiver's Instance Variable Whose Index 
  27714.     is the argument, offset, On Top Of Stack bytecode."
  27715.  
  27716.     self print: 'pushRcvr: ' , offset printString!
  27717. pushTemporaryVariable: offset
  27718.     "Print the Push Contents Of Temporary Variable Whose Index Is the 
  27719.     argument, offset, On Top Of Stack bytecode."
  27720.  
  27721.     self print: 'pushTemp: ' , offset printString!
  27722. send: selector super: supered numArgs: numberArguments
  27723.     "Print the Send Message With Selector, selector, bytecode. The argument, 
  27724.     supered, indicates whether the receiver of the message is specified with 
  27725.     'super' in the source method. The arguments of the message are found in 
  27726.     the top numArguments locations on the stack and the receiver just 
  27727.     below them."
  27728.  
  27729.     self print: (supered ifTrue: ['superSend: '] ifFalse: ['send: ']) , selector!
  27730. storeIntoLiteralVariable: anAssociation 
  27731.     "Print the Store Top Of Stack Into Literal Variable Of Method bytecode."
  27732.  
  27733.     self print: 'storeIntoLit: ' , anAssociation key!
  27734. storeIntoReceiverVariable: offset 
  27735.     "Print the Store Top Of Stack Into Instance Variable Of Method bytecode."
  27736.  
  27737.     self print: 'storeIntoRcvr: ' , offset printString!
  27738. storeIntoTemporaryVariable: offset 
  27739.     "Print the Store Top Of Stack Into Temporary Variable Of Method 
  27740.     bytecode."
  27741.  
  27742.     self print: 'storeIntoTemp: ' , offset printString! !
  27743.  
  27744. !InstructionPrinter methodsFor: 'printing'!
  27745. print: instruction 
  27746.     "Append to the receiver a description of the bytecode, instruction." 
  27747.  
  27748.     | code |
  27749.     stream print: oldPC; space.
  27750.     stream nextPut: $<.
  27751.     oldPC to: pc - 1 do: 
  27752.         [:i | 
  27753.         code _ (self method at: i) radix: 16.
  27754.         stream nextPut: 
  27755.             (code size < 5
  27756.                 ifTrue: [$0]
  27757.                 ifFalse: [code at: 4]).
  27758.         stream nextPut: code last; space].
  27759.     stream skip: -1.
  27760.     stream nextPut: $>.
  27761.     stream space.
  27762.     stream nextPutAll: instruction.
  27763.     stream cr.
  27764.     oldPC _ pc
  27765.     "(InstructionPrinter compiledMethodAt: #print:) symbolic."
  27766. ! !
  27767. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  27768.  
  27769. InstructionPrinter class
  27770.     instanceVariableNames: ''!
  27771.  
  27772. !InstructionPrinter class methodsFor: 'printing'!
  27773. printClass: class 
  27774.     "Create a file whose name is the argument followed by '.bytes'. Store on 
  27775.     the file the symbolic form of the compiled methods of the class."
  27776.     | file |
  27777.     file _ FileStream newFileNamed: class name , '.bytes'.
  27778.     class selectors do: 
  27779.         [:sel | 
  27780.         file cr; nextPutAll: sel; cr.
  27781.         (self on: (class compiledMethodAt: sel)) printInstructionsOn: file].
  27782.     file close
  27783.     "InstructionPrinter printClass: Parser."
  27784. ! !Object subclass: #InstructionStream
  27785.     instanceVariableNames: 'sender pc '
  27786.     classVariableNames: 'SpecialConstants '
  27787.     poolDictionaries: ''
  27788.     category: 'Kernel-Methods'!
  27789. InstructionStream comment:
  27790. 'My instances can interpret the byte-encoded Smalltalk instruction set. They maintain a program counter (pc) for streaming through CompiledMethods. My subclasses are Contexts, which inherit this capability. They store the return pointer in the instance variable sender, and the current position in their method in the instance variable pc. For other users, sender can hold a method to be similarly interpreted. The unclean re-use of sender to hold the method was to avoid a trivial subclass for the stand-alone scanning function.'!
  27791.  
  27792. !InstructionStream methodsFor: 'testing'!
  27793. willJumpIfFalse
  27794.     "Answer whether the next bytecode is a jump-if-false."
  27795.  
  27796.     | byte |
  27797.     byte _ self method at: pc.
  27798.     ^(byte between: 152 and: 159) or: [byte between: 172 and: 175]!
  27799. willReturn
  27800.     "Answer whether the next bytecode is a return."
  27801.  
  27802.     ^(self method at: pc) between: 120 and: 125!
  27803. willSend
  27804.     "Answer whether the next bytecode is a message-send."
  27805.  
  27806.     | byte |
  27807.     byte _ self method at: pc.
  27808.     byte < 128 ifTrue: [^false].
  27809.     byte >= 176 ifTrue: [^true].    "special send or short send"
  27810.     ^byte between: 131 and: 134    "long sends"!
  27811. willStorePop
  27812.     "Answer whether the next bytecode is a store-pop."
  27813.  
  27814.     | byte |
  27815.     byte _ self method at: pc.
  27816.     ^byte = 130 or: [byte between: 96 and: 111]! !
  27817.  
  27818. !InstructionStream methodsFor: 'decoding'!
  27819. interpretJump
  27820.  
  27821.     | byte |
  27822.     byte _ self method at: pc.
  27823.     (byte between: 144 and: 151) ifTrue:
  27824.         [pc _ pc + 1. ^byte - 143].
  27825.     (byte between: 160 and: 167) ifTrue:
  27826.         [pc _ pc + 2. ^(byte - 164) * 256 + (self method at: pc - 1)].
  27827.     ^nil!
  27828. interpretNextInstructionFor: client 
  27829.     "Send to the argument, client, a message that specifies the type of the 
  27830.     next instruction."
  27831.  
  27832.     | byte type offset method |
  27833.     method _ self method.  
  27834.     byte _ method at: pc.
  27835.     type _ byte // 16.  
  27836.     offset _ byte \\ 16.  
  27837.     pc _ pc+1.
  27838.     type=0 ifTrue: [^client pushReceiverVariable: offset].
  27839.     type=1 ifTrue: [^client pushTemporaryVariable: offset].
  27840.     type=2 ifTrue: [^client pushConstant: (method literalAt: offset+1)].
  27841.     type=3 ifTrue: [^client pushConstant: (method literalAt: offset+17)].
  27842.     type=4 ifTrue: [^client pushLiteralVariable: (method literalAt: offset+1)].
  27843.     type=5 ifTrue: [^client pushLiteralVariable: (method literalAt: offset+17)].
  27844.     type=6 
  27845.         ifTrue: [offset<8
  27846.                     ifTrue: [^client popIntoReceiverVariable: offset]
  27847.                     ifFalse: [^client popIntoTemporaryVariable: offset-8]].
  27848.     type=7
  27849.         ifTrue: [offset=0 ifTrue: [^client pushReceiver].
  27850.                 offset<8 ifTrue: [^client pushConstant: (SpecialConstants at: offset)].
  27851.                 offset=8 ifTrue: [^client methodReturnReceiver].
  27852.                 offset<12 ifTrue: [^client methodReturnConstant: 
  27853.                                                 (SpecialConstants at: offset-8)].
  27854.                 offset=12 ifTrue: [^client methodReturnTop].
  27855.                 offset=13 ifTrue: [^client blockReturnTop].
  27856.                 offset>13 ifTrue: [^self error: 'unusedBytecode']].
  27857.     type=8 ifTrue: [^self interpretExtension: offset in: method for: client].
  27858.     type=9
  27859.         ifTrue:  "short jumps"
  27860.             [offset<8 ifTrue: [^client jump: offset+1].
  27861.             ^client jump: offset-8+1 if: false].
  27862.     type=10 
  27863.         ifTrue:  "long jumps"
  27864.             [byte_ method at: pc.  pc_ pc+1.
  27865.             offset<8 ifTrue: [^client jump: offset-4*256 + byte].
  27866.             ^client jump: (offset bitAnd: 3)*256 + byte if: offset<12].
  27867.     type=11 
  27868.         ifTrue: 
  27869.             [^client 
  27870.                 send: (Smalltalk specialSelectorAt: offset+1) 
  27871.                 super: false
  27872.                 numArgs: (Smalltalk specialNargsAt: offset+1)].
  27873.     type=12 
  27874.         ifTrue: 
  27875.             [^client 
  27876.                 send: (Smalltalk specialSelectorAt: offset+17) 
  27877.                 super: false
  27878.                 numArgs: (Smalltalk specialNargsAt: offset+17)].
  27879.     type>12
  27880.         ifTrue: 
  27881.             [^client send: (method literalAt: offset+1) 
  27882.                     super: false
  27883.                     numArgs: type-13]! !
  27884.  
  27885. !InstructionStream methodsFor: 'scanning'!
  27886. addSelectorTo: set 
  27887.     "If this instruction is a send, add its selector to set."
  27888.  
  27889.     | byte literalNumber |
  27890.     byte _ self method at: pc.
  27891.     byte < 128 ifTrue: [^self].
  27892.     byte >= 176
  27893.         ifTrue: 
  27894.             ["special byte or short send"
  27895.             byte >= 208
  27896.                 ifTrue: [set add: (self method literalAt: (byte bitAnd: 15) + 1)]
  27897.                 ifFalse: [set add: (Smalltalk specialSelectorAt: byte - 176 + 1)]]
  27898.         ifFalse: 
  27899.             [(byte between: 131 and: 134)
  27900.                 ifTrue: 
  27901.                     [literalNumber _ byte odd
  27902.                                 ifTrue: [(self method at: pc + 1) \\ 32]
  27903.                                 ifFalse: [self method at: pc + 2].
  27904.                     set add: (self method literalAt: literalNumber + 1)]]!
  27905. followingByte
  27906.     "Answer the next bytecode."
  27907.  
  27908.     ^self method at: pc + 1!
  27909. method
  27910.     "Answer the compiled method that supplies the receiver's bytecodes."
  27911.  
  27912.     ^sender        "method access when used alone (not as part of a context)"!
  27913. nextByte
  27914.     "Answer the next bytecode."
  27915.  
  27916.     ^self method at: pc!
  27917. pc
  27918.     "Answer the index of the next bytecode."
  27919.  
  27920.     ^pc!
  27921. scanFor: scanBlock 
  27922.     "Answer the index of the first bytecode for which scanBlock answer true 
  27923.     when supplied with that bytecode."
  27924.  
  27925.     | method end byte type |
  27926.     method _ self method.
  27927.     end _ method endPC.
  27928.     [pc <= end]
  27929.         whileTrue: 
  27930.             [(scanBlock value: (byte _ method at: pc)) ifTrue: [^true].
  27931.             type _ byte // 16.
  27932.             pc _ 
  27933.                 type = 8
  27934.                     ifTrue: ["extensions"
  27935.                             pc + (#(2 2 2 2 3 2 3 1 1 1 ) at: byte \\ 16 + 1)]
  27936.                     ifFalse: [type = 10
  27937.                                 ifTrue: [pc + 2"long jumps"]
  27938.                                 ifFalse: [pc + 1]]].
  27939.     ^false! !
  27940.  
  27941. !InstructionStream methodsFor: 'private'!
  27942. interpretExtension: offset in: method for: client
  27943.  
  27944.     | numberArguments literalNumber type offset2 |
  27945.     "pc has already been incremented by 1"
  27946.     offset < 3
  27947.         ifTrue: 
  27948.             ["extended pushes and pops"
  27949.             type _ (method at: pc) // 64.
  27950.             offset2 _ (method at: pc) \\ 64.
  27951.             pc _ pc + 1.
  27952.             offset = 0
  27953.                 ifTrue: 
  27954.                     [type = 0 ifTrue: [^client pushReceiverVariable: offset2].
  27955.                     type = 1 ifTrue: [^client pushTemporaryVariable: offset2].
  27956.                     type = 2 
  27957.                         ifTrue: [^client pushConstant: (method literalAt: offset2 + 1)].
  27958.                     type = 3
  27959.                         ifTrue: [^client pushLiteralVariable: 
  27960.                                     (method literalAt: offset2 + 1)]].
  27961.             offset = 1
  27962.                 ifTrue: 
  27963.                     [type = 0 ifTrue: [^client storeIntoReceiverVariable: offset2].
  27964.                     type = 1 ifTrue: [^client storeIntoTemporaryVariable: offset2].
  27965.                     type = 2 ifTrue: [self error: 'illegalStore'].
  27966.                     type = 3 
  27967.                         ifTrue: [^client storeIntoLiteralVariable: 
  27968.                                     (method literalAt: offset2 + 1)]].
  27969.             offset = 2
  27970.                 ifTrue: 
  27971.                     [type = 0 ifTrue: [^client popIntoReceiverVariable: offset2].
  27972.                     type = 1 ifTrue: [^client popIntoTemporaryVariable: offset2].
  27973.                     type = 2 ifTrue: [self error: 'illegalStore'].
  27974.                     type = 3 
  27975.                         ifTrue: [^client popIntoLiteralVariable: 
  27976.                                     (method literalAt: offset2 + 1)]]].
  27977.     offset < 7
  27978.         ifTrue: 
  27979.             ["extended sends"
  27980.             offset odd
  27981.                 ifTrue: 
  27982.                     [numberArguments _ (method at: pc) // 32.
  27983.                     literalNumber _ (method at: pc) \\ 32.
  27984.                     pc _ pc + 1]
  27985.                 ifFalse: 
  27986.                     [numberArguments _ method at: pc.
  27987.                     literalNumber _ method at: pc + 1.
  27988.                     pc _ pc + 2].
  27989.             ^client
  27990.                 send: (method literalAt: literalNumber + 1)
  27991.                 super: offset > 4
  27992.                 numArgs: numberArguments].
  27993.     offset = 7 ifTrue: [^client doPop].
  27994.     offset = 8 ifTrue: [^client doDup].
  27995.     offset = 9 ifTrue: [^client pushActiveContext].
  27996.     self error: 'unusedBytecode'!
  27997. method: method pc: startpc
  27998.  
  27999.     sender _ method. 
  28000.     "allows this class to stand alone as a method scanner"
  28001.     pc _ startpc! !
  28002. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  28003.  
  28004. InstructionStream class
  28005.     instanceVariableNames: ''!
  28006.  
  28007. !InstructionStream class methodsFor: 'class initialization'!
  28008. initialize
  28009.     "Initialize an array of special constants returned by single-bytecode returns."
  28010.  
  28011.     SpecialConstants _ 
  28012.         (Array with: true with: false with: nil)
  28013.             , (Array with: -1 with: 0 with: 1 with: 2)    
  28014.     "InstructionStream initialize."
  28015. ! !
  28016.  
  28017. !InstructionStream class methodsFor: 'instance creation'!
  28018. on: method 
  28019.     "Answer an instance of me on the argument, method."
  28020.  
  28021.     ^self new method: method pc: method initialPC! !
  28022.  
  28023. InstructionStream initialize!
  28024. Number subclass: #Integer
  28025.     instanceVariableNames: ''
  28026.     classVariableNames: 'SinArray '
  28027.     poolDictionaries: ''
  28028.     category: 'Numeric-Numbers'!
  28029. Integer comment:
  28030. 'I am a common abstract superclass for all Integer implementations. My implementation subclasses are SmallInteger, LargePositiveInteger, and LargeNegativeInteger.
  28031.     
  28032. Integer division consists of:
  28033.     /    exact division, answers a fraction if result is not a whole integer
  28034.     //    answers an Integer, rounded towards negative infinity
  28035.     \\    is modulo rounded towards negative infinity
  28036.     quo: truncated division, rounded towards zero'!
  28037.  
  28038. !Integer methodsFor: 'testing'!
  28039. benchmark "Time millisecondsToRun: [10 benchmark]
  28040.     11950 (AST 1.0 3/31 on 8100 (arith & spl prims in primary dispatch)
  28041.     15100 (AST 1.0 3/20 on 8100 (checkProcessSwitch out of inner loop)
  28042.     17033 (AST 1.0 3/15 on 8100)
  28043.     35483 (AST 1.0 3/1 on 8100)
  28044.     4110 (PPS interpreter on 8100)
  28045.     10880 (APDA interpreter on Duo)"
  28046.     | size flags i prime k count iter |
  28047.     size _ 8190.
  28048.     1 to: self do:
  28049.         [:iter |
  28050.         count _ 0.
  28051.         flags _ (Array new: size) atAllPut: true.
  28052.         1 to: size do:
  28053.             [:i | (flags at: i) ifTrue:
  28054.                 [prime _ i+1.
  28055.                 k _ i + prime.
  28056.                 [k <= size] whileTrue:
  28057.                     [flags at: k put: false.
  28058.                     k _ k + prime].
  28059.                 count _ count + 1]]].
  28060.     ^ count!
  28061. even 
  28062.     "Refer to the comment in Number|even."
  28063.  
  28064.     ^((self digitAt: 1) bitAnd: 1) = 0!
  28065. isInteger
  28066.     "True for all subclasses of Integer."
  28067.  
  28068.     ^ true!
  28069. isPowerOfTwo
  28070.     ^ (self bitAnd: self-1) = 0! !
  28071.  
  28072. !Integer methodsFor: 'arithmetic'!
  28073. * aNumber
  28074.     "Refer to the comment in Number * " 
  28075.     aNumber isInteger
  28076.         ifTrue: [^ self digitMultiply: aNumber 
  28077.                     neg: self negative ~~ aNumber negative]
  28078.         ifFalse: [^self retry: #* coercing: aNumber]!
  28079. + aNumber
  28080.     "Refer to the comment in Number + "
  28081.     (aNumber isInteger)
  28082.         ifTrue: [self negative == aNumber negative
  28083.                     ifTrue: [^(self digitAdd: aNumber) normalize]
  28084.                     ifFalse: [^self digitSubtract: aNumber]]
  28085.         ifFalse: [^self retry: #+ coercing: aNumber]!
  28086. - aNumber
  28087.     "Refer to the comment in Number - "
  28088.     (aNumber isInteger)
  28089.         ifTrue: [self negative == aNumber negative
  28090.                     ifTrue: [^ self digitSubtract: aNumber]
  28091.                     ifFalse: [^ (self digitAdd: aNumber) normalize]]
  28092.         ifFalse: [^self retry: #- coercing: aNumber]!
  28093. / aNumber
  28094.     "Refer to the comment in Number / "
  28095.     | quoRem |
  28096.     (aNumber isInteger)
  28097.         ifTrue: 
  28098.             [quoRem _ self digitDiv: aNumber 
  28099.                             neg: self negative ~~ aNumber negative.
  28100.             (quoRem at: 2) = 0
  28101.                 ifTrue: [^(quoRem at: 1) normalize]
  28102.                 ifFalse: [^(Fraction numerator: self denominator: aNumber) reduced]]
  28103.         ifFalse: [^self retry: #/ coercing: aNumber]!
  28104. // aNumber
  28105.  
  28106.     | q |
  28107.     aNumber = 0 ifTrue: [^self error: 'division by 0'].
  28108.     self = 0 ifTrue: [^0].
  28109.     q _ self quo: aNumber 
  28110.     "Refer to the comment in Number|//.".
  28111.     (q negative
  28112.         ifTrue: [q * aNumber ~= self]
  28113.         ifFalse: [q = 0 and: [self negative ~= aNumber negative]])
  28114.         ifTrue: [^q - 1"Truncate towards minus infinity"]
  28115.         ifFalse: [^q]!
  28116. alignedTo: anInteger
  28117.     "Answer the smallest number not less than receiver that is a multiple of anInteger."
  28118.  
  28119.     ^(self+anInteger-1//anInteger)*anInteger
  28120.  
  28121. "5 alignedTo: 2"
  28122. "12 alignedTo: 3"!
  28123. quo: aNumber 
  28124.     "Refer to the comment in Number quo: "
  28125.     | ng quo |
  28126.     (aNumber isInteger)
  28127.         ifTrue: 
  28128.             [ng _ self negative == aNumber negative == false.
  28129.             quo _ (self digitDiv: aNumber neg: ng) at: 1.
  28130.             ^ quo normalize]
  28131.         ifFalse: [^self retry: #quo: coercing: aNumber]! !
  28132.  
  28133. !Integer methodsFor: 'comparing'!
  28134. < anInteger
  28135.     (anInteger isInteger)
  28136.         ifTrue: [self negative == anInteger negative
  28137.                     ifTrue: [self negative
  28138.                                 ifTrue: [^(self digitCompare: anInteger) > 0]
  28139.                                 ifFalse: [^(self digitCompare: anInteger) < 0]]
  28140.                     ifFalse: [^self negative]]
  28141.         ifFalse: [^self retry: #< coercing: anInteger]!
  28142. = arg
  28143.     arg isNumber
  28144.         ifFalse: [^ false].
  28145.     arg isInteger
  28146.         ifTrue: [arg negative == self negative
  28147.                     ifTrue: [^ (self digitCompare: arg) = 0]
  28148.                     ifFalse: [^ false]]
  28149.         ifFalse: [^ self retry: #= coercing: arg]!
  28150. > anInteger
  28151.     (anInteger isInteger)
  28152.         ifTrue: [self negative == anInteger negative
  28153.                     ifTrue: [self negative
  28154.                                 ifTrue: [^(self digitCompare: anInteger) < 0]
  28155.                                 ifFalse: [^(self digitCompare: anInteger) > 0]]
  28156.                     ifFalse: [^anInteger negative]]
  28157.         ifFalse: [^self retry: #> coercing: anInteger]!
  28158. hash
  28159.     "Hash is reimplemented because = is implemented."
  28160.  
  28161.     ^(self lastDigit bitShift: 8) + (self digitAt: 1)! !
  28162.  
  28163. !Integer methodsFor: 'truncation and round off'!
  28164. atRandom
  28165.     "Return a random integer from 1 to self.  Heavy users should use Interval atRandom or atRandom: directly."
  28166.     ^ (1 to: self) atRandom!
  28167. ceiling 
  28168.     "Refer to the comment in Number|ceiling."!
  28169. floor 
  28170.     "Refer to the comment in Number|floor."!
  28171. normalize 
  28172.     "SmallInts OK; LgInts override"
  28173.     ^ self!
  28174. rounded 
  28175.     "Refer to the comment in Number|rounded."!
  28176. truncated 
  28177.     "Refer to the comment in Number|truncated."! !
  28178.  
  28179. !Integer methodsFor: 'enumerating'!
  28180. timesRepeat: aBlock 
  28181.     "Evaluate the argument, aBlock, the number of times represented by the 
  28182.     receiver."
  28183.  
  28184.     | count |
  28185.     count _ 1.
  28186.     [count <= self]
  28187.         whileTrue: 
  28188.             [aBlock value.
  28189.             count _ count + 1]! !
  28190.  
  28191. !Integer methodsFor: 'mathematical functions'!
  28192. degreeCos
  28193.     "Return the cosine of self as an angle in degrees"
  28194.     ^ (90 + self) degreeSin!
  28195. degreeSin
  28196.     "Return the sine of self as an angle in degrees"
  28197.     self < 0 ifTrue: [^ 0.0 - (0 - self) degreeSin].
  28198.     self > 360 ifTrue: [^ (self \\ 360) degreeSin].
  28199.     self > 180 ifTrue: [^ 0.0 - (self - 180) degreeSin].
  28200.     self > 90 ifTrue: [^ (180 - self) degreeSin].
  28201.     " now 0<= self <= 90 "
  28202.     ^ SinArray at: self+1!
  28203. factorial
  28204.     "Answer the factorial of the receiver. Create an error notification if the 
  28205.     receiver is less than 0."
  28206.  
  28207.     self = 0 ifTrue: [^1].
  28208.     self < 0
  28209.         ifTrue: [self error: 'factorial invalid for: ' , self printString]
  28210.         ifFalse: [^self * (self - 1) factorial]!
  28211. gcd: anInteger 
  28212.     "Answer the greatest common divisor of the receiver and n. Uses Roland 
  28213.     Silver's algorithm (see Knuth, Vol. 2)."
  28214.  
  28215.     | m n d t |
  28216.     m _ self abs max: anInteger abs.
  28217.     n _ self abs min: anInteger abs.
  28218.     m \\ n = 0 ifTrue: [^n].
  28219.     "easy test, speeds up rest"
  28220.     d _ 0.
  28221.     [n even and: [m even]]
  28222.         whileTrue: 
  28223.             [d _ d + 1.
  28224.             n _ n bitShift: -1.
  28225.             m _ m bitShift: -1].
  28226.     [n even]
  28227.         whileTrue: [n _ n bitShift: -1].
  28228.     [m even]
  28229.         whileTrue: [m _ m bitShift: -1].
  28230.     [m = n]
  28231.         whileFalse: 
  28232.             [m > n
  28233.                 ifTrue: 
  28234.                     [m _ m - n]
  28235.                 ifFalse: 
  28236.                     [t _ m.
  28237.                     m _ n - m.
  28238.                     n _ t].
  28239.             "Make sure larger gets replaced"
  28240.             [m even]
  28241.                 whileTrue: [m _ m bitShift: -1]].
  28242.     d = 0 ifTrue: [^m].
  28243.     ^m bitShift: d!
  28244. lcm: n 
  28245.     "Answer the least common multiple of the receiver and n."
  28246.  
  28247.     ^self // (self gcd: n) * n! !
  28248.  
  28249. !Integer methodsFor: 'bit manipulation'!
  28250. << shiftAmount  "left shift"
  28251.     shiftAmount < 0 ifTrue: [self error: 'negative arg'].
  28252.     ^ self bitShift: shiftAmount!
  28253. >> shiftAmount  "left shift"
  28254.     shiftAmount < 0 ifTrue: [self error: 'negative arg'].
  28255.     ^ self bitShift: 0 - shiftAmount!
  28256. allMask: mask 
  28257.     "Treat the argument as a bit mask. Answer whether all of the bits that 
  28258.     are 1 in the argument are 1 in the receiver."
  28259.  
  28260.     ^mask = (self bitAnd: mask)!
  28261. anyMask: mask 
  28262.     "Treat the argument as a bit mask. Answer whether any of the bits that 
  28263.     are 1 in the argument are 1 in the receiver."
  28264.  
  28265.     ^0 ~= (self bitAnd: mask)!
  28266. bitAnd: n 
  28267.     "Answer an Integer whose bits are the logical AND of the receiver's bits 
  28268.     and those of the argument, n."
  28269.     | norm |
  28270.     norm _ n normalize.
  28271.     ^ self digitLogic: norm
  28272.         op: #bitAnd:
  28273.         length: (self digitLength max: norm digitLength)!
  28274. bitInvert32
  28275.     "Answer the 32-bit complement of the receiver."
  28276.  
  28277.     ^ self bitXor: 16rFFFFFFFF!
  28278. bitOr: n 
  28279.     "Answer an Integer whose bits are the logical OR of the receiver's bits 
  28280.     and those of the argument, n."
  28281.     | norm |
  28282.     norm _ n normalize.
  28283.     ^self digitLogic: norm
  28284.         op: #bitOr:
  28285.         length: (self digitLength max: norm digitLength)!
  28286. bitShift: shiftCount 
  28287.     "Answer an Integer whose value (in twos-complement representation) is 
  28288.     the receiver's value (in twos-complement representation) shifted left by 
  28289.     the number of bits indicated by the argument. Negative arguments shift 
  28290.     right. Zeros are shifted in from the right in left shifts."
  28291.     | rShift |
  28292.     shiftCount >= 0 ifTrue: [^ self digitLshift: shiftCount].
  28293.     rShift _ 0 - shiftCount.
  28294.     ^ (self digitRshift: (rShift bitAnd: 7)
  28295.                 bytes: (rShift bitShift: -3)
  28296.                 lookfirst: self digitLength) normalize!
  28297. bitXor: n 
  28298.     "Answer an Integer whose bits are the logical XOR of the receiver's bits 
  28299.     and those of the argument, n."
  28300.     | norm |
  28301.     norm _ n normalize.
  28302.     ^self
  28303.         digitLogic: norm
  28304.         op: #bitXor:
  28305.         length: (self digitLength max: norm digitLength)!
  28306. highBit
  28307.     "Answer the index of the high order bit of this number."
  28308.     | realLength lastDigit |
  28309.     realLength _ self digitLength.
  28310.     [(lastDigit _ self digitAt: realLength) = 0]
  28311.         whileTrue:
  28312.         [(realLength _ realLength - 1) = 0 ifTrue: [^ 0]].
  28313.     ^ lastDigit highBit + (8 * (realLength - 1))!
  28314. noMask: mask 
  28315.     "Treat the argument as a bit mask. Answer whether none of the bits that 
  28316.     are 1 in the argument are 1 in the receiver."
  28317.  
  28318.     ^0 = (self bitAnd: mask)! !
  28319.  
  28320. !Integer methodsFor: 'converting'!
  28321. asCharacter
  28322.     "Answer the Character whose value is the receiver."
  28323.  
  28324.     ^Character value: self!
  28325. asFloat
  28326.     "Answer a Float that represents the value of the receiver."
  28327.  
  28328.     | factor sum |
  28329.     sum _ 0.0.
  28330.     factor _ self sign asFloat.
  28331.     1 to: self size do: 
  28332.         [:i | 
  28333.         sum _ (self digitAt: i) * factor + sum.
  28334.         factor _ factor * 256.0].
  28335.     ^sum!
  28336. asFraction
  28337.     "Answer a Fraction that represents value of the the receiver."
  28338.  
  28339.     ^Fraction numerator: self denominator: 1!
  28340. asInteger
  28341.     "Answer with the receiver itself."
  28342.  
  28343.     ^self
  28344.  
  28345. ! !
  28346.  
  28347. !Integer methodsFor: 'coercing'!
  28348. coerce: aNumber 
  28349.     "Refer to the comment in Number|coerce:."
  28350.  
  28351.     ^ aNumber asInteger!
  28352. coerceToPoint
  28353.     "Coerce the receiver into a point by taking the high order part as the vertical coordinate and the low order part as the horizontal coordinate.  The part divisin is at 65536."
  28354.  
  28355.     | x y |
  28356.     x _ self bitAnd: 16rFFFF.
  28357.     y _ self bitShift: -16.
  28358.     (x >= 16r8000) ifTrue: [ x _ x - 16r10000 ].
  28359.     (y >= 16r8000) ifTrue: [ y _ y - 16r10000 ].
  28360.     ^ Point x: x y: y
  28361. !
  28362. generality 
  28363.     "Refer to the comment in Number|generality."
  28364.  
  28365.     ^40! !
  28366.  
  28367. !Integer methodsFor: 'printing'!
  28368. asStringWithCommas  "123456789 asStringWithCommas"
  28369.     | digits |
  28370.     digits _ self abs printString.
  28371.     ^ String streamContents:
  28372.         [:strm | 1 to: digits size do: 
  28373.             [:i | strm nextPut: (digits at: i).
  28374.             (i < digits size and: [(i - digits size) \\ 3 = 0])
  28375.                 ifTrue: [strm nextPut: $,]]]!
  28376. hex
  28377.     ^ self printStringBase: 16!
  28378. hex8  "16r3333 hex8"
  28379.     | hex |
  28380.     hex _ self hex.  "16rNNN"
  28381.     hex size < 11
  28382.         ifTrue: [^ hex copyReplaceFrom: 4 to: 3
  28383.                          with: ('00000000' copyFrom: 1 to: 11-hex size)]
  28384.         ifFalse: [^ hex]!
  28385. isLiteral
  28386.  
  28387.     ^true!
  28388. printOn: aStream base: b 
  28389.     "Print a representation of the receiver on the stream, aStream, in base, b, 
  28390.     where 2<=b<=16."
  28391.     | digits source dest i j pos t rem |
  28392.     b = 10 ifFalse: [aStream print: b; nextPut: $r].
  28393.     i _ self digitLength.
  28394.     "Estimate size of result, conservatively"
  28395.     digits _ Array new: i * 8.
  28396.     pos _ 0.
  28397.     dest _ i <= 1
  28398.         ifTrue: [self]
  28399.         ifFalse: [LargePositiveInteger new: i].
  28400.     source _ self.
  28401.     [i >= 1]
  28402.         whileTrue: 
  28403.             [rem _ 0.
  28404.             j _ i.
  28405.             [j > 0]
  28406.                 whileTrue: 
  28407.                     [t _ (rem bitShift: 8) + (source digitAt: j).
  28408.                     dest digitAt: j put: t // b.
  28409.                     rem _ t \\ b.
  28410.                     j _ j - 1].
  28411.             pos _ pos + 1.
  28412.             digits at: pos put: rem.
  28413.             source _ dest.
  28414.             (source digitAt: i) = 0 ifTrue: [i _ i - 1]].
  28415.     "(dest digitAt: 1) printOn: aStream base: b."
  28416.     [pos > 0]
  28417.         whileTrue:
  28418.             [aStream nextPut: (Character digitValue: (digits at: pos)).
  28419.             pos _ pos - 1]!
  28420. radix: radix 
  28421.     "Answer a String representing the receiver as a base radix integer."
  28422.  
  28423.     ^ self printStringBase: radix! !
  28424.  
  28425. !Integer methodsFor: 'system primitives'!
  28426. lastDigit
  28427.     "Answer the last digit of the integer."
  28428.  
  28429.     ^self digitAt: self digitLength!
  28430. replaceFrom: start to: stop with: replacement startingAt: repStart
  28431.     | j |  "Catches failure if LgInt replace primitive fails"
  28432.     j _ repStart.
  28433.     start to: stop do:
  28434.         [:i |
  28435.         self digitAt: i put: (replacement digitAt: j).
  28436.         j _ j+1]! !
  28437.  
  28438. !Integer methodsFor: 'private'!
  28439. copyto: x
  28440.     | stop |
  28441.     stop _ self digitLength min: x digitLength.
  28442.     ^ x replaceFrom: 1 to: stop with: self startingAt: 1!
  28443. digitAdd: arg
  28444.     | len arglen accum sum |
  28445.     accum _ 0.
  28446.     (len _ self digitLength) < (arglen _ arg digitLength)
  28447.         ifTrue: [len _ arglen].
  28448.     "Open code max: for speed"
  28449.     sum _ Integer new: len neg: self negative.
  28450.     1 to: len do: 
  28451.         [:i |
  28452.         accum _ (accum bitShift: -8) + (self digitAt: i) + (arg digitAt: i).
  28453.         sum digitAt: i put: (accum bitAnd: 255)].
  28454.     accum > 255 ifTrue: 
  28455.             [sum _ sum growby: 1.
  28456.             sum at: sum digitLength put: (accum bitShift: -8)].
  28457.     ^sum!
  28458. digitCompare: arg
  28459.     "Compare the magnitude of self with that of arg.
  28460.     Return a code of 1, 0, -1 for self >, = , < arg"
  28461.     | len arglen argDigit selfDigit |
  28462.     len _ self digitLength.
  28463.     (arglen _ arg digitLength) ~= len 
  28464.         ifTrue: [arglen > len
  28465.                     ifTrue: [^-1]
  28466.                     ifFalse: [^1]].
  28467.     [len > 0]
  28468.         whileTrue: 
  28469.             [(argDigit _ arg digitAt: len) ~= (selfDigit _ self digitAt: len) 
  28470.                 ifTrue: [argDigit < selfDigit
  28471.                             ifTrue: [^1]
  28472.                             ifFalse: [^-1]].
  28473.             len _ len - 1].
  28474.     ^0!
  28475. digitDiv: arg neg: ng 
  28476.     "Answer with an array of (quotient, remainder)."
  28477.     | quo rem ql d div dh dnh dl qhi qlo i j k l hi lo r3 a t |
  28478.     l _ self digitLength - arg digitLength + 1.
  28479.     l <= 0 ifTrue: [^Array with: 0 with: self].
  28480.     d _ 8 - arg lastDigit highBit.
  28481.     div _ arg digitLshift: d.  div _ div growto: div digitLength + 1.
  28482.     "shifts so high order word is >=128"
  28483.     rem _ self digitLshift: d.
  28484.     rem digitLength = self digitLength ifTrue:
  28485.         [rem _ rem growto: self digitLength + 1].
  28486.     "makes a copy and shifts"
  28487.     quo _ Integer new: l neg: ng.
  28488.     dl _ div digitLength - 1.
  28489.     "Last actual byte of data"
  28490.     ql _ l.
  28491.     dh _ div digitAt: dl.
  28492.     dnh _
  28493.          dl = 1
  28494.             ifTrue: [0]
  28495.             ifFalse: [div digitAt: dl - 1].
  28496.     1 to: ql do: 
  28497.         [:k | 
  28498.         "maintain quo*arg+rem=self"
  28499.         "Estimate rem/div by dividing the leading to bytes of rem by dh."
  28500.         "The estimate is q = qhi*16+qlo, where qhi and qlo are nibbles."
  28501.         j _ rem digitLength + 1 - k.
  28502.         "r1 _ rem digitAt: j."
  28503.         (rem digitAt: j) = dh
  28504.             ifTrue: [qhi _ qlo _ 15"i.e. q=255"]
  28505.             ifFalse: 
  28506.                 ["Compute q = (r1,r2)//dh, t = (r1,r2)\\dh.  
  28507.                 Note that r1,r2 are bytes, not nibbles.  
  28508.                 Be careful not to generate intermediate results exceeding 13 bits."
  28509.                 "r2 _ (rem digitAt: j - 1)."
  28510.                 t _ ((rem digitAt: j) bitShift: 4) + ((rem digitAt: j - 1) bitShift: -4).
  28511.                 qhi _ t // dh.
  28512.                 t _ (t \\ dh bitShift: 4) + ((rem digitAt: j - 1) bitAnd: 15).
  28513.                 qlo _ t // dh.
  28514.                 t _ t \\ dh.
  28515.                 "Next compute (hi,lo) _ q*dnh"
  28516.                 hi _ qhi * dnh.
  28517.                 lo _ qlo * dnh + ((hi bitAnd: 15) bitShift: 4).
  28518.                 hi _ (hi bitShift: -4) + (lo bitShift: -8).
  28519.                 lo _ lo bitAnd: 255.
  28520.                 "Correct overestimate of q.  
  28521.                 Max of 2 iterations through loop -- see Knuth vol. 2"
  28522.                 r3 _ 
  28523.                     j < 3 ifTrue: [0]
  28524.                          ifFalse: [rem digitAt: j - 2].
  28525.                 [(t < hi or: [t = hi and: [r3 < lo]]) and: 
  28526.                         ["i.e. (t,r3) < (hi,lo)"
  28527.                         qlo _ qlo - 1.
  28528.                         lo _ lo - dnh.
  28529.                         lo < 0
  28530.                             ifTrue: 
  28531.                                 [hi _ hi - 1.
  28532.                                 lo _ lo + 256].
  28533.                         hi >= dh]]
  28534.                     whileTrue: [hi _ hi - dh].
  28535.                 qlo < 0
  28536.                     ifTrue: 
  28537.                         [qhi _ qhi - 1.
  28538.                         qlo _ qlo + 16]].
  28539.         "Subtract q*div from rem"
  28540.         l _ j - dl.
  28541.         a _ 0.
  28542.         1 to: div digitLength do: 
  28543.             [:i | 
  28544.             hi _ (div digitAt: i) * qhi.
  28545.             lo _ 
  28546.                 a + (rem digitAt: l) 
  28547.                     - ((hi bitAnd: 15) bitShift: 4) 
  28548.                     - ((div digitAt: i) * qlo).
  28549.             rem digitAt: l put: (lo bitAnd: 255).
  28550.             a _ (lo bitShift: -8) - (hi bitShift: -4).
  28551.             l _ l + 1].
  28552.         a < 0
  28553.             ifTrue: 
  28554.                 ["Add div back into rem, decrease q by 1"
  28555.                 qlo _ qlo - 1.
  28556.                 l _ j - dl.
  28557.                 a _ 0.
  28558.                 1 to: div digitLength do: 
  28559.                     [:i | 
  28560.                     a _ (a bitShift: -8) + (rem digitAt: l) + (div digitAt: i).
  28561.                     rem digitAt: l put: (a bitAnd: 255).
  28562.                     l _ l + 1]].
  28563.         quo digitAt: quo digitLength + 1 - k put: (qhi bitShift: 4) + qlo].
  28564.     rem _ rem digitRshift: d bytes: 0 lookfirst: dl.
  28565.     ^Array with: quo with: rem!
  28566. digitLogic: arg op: op length: len
  28567.     | result i neg1 neg2 rneg z1 z2 rz b1 b2 b |
  28568.     neg1 _ self negative.
  28569.     neg2 _ arg negative.
  28570.     rneg _ 
  28571.         ((neg1 ifTrue: [-1] ifFalse: [0])
  28572.             perform: op 
  28573.             with: (neg2
  28574.                     ifTrue: [-1]
  28575.                     ifFalse: [0])) < 0.
  28576.     result _ Integer new: len neg: rneg.
  28577.     rz _ z1 _ z2 _ true.
  28578.     1 to: result digitLength do: 
  28579.         [:i | 
  28580.         b1 _ self digitAt: i.
  28581.         neg1 
  28582.             ifTrue: [b1 _ z1
  28583.                         ifTrue: [b1 = 0
  28584.                                     ifTrue: [0]
  28585.                                     ifFalse: 
  28586.                                         [z1 _ false.
  28587.                                         256 - b1]]
  28588.                         ifFalse: [255 - b1]].
  28589.         b2 _ arg digitAt: i.
  28590.         neg2 
  28591.             ifTrue: [b2 _ z2
  28592.                         ifTrue: [b2 = 0
  28593.                                     ifTrue: [0]
  28594.                                     ifFalse: 
  28595.                                         [z2 _ false.
  28596.                                         256 - b2]]
  28597.                         ifFalse: [255 - b2]].
  28598.         b _ b1 perform: op with: b2.
  28599.         b = 0
  28600.             ifTrue: 
  28601.                 [result digitAt: i put: 0]
  28602.             ifFalse: 
  28603.                 [result 
  28604.                     digitAt: i 
  28605.                     put: (rneg
  28606.                             ifTrue: [rz ifTrue: 
  28607.                                             [rz _ false.
  28608.                                             256 - b]
  28609.                                         ifFalse: [255 - b]]
  28610.                         ifFalse: [b])]].
  28611.     ^ result normalize!
  28612. digitLshift: shiftCount
  28613.     | carry rShift mask len result digit byteShift bitShift highBit |
  28614.     (highBit _ self highBit) = 0 ifTrue: [^ 0].
  28615.     len _ highBit + shiftCount + 7 // 8.
  28616.     result _ Integer new: len neg: self negative.
  28617.     byteShift _ shiftCount // 8.
  28618.     bitShift _ shiftCount \\ 8.
  28619.     bitShift = 0 ifTrue:  
  28620.         ["Fast version for byte-aligned shifts"
  28621.         ^ result replaceFrom: byteShift+1 to: len
  28622.                 with: self startingAt: 1].
  28623.     carry _ 0.
  28624.     rShift _ bitShift - 8.
  28625.     mask _ 255 bitShift: 0 - bitShift.
  28626.     1 to: byteShift do: [:i | result digitAt: i put: 0].
  28627.     1 to: len - byteShift do: 
  28628.         [:i | 
  28629.         digit _ self digitAt: i.
  28630.         result digitAt: i + byteShift 
  28631.             put: (((digit bitAnd: mask) bitShift: bitShift) bitOr: carry).
  28632.         carry _ digit bitShift: rShift].
  28633.     ^ result!
  28634. digitMultiply: arg neg: ng
  28635.     | prod prodLen carry digit i j k ab |
  28636.     (arg digitLength = 1 and: [(arg digitAt: 1) = 0]) ifTrue: [^0].
  28637.     prodLen _ self digitLength + arg digitLength.
  28638.     prod _ Integer new: prodLen neg: ng.
  28639.     "prod starts out all zero"
  28640.     1 to: self digitLength do: 
  28641.         [:i | 
  28642.         (digit _ self digitAt: i) ~= 0
  28643.             ifTrue: 
  28644.                 [k _ i.
  28645.                 carry _ 0.
  28646.                 "Loop invariant: 0<=carry<=0377, k=i+j-1"
  28647.                 1 to: arg digitLength do: 
  28648.                     [:j | 
  28649.                     ab _ ((arg digitAt: j) * digit) + carry
  28650.                             + (prod digitAt: k).
  28651.                     carry _ ab bitShift: -8.
  28652.                     prod digitAt: k put: (ab bitAnd: 255).
  28653.                     k _ k + 1].
  28654.                 prod digitAt: k put: carry]].
  28655.     ^ prod normalize!
  28656. digitRshift: anInteger bytes: b lookfirst: a 
  28657.      "Shift right 8*b+anInteger bits, 0<=n<8.
  28658.     Discard all digits beyond a, and all zeroes at or below a."
  28659.  
  28660.     | n x i r f m digit count |
  28661.     n _ 0 - anInteger.
  28662.     x _ 0.
  28663.     f _ n + 8.
  28664.     i _ a.
  28665.     m _ 255 bitShift: 0 - f.
  28666.     digit _ self digitAt: i.
  28667.     [((digit bitShift: n) bitOr: x) = 0 and: [i ~= 1]] whileTrue:
  28668.         [x _ digit bitShift: f "Can't exceed 8 bits".
  28669.         i _ i - 1.
  28670.         digit _ self digitAt: i].
  28671.     i <= b ifTrue: [^Integer new: 0 neg: self negative].  "All bits lost"
  28672.     r _ Integer new: i - b neg: self negative.
  28673.     count _ i.
  28674.     x _ (self digitAt: b + 1) bitShift: n.
  28675.     b + 1 to: count do:
  28676.         [:i | digit _ self digitAt: i + 1.
  28677.         r digitAt: i - b put: (((digit bitAnd: m) bitShift: f) bitOr: x) 
  28678.             "Avoid values > 8 bits".
  28679.         x _ digit bitShift: n].
  28680.     ^r!
  28681. digitSubtract: arg
  28682.     | smaller larger z sum sl al ng |
  28683.     sl _ self digitLength.
  28684.     al _ arg digitLength.
  28685.     (sl = al
  28686.         ifTrue: 
  28687.             [[(self digitAt: sl) = (arg digitAt: sl) and: [sl > 1]]
  28688.                 whileTrue: [sl _ sl - 1].
  28689.             al _ sl.
  28690.             (self digitAt: sl) < (arg digitAt: sl)]
  28691.         ifFalse: [sl < al])
  28692.         ifTrue: 
  28693.             [larger _ arg.
  28694.             smaller _ self.
  28695.             ng _ self negative == false.
  28696.             sl _ al]
  28697.         ifFalse: 
  28698.             [larger _ self.
  28699.             smaller _ arg.
  28700.             ng _ self negative].
  28701.     sum _ Integer new: sl neg: ng.
  28702.     z _ 0.
  28703.     "Loop invariant is -1<=z<=1"
  28704.     1 to: sl do:
  28705.         [:i |
  28706.         z _ z + (larger digitAt: i) - (smaller digitAt: i).
  28707.         sum digitAt: i put: (z bitAnd: 255).
  28708.         z _ z bitShift: -8].
  28709.     ^ sum normalize!
  28710. growby: n
  28711.  
  28712.     ^self growto: self digitLength + n!
  28713. growto: n
  28714.  
  28715.     ^self copyto: (self species new: n)! !
  28716. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  28717.  
  28718. Integer class
  28719.     instanceVariableNames: ''!
  28720.  
  28721. !Integer class methodsFor: 'instance creation'!
  28722. byte1: byte1 byte2: byte2 byte3: byte3 byte4: byte4 
  28723.     "Depending on high-order byte copy directly into a LargeInteger,
  28724.     or build up a SmallInteger by shifting"
  28725.     | value |
  28726.     byte4 < 16r20 ifTrue:
  28727.         [^ (byte4 bitShift: 24)
  28728.          + (byte3 bitShift: 16)
  28729.          + (byte2 bitShift: 8)
  28730.          + byte1].
  28731.     value _ LargePositiveInteger new: 4.
  28732.     value digitAt: 4 put: byte4.
  28733.     value digitAt: 3 put: byte3.
  28734.     value digitAt: 2 put: byte2.
  28735.     value digitAt: 1 put: byte1.
  28736.     ^ value!
  28737. new: length neg: neg
  28738.     "Answer an instance of a large integer whose size is length. neg is a flag 
  28739.     determining whether the integer is negative or not."
  28740.  
  28741.     neg 
  28742.         ifTrue: [^LargeNegativeInteger new: length]
  28743.         ifFalse: [^LargePositiveInteger new: length]!
  28744. readFrom: aStream 
  28745.     "Answer a new Integer as described on the stream, aStream.
  28746.     Embedded radix specifiers not allowed - use Number readFrom: for that."
  28747.     ^self readFrom: aStream base: 10!
  28748. readFrom: aStream base: base 
  28749.     "Answer an instance of one of my concrete subclasses. Initial minus sign 
  28750.     accepted, and bases > 10 use letters A-Z. Embedded radix specifiers not 
  28751.     allowed--use Number readFrom: for that. Answer zero (not an error) if 
  28752.     there are no digits."
  28753.  
  28754.     | digit value neg |
  28755.     neg _ aStream peekFor: $-.
  28756.     value _ 0.
  28757.     [aStream atEnd]
  28758.         whileFalse: 
  28759.             [digit _ aStream next digitValue.
  28760.             (digit < 0 or: [digit >= base])
  28761.                 ifTrue: 
  28762.                     [aStream skip: -1.
  28763.                     neg ifTrue: [^ value negated].
  28764.                     ^ value]
  28765.                 ifFalse: [value _ value * base + digit]].
  28766.     neg ifTrue: [^ value negated].
  28767.     ^ value! !
  28768.  
  28769. !Integer class methodsFor: 'initialization'!
  28770. initialize  "Integer initialize"
  28771.     SinArray _ (0 to: 90) collect: [:x | x asFloat degreesToRadians sin].
  28772.     "Return integral values for 90-degree multiples"
  28773.     SinArray at: 1 put: 0.
  28774.     SinArray at: 91 put: 1! !
  28775.  
  28776. Integer initialize!
  28777. SequenceableCollection subclass: #Interval
  28778.     instanceVariableNames: 'start stop step '
  28779.     classVariableNames: ''
  28780.     poolDictionaries: ''
  28781.     category: 'Collections-Sequenceable'!
  28782. Interval comment:
  28783. 'I represent a finite arithmetic progression.'!
  28784.  
  28785. !Interval methodsFor: 'accessing'!
  28786. at: anInteger 
  28787.     "Answer the anInteger'th element."
  28788.  
  28789.     (anInteger >= 1 and: [anInteger <= self size])
  28790.         ifTrue: [^start + (step * (anInteger - 1))]
  28791.         ifFalse: [self errorSubscriptBounds: anInteger]!
  28792. at: anInteger put: anObject 
  28793.     "Storing into an Interval is not allowed."
  28794.  
  28795.     self error: 'you can not store into an interval'!
  28796. atPin: anInteger 
  28797.     "Answer the anInteger'th element.  Return first or last if out of bounds.  6/18/96 tk"
  28798.  
  28799. anInteger >= 1
  28800.     ifTrue: [anInteger <= self size
  28801.         ifTrue: [^start + (step * (anInteger - 1))]
  28802.         ifFalse: [^ self last]]
  28803.     ifFalse: [^ self first]!
  28804. atWrap: anInteger 
  28805.     "Answer the anInteger'th element.  If index is out of bounds, let it wrap around from the end to the beginning unil it is in bounds.  6/18/96 tk"
  28806.  
  28807. ^ self at: (anInteger - self increment \\ self size + self increment)!
  28808. first 
  28809.     "Refer to the comment in SequenceableCollection|first."
  28810.  
  28811.     ^start!
  28812. increment
  28813.     "Answer the receiver's interval increment."
  28814.  
  28815.     ^step!
  28816. last 
  28817.     "Refer to the comment in SequenceableCollection|last."
  28818.  
  28819.     ^stop - (stop - start \\ step)!
  28820. size
  28821.  
  28822.     step < 0
  28823.         ifTrue: [start < stop
  28824.                 ifTrue: [^0]
  28825.                 ifFalse: [^stop - start // step + 1]]
  28826.         ifFalse: [stop < start
  28827.                 ifTrue: [^0]
  28828.                 ifFalse: [^stop - start // step + 1]]! !
  28829.  
  28830. !Interval methodsFor: 'comparing'!
  28831. = anInterval 
  28832.     "Answer true if my species and anInterval species are equal, and
  28833.     if our starts, steps and sizes are equal."
  28834.  
  28835.     self species == anInterval species
  28836.         ifTrue: [^start = anInterval first
  28837.                     and: [step = anInterval increment and: [self size = anInterval size]]]
  28838.         ifFalse: [^false]!
  28839. hash
  28840.     "Hash is reimplemented because = is implemented."
  28841.  
  28842.     ^(((start hash bitShift: 2)
  28843.         bitOr: stop hash)
  28844.         bitShift: 1)
  28845.         bitOr: self size!
  28846. hashMappedBy: map
  28847.     "My hash is independent of my oop."
  28848.  
  28849.     ^self hash! !
  28850.  
  28851. !Interval methodsFor: 'adding'!
  28852. add: newObject 
  28853.     "Adding to an Interval is not allowed."
  28854.  
  28855.     self shouldNotImplement! !
  28856.  
  28857. !Interval methodsFor: 'removing'!
  28858. remove: newObject 
  28859.     "Removing from an Interval is not allowed."
  28860.  
  28861.     self error: 'elements cannot be removed from an Interval'! !
  28862.  
  28863. !Interval methodsFor: 'copying'!
  28864. copy
  28865.     "Return a copy of me. Override the superclass because my species is
  28866.     Array and copy, as inherited from SequenceableCollection, uses
  28867.     copyFrom:to:, which creates a new object of my species."
  28868.  
  28869.     ^self shallowCopy! !
  28870.  
  28871. !Interval methodsFor: 'enumerating'!
  28872. collect: aBlock
  28873.     | nextValue result |
  28874.     result _ self species new: self size.
  28875.     nextValue _ start.
  28876.     1 to: result size do:
  28877.         [:i |
  28878.         result at: i put: (aBlock value: nextValue).
  28879.         nextValue _ nextValue + step].
  28880.     ^ result!
  28881. do: aBlock
  28882.  
  28883.     | aValue |
  28884.     aValue _ start.
  28885.     step < 0
  28886.         ifTrue: [[stop <= aValue]
  28887.                 whileTrue: 
  28888.                     [aBlock value: aValue.
  28889.                     aValue _ aValue + step]]
  28890.         ifFalse: [[stop >= aValue]
  28891.                 whileTrue: 
  28892.                     [aBlock value: aValue.
  28893.                     aValue _ aValue + step]]!
  28894. reverseDo: aBlock 
  28895.     "Evaluate aBlock for each element of my interval, in reverse order."
  28896.  
  28897.     | aValue |
  28898.     aValue _ stop.
  28899.     step < 0
  28900.         ifTrue: [[start >= aValue]
  28901.                 whileTrue: 
  28902.                     [aBlock value: aValue.
  28903.                     aValue _ aValue - step]]
  28904.         ifFalse: [[start <= aValue]
  28905.                 whileTrue: 
  28906.                     [aBlock value: aValue.
  28907.                     aValue _ aValue - step]]! !
  28908.  
  28909. !Interval methodsFor: 'printing'!
  28910. printOn: aStream
  28911.  
  28912.     aStream nextPut: $(.
  28913.     start printOn: aStream.
  28914.     aStream nextPutAll: ' to: '.
  28915.     stop printOn: aStream.
  28916.     step ~= 1
  28917.         ifTrue: 
  28918.             [aStream nextPutAll: ' by: '.
  28919.             step printOn: aStream].
  28920.     aStream nextPut: $)!
  28921. storeOn: aStream 
  28922.     "This is possible because we know numbers store and print the same."
  28923.  
  28924.     self printOn: aStream! !
  28925.  
  28926. !Interval methodsFor: 'private'!
  28927. setFrom: startInteger to: stopInteger by: stepInteger
  28928.  
  28929.     start _ startInteger.
  28930.     stop _ stopInteger.
  28931.     step _ stepInteger!
  28932. species
  28933.  
  28934.     ^Array! !
  28935. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  28936.  
  28937. Interval class
  28938.     instanceVariableNames: ''!
  28939.  
  28940. !Interval class methodsFor: 'instance creation'!
  28941. from: startInteger to: stopInteger 
  28942.     "Answer an instance of me, starting at startNumber, ending at 
  28943.     stopNumber, and with an interval increment of 1."
  28944.  
  28945.     ^self new
  28946.         setFrom: startInteger
  28947.         to: stopInteger
  28948.         by: 1!
  28949. from: startInteger to: stopInteger by: stepInteger 
  28950.     "Answer an instance of me, starting at startNumber, ending at 
  28951.     stopNumber, and with an interval increment of stepNumber."
  28952.  
  28953.     ^self new
  28954.         setFrom: startInteger
  28955.         to: stopInteger
  28956.         by: stepInteger!
  28957. new
  28958.     "Primitive. Create and answer with a new instance of the receiver
  28959.     (a class) with no indexable fields. Fail if the class is indexable. Override
  28960.     SequenceableCollection new. Essential. See Object documentation
  28961.     whatIsAPrimitive."
  28962.  
  28963.     <primitive: 70>
  28964.     self isVariable ifTrue: [ ^ self new: 0 ].
  28965.     "space must be low"
  28966.     Smalltalk signalLowSpace.
  28967.     ^ self new  "retry if user proceeds"
  28968. !
  28969. newFrom: aCollection 
  28970.     "Answer an instance of me containing the same elements as aCollection."
  28971.  
  28972.     | newInterval |
  28973.     newInterval _ self from: aCollection first to: aCollection last by:
  28974.         (aCollection last - aCollection first)//(aCollection size - 1).
  28975.     aCollection ~= newInterval
  28976.         ifTrue: [self error: 'The argument is not an arithmetic progression'].
  28977.     ^newInterval
  28978.  
  28979. "    Interval newFrom: {1. 2. 3}
  28980.     {33. 5. -23} as: Interval
  28981.     {33. 5. -22} as: Interval    (an error)
  28982.     (-4 to: -12 by: -1) as: Interval
  28983. "! !Array variableSubclass: #IOWeakArray
  28984.     instanceVariableNames: ''
  28985.     classVariableNames: ''
  28986.     poolDictionaries: ''
  28987.     category: 'Object Storage'!
  28988.  
  28989. !IOWeakArray methodsFor: 'as yet unclassified'!
  28990. storeDataOn: aDataStream
  28991.     "Store myself on a DataStream. Answer self. Since I'm an IOWeakArray, use
  28992.      nextPutWeak: to write out my contents.
  28993.      This is a low-level DataStream/ReferenceStream method. See also
  28994.      objectToStoreOnDataStream.
  28995.      NOTE: This method must send 'aDataStream beginInstance:size:'
  28996.         and then put a number of objects (via aDataStream nextPut:/nextPutWeak:).
  28997.      Cf. readDataFrom:size:, which must read back what this puts
  28998.         when given the size that it gave to beginInstance:size:. -- 11/15/92 jhm
  28999.      ISSUE: Should this use nextPut: or nextPutWeak: to write any named instance
  29000.         variables? I don't yet have any, so it's moot for now."
  29001.     | cntInstVars cntIndexedVars |
  29002.  
  29003.     cntInstVars _ self class instSize.
  29004.     cntIndexedVars _ self basicSize.
  29005.     aDataStream
  29006.         beginInstance: self class
  29007.         size: cntInstVars + cntIndexedVars.
  29008.     1 to: cntInstVars do:
  29009.         [:i | aDataStream nextPut: (self instVarAt: i)].
  29010.     1 to: cntIndexedVars do:
  29011.         [:i | aDataStream nextPutWeak: (self basicAt: i)]! !
  29012. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  29013.  
  29014. IOWeakArray class
  29015.     instanceVariableNames: ''!
  29016.  
  29017. !IOWeakArray class methodsFor: 'imported from V'!
  29018. classComment
  29019. "An IOWeakArray is like an Array except that it acts like a weak object (holds weak
  29020. pointers) on a ReferenceStream.
  29021.  
  29022. In an objectToStoreOnDataStream (externalize) method, putting some objects into an
  29023. IOWeakArray is a practical way to write them via ReferenceStream>>nextPutWeak:.
  29024.     -- 11/15/92 jhm
  29025. "! !Object subclass: #KeyboardEvent
  29026.     instanceVariableNames: 'keyCharacter metaState '
  29027.     classVariableNames: ''
  29028.     poolDictionaries: ''
  29029.     category: 'Kernel-Processes'!
  29030. KeyboardEvent comment:
  29031. 'I represent a keyboard event consisting of a non-meta key being struck plus the state of the meta keys at that moment. Only InputState creates instances of me.'!
  29032.  
  29033. !KeyboardEvent methodsFor: 'accessing'!
  29034. keyCharacter
  29035.     "Answer the keyboard character of the receiver."
  29036.  
  29037.     ^keyCharacter!
  29038. metaState
  29039.     "Answer the state of the special keyboard characters: control, shift, lock."
  29040.  
  29041.     ^metaState! !
  29042.  
  29043. !KeyboardEvent methodsFor: 'testing'!
  29044. hasCtrl
  29045.     "Answer whether a control key was pressed."
  29046.  
  29047.     ^metaState anyMask: 2!
  29048. hasLock
  29049.     "Answer whether the shift key is locked."
  29050.  
  29051.     ^metaState anyMask: 4!
  29052. hasShift
  29053.     "Answer whether a shift key was pressed."
  29054.  
  29055.     ^metaState anyMask: 1! !
  29056.  
  29057. !KeyboardEvent methodsFor: 'private'!
  29058. key: anInteger meta: meta
  29059.  
  29060.     keyCharacter _ anInteger asCharacter.
  29061.     metaState _ meta! !
  29062. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  29063.  
  29064. KeyboardEvent class
  29065.     instanceVariableNames: ''!
  29066.  
  29067. !KeyboardEvent class methodsFor: 'instance creation'!
  29068. code: code meta: meta 
  29069.     "Answer an instance of me, with code the regular key and meta the 
  29070.     special keys: control, shift, lock."
  29071.  
  29072.     ^ self new key: code meta: meta! !LargePositiveInteger variableByteSubclass: #LargeNegativeInteger
  29073.     instanceVariableNames: ''
  29074.     classVariableNames: ''
  29075.     poolDictionaries: ''
  29076.     category: 'Numeric-Numbers'!
  29077.  
  29078. !LargeNegativeInteger methodsFor: 'arithmetic'!
  29079. abs
  29080.     ^ self negated!
  29081. negated
  29082.     ^ self copyto: (LargePositiveInteger new: self digitLength)! !
  29083.  
  29084. !LargeNegativeInteger methodsFor: 'converting'!
  29085. normalize
  29086.     "Check for leading zeroes and return shortened copy if so"
  29087.     | sLen val len oldLen minVal |
  29088.     "First establish len = significant length"
  29089.     len _ oldLen _ self digitLength.
  29090.     [len = 0 ifTrue: [^0].
  29091.     (self digitAt: len) = 0]
  29092.         whileTrue: [len _ len - 1].
  29093.  
  29094.     "Now check if in SmallInteger range"
  29095.     sLen _ 4  "SmallInteger minVal digitLength".
  29096.     len <= sLen ifTrue:
  29097.         [minVal _ SmallInteger minVal.
  29098.         (len < sLen
  29099.             or: [(self digitAt: sLen) < minVal lastDigit])
  29100.             ifTrue: ["If high digit less, then can be small"
  29101.                     val _ 0.
  29102.                     len to: 1 by: -1 do:
  29103.                         [:i | val _ (val *256) - (self digitAt: i)].
  29104.                     ^ val].
  29105.         1 to: sLen do:  "If all digits same, then = minVal"
  29106.             [:i | (self digitAt: i) = (minVal digitAt: i)
  29107.                     ifFalse: ["Not so; return self shortened"
  29108.                             len < oldLen
  29109.                                 ifTrue: [^ self growto: len]
  29110.                                 ifFalse: [^ self]]].
  29111.         ^ minVal].
  29112.  
  29113.     "Return self, or a shortened copy"
  29114.     len < oldLen
  29115.         ifTrue: [^ self growto: len]
  29116.         ifFalse: [^ self]! !
  29117.  
  29118. !LargeNegativeInteger methodsFor: 'testing'!
  29119. negative
  29120.     ^ true!
  29121. positive
  29122.     ^ false! !
  29123.  
  29124. !LargeNegativeInteger methodsFor: 'printing'!
  29125. printOn: aStream base: b 
  29126.     "Refer to the comment in Integer|printOn:base:."
  29127.  
  29128.     aStream nextPut: $-.
  29129.     super printOn: aStream base: b! !Integer variableByteSubclass: #LargePositiveInteger
  29130.     instanceVariableNames: ''
  29131.     classVariableNames: ''
  29132.     poolDictionaries: ''
  29133.     category: 'Numeric-Numbers'!
  29134. LargePositiveInteger comment:
  29135. 'I represent a positive large integer, integers greater than 16383.'!
  29136.  
  29137. !LargePositiveInteger methodsFor: 'arithmetic'!
  29138. * anInteger 
  29139.     "Primitive. Multiply the receiver by the argument and answer with an
  29140.     Integer result. Fail if either the argument or the result is not a
  29141.     SmallInteger or a LargePositiveInteger less than 65536. Optional. See
  29142.     Object documentation whatIsAPrimitive. "
  29143.  
  29144.     <primitive: 29>
  29145.     ^super * anInteger!
  29146. + anInteger 
  29147.     "Primitive. Add the receiver to the argument and answer with an
  29148.     Integer result. Fail if either the argument or the result is not a
  29149.     SmallInteger or a LargePositiveInteger less than 65536. Optional. See
  29150.     Object documentation whatIsAPrimitive."
  29151.  
  29152.     <primitive: 21>
  29153.     ^super + anInteger!
  29154. - anInteger 
  29155.     "Primitive. Subtract the argument from the receiver and answer with an
  29156.     Integer result. Fail if either the argument or the result is not a
  29157.     SmallInteger or a LargePositiveInteger less than 65536. Optional. See
  29158.     Object documentation whatIsAPrimitive."
  29159.  
  29160.     <primitive: 22>
  29161.     ^super - anInteger!
  29162. / anInteger 
  29163.     "Primitive. Divide the receiver by the argument and answer with the
  29164.     result if the division is exact. Fail if the result is not a whole integer.
  29165.     Fail if the argument is 0. Fail if either the argument or the result is not
  29166.     a SmallInteger or a LargePositiveInteger less than 65536. Optional. See
  29167.     Object documentation whatIsAPrimitive. "
  29168.  
  29169.     <primitive: 30>
  29170.     ^super / anInteger!
  29171. // anInteger 
  29172.     "Primitive. Divide the receiver by the argument and return the result.
  29173.     Round the result down towards negative infinity to make it a whole
  29174.     integer. Fail if the argument is 0. Fail if either the argument or the
  29175.     result is not a SmallInteger or a LargePositiveInteger less than 65536.
  29176.     Optional. See Object documentation whatIsAPrimitive. "
  29177.  
  29178.     <primitive: 32>
  29179.     ^super // anInteger!
  29180. abs!
  29181. negated 
  29182.     ^ (self copyto: (LargeNegativeInteger new: self digitLength))
  29183.         normalize  "Need to normalize to catch SmallInteger minVal"!
  29184. quo: anInteger 
  29185.     "Primitive. Divide the receiver by the argument and return the result.
  29186.     Round the result down towards zero to make it a whole integer. Fail if
  29187.     the argument is 0. Fail if either the argument or the result is not a
  29188.     SmallInteger or a LargePositiveInteger less than 65536. Optional. See
  29189.     Object documentation whatIsAPrimitive."
  29190.  
  29191.     <primitive: 33>
  29192.     ^super quo: anInteger!
  29193. \\ anInteger 
  29194.     "Primitive. Take the receiver modulo the argument. The result is the
  29195.     remainder rounded towards negative infinity, of the receiver divided
  29196.     by the argument. Fail if the argument is 0. Fail if either the argument
  29197.     or the result is not a SmallInteger or a LargePositiveInteger less than
  29198.     65536. Optional. See Object documentation whatIsAPrimitive."
  29199.  
  29200.     <primitive: 31>
  29201.     ^super \\ anInteger! !
  29202.  
  29203. !LargePositiveInteger methodsFor: 'bit manipulation'!
  29204. bitAnd: anInteger 
  29205.     "Primitive. Answer an Integer whose bits are the logical AND of the
  29206.     receiver's bits and those of the argument. Fail if the receiver or argument
  29207.     is greater than 32 bits. See Object documentation whatIsAPrimitive."
  29208.     <primitive: 14>
  29209.     ^ super bitAnd: anInteger!
  29210. bitOr: anInteger 
  29211.     "Primitive. Answer an Integer whose bits are the logical OR of the
  29212.     receiver's bits and those of the argument. Fail if the receiver or argument
  29213.     is greater than 32 bits. See Object documentation whatIsAPrimitive."
  29214.     <primitive: 15>
  29215.     ^ super bitOr: anInteger!
  29216. bitShift: anInteger 
  29217.     "Primitive. Answer an Integer whose value (in twos-complement 
  29218.     representation) is the receiver's value (in twos-complement
  29219.     representation) shifted left by the number of bits indicated by the
  29220.     argument. Negative arguments shift right. Zeros are shifted in from the
  29221.     right in left shifts. The sign bit is extended in right shifts.
  29222.     Fail if the receiver or result is greater than 32 bits.
  29223.     See Object documentation whatIsAPrimitive."
  29224.     <primitive: 17>
  29225.     ^super bitShift: anInteger!
  29226. bitXor: anInteger 
  29227.     "Primitive. Answer an Integer whose bits are the logical XOR of the
  29228.     receiver's bits and those of the argument. Fail if the receiver or argument
  29229.     is greater than 32 bits. See Object documentation whatIsAPrimitive."
  29230.     <primitive: 16>
  29231.     ^ super bitXor: anInteger! !
  29232.  
  29233. !LargePositiveInteger methodsFor: 'testing'!
  29234. negative
  29235.  
  29236.     ^false!
  29237. positive
  29238.  
  29239.     ^true! !
  29240.  
  29241. !LargePositiveInteger methodsFor: 'comparing'!
  29242. < anInteger 
  29243.     "Primitive. Compare the receiver with the argument and answer true if
  29244.     the receiver is less than the argument. Otherwise answer false. Fail if the
  29245.     argument is not a SmallInteger or a LargePositiveInteger less than 65536.
  29246.     Optional. See Object documentation whatIsAPrimitive."
  29247.  
  29248.     <primitive: 23>
  29249.     ^super < anInteger!
  29250. <= anInteger 
  29251.     "Primitive. Compare the receiver with the argument and answer true if
  29252.     the receiver is less than or equal to the argument. Otherwise answer false.
  29253.     Fail if the argument is not a SmallInteger or a LargePositiveInteger less
  29254.     than 65536. Optional. See Object documentation whatIsAPrimitive."
  29255.  
  29256.     <primitive: 25>
  29257.     ^super <= anInteger!
  29258. = anInteger 
  29259.     "Primitive. Compare the receiver with the argument and answer true if
  29260.     the receiver is equal to the argument. Otherwise answer false. Fail if the
  29261.     receiver or argument is negative or greater than 32 bits.
  29262.     Optional. See Object documentation whatIsAPrimitive."
  29263.  
  29264.     <primitive: 7>
  29265.     ^ super = anInteger!
  29266. > anInteger 
  29267.     "Primitive. Compare the receiver with the argument and answer true if
  29268.     the receiver is greater than the argument. Otherwise answer false. Fail if
  29269.     the argument is not a SmallInteger or a LargePositiveInteger less than
  29270.     65536. Optional. See Object documentation whatIsAPrimitive."
  29271.  
  29272.     <primitive: 24>
  29273.     ^super > anInteger!
  29274. >= anInteger 
  29275.     "Primitive. Compare the receiver with the argument and answer true if
  29276.     the receiver is greater than or equal to the argument. Otherwise answer
  29277.     false. Fail if the argument is not a SmallInteger or a LargePositiveInteger
  29278.     less than 65536. Optional. See Object documentation whatIsAPrimitive."
  29279.  
  29280.     <primitive: 26>
  29281.     ^super >= anInteger!
  29282. ~= anInteger 
  29283.     "Primitive. Compare the receiver with the argument and answer true if
  29284.     the receiver is equal to the argument. Otherwise answer false. Fail if the
  29285.     receiver or argument is negative or greater than 32 bits.
  29286.     Optional. See Object documentation whatIsAPrimitive."
  29287.  
  29288.     <primitive: 8>
  29289.     ^ super ~= anInteger! !
  29290.  
  29291. !LargePositiveInteger methodsFor: 'converting'!
  29292. normalize
  29293.     "Check for leading zeroes and return shortened copy if so"
  29294.     | sLen val len oldLen |
  29295.     "First establish len = significant length"
  29296.     len _ oldLen _ self digitLength.
  29297.     [len = 0 ifTrue: [^0].
  29298.     (self digitAt: len) = 0]
  29299.         whileTrue: [len _ len - 1].
  29300.  
  29301.     "Now check if in SmallInteger range"
  29302.     sLen _ SmallInteger maxVal digitLength.
  29303.     (len <= sLen
  29304.         and: [(self digitAt: sLen) <= (SmallInteger maxVal digitAt: sLen)])
  29305.         ifTrue: ["If so, return its SmallInt value"
  29306.                 val _ 0.
  29307.                 len to: 1 by: -1 do:
  29308.                     [:i | val _ (val *256) + (self digitAt: i)].
  29309.                 ^ val].
  29310.  
  29311.     "Return self, or a shortened copy"
  29312.     len < oldLen
  29313.         ifTrue: [^ self growto: len]
  29314.         ifFalse: [^ self]! !
  29315.  
  29316. !LargePositiveInteger methodsFor: 'system primitives'!
  29317. digitAt: index 
  29318.     "Primitive. Answer the value of an indexable field in the receiver. Fail if 
  29319.     the argument (the index) is not an Integer or is out of bounds. Essential. 
  29320.     See Object documentation whatIsAPrimitive."
  29321.  
  29322.     <primitive: 60>
  29323.     self digitLength < index
  29324.         ifTrue: [^0]
  29325.         ifFalse: [^super at: index]!
  29326. digitAt: index put: value 
  29327.     "Primitive. Store the second argument (value) in the indexable field of 
  29328.     the receiver indicated by index. Fail if the value is negative or is larger 
  29329.     than 255. Fail if the index is not an Integer or is out of bounds. Answer 
  29330.     the value that was stored. Essential. See Object documentation 
  29331.     whatIsAPrimitive."
  29332.  
  29333.     <primitive: 61>
  29334.     ^super at: index put: value!
  29335. digitLength
  29336.     "Primitive. Answer the number of indexable fields in the receiver. This 
  29337.     value is the same as the largest legal subscript. Essential. See Object 
  29338.     documentation whatIsAPrimitive."
  29339.  
  29340.     <primitive: 62>
  29341.     self primitiveFailed!
  29342. replaceFrom: start to: stop with: replacement startingAt: repStart 
  29343.     "Primitive. This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the collection, replacement. Answer the receiver. Range checks are performed in the primitive only. Optional. See Object documentation whatIsAPrimitive."
  29344.     <primitive: 105>
  29345.     ^ super replaceFrom: start to: stop with: replacement startingAt: repStart! !
  29346. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  29347.  
  29348. LargePositiveInteger class
  29349.     instanceVariableNames: ''!
  29350. LargePositiveInteger class comment:
  29351. 'My instances represent integers beyond the range of SmallInteger, encoded as an array of 8-bit digits.  Care must be taken, when new results are computed, that any value that COULD BE a SmallInteger IS a SmallInteger (see normalize).  Several algorithms here were written for a SmallInteger range of 15 bits or less, and should be updated to take advantage of the current 31-bit range.'!
  29352.  
  29353. !LargePositiveInteger class methodsFor: 'testing'!
  29354. test: n  "Time millisecondsToRun: [LargePositiveInteger test: 100] 1916"
  29355.     | f f1 |
  29356.     "Test and time mult, div, add, subtract"
  29357.     f _ n factorial.
  29358.     f1 _ f*(n+1).
  29359.     n timesRepeat: [f1 _ f1 - f].
  29360.     f1 = f ifFalse: [self halt].
  29361.     n timesRepeat: [f1 _ f1 + f].
  29362.     f1 // f = (n+1) ifFalse: [self halt].
  29363.     f1 negated = (Number readFrom: '-' , f1 printString) ifFalse: [self halt].
  29364.  
  29365.     "Check normalization and conversion to/from SmallInts"
  29366.     (SmallInteger maxVal + 1 - 1) == SmallInteger maxVal ifFalse: [self halt].
  29367.     (SmallInteger maxVal + 3 - 6) == (SmallInteger maxVal-3) ifFalse: [self halt].
  29368.     (SmallInteger minVal - 1 + 1) == SmallInteger minVal ifFalse: [self halt].
  29369.     (SmallInteger minVal - 3 + 6) == (SmallInteger minVal+3) ifFalse: [self halt].
  29370.  
  29371.     "Check bitShift from and back to SmallInts"
  29372.     1 to: 257 do: [:i | ((i bitShift: i) bitShift: 0-i) == i ifFalse: [self halt]].
  29373. ! !ParseNode subclass: #LeafNode
  29374.     instanceVariableNames: 'key code '
  29375.     classVariableNames: ''
  29376.     poolDictionaries: ''
  29377.     category: 'System-Compiler'!
  29378. LeafNode comment:
  29379. 'I represent a leaf node of the compiler parse tree. I am abstract.
  29380.     
  29381. Types (defined in class ParseNode):
  29382.     1 LdInstType (which uses class VariableNode)
  29383.     2 LdTempType (which uses class VariableNode)
  29384.     3 LdLitType (which uses class LiteralNode)
  29385.     4 LdLitIndType (which uses class VariableNode)
  29386.     5 SendType (which uses class SelectorNode)'!
  29387.  
  29388. !LeafNode methodsFor: 'initialize-release'!
  29389. key: object code: byte
  29390.  
  29391.     key _ object.
  29392.     code _ byte!
  29393. key: object index: i type: type
  29394.  
  29395.     self key: object code: (self code: i type: type)!
  29396. name: ignored key: object code: byte
  29397.  
  29398.     key _ object.
  29399.     code _ byte!
  29400. name: literal key: object index: i type: type
  29401.  
  29402.     self key: object
  29403.         index: i
  29404.         type: type! !
  29405.  
  29406. !LeafNode methodsFor: 'accessing'!
  29407. key
  29408.  
  29409.     ^key! !
  29410.  
  29411. !LeafNode methodsFor: 'code generation'!
  29412. code
  29413.  
  29414.     ^code!
  29415. emitForEffect: stack on: strm
  29416.  
  29417.     ^self!
  29418. emitLong: mode on: aStream 
  29419.     "Emit extended variable access."
  29420.     | type index |
  29421.     code < 256
  29422.         ifTrue: [code < 16
  29423.                 ifTrue: 
  29424.                     [type _ 0.
  29425.                     index _ code]
  29426.                 ifFalse: 
  29427.                     [code < 32
  29428.                         ifTrue: 
  29429.                             [type _ 1.
  29430.                             index _ code - 16]
  29431.                         ifFalse: 
  29432.                             [code < 96
  29433.                                 ifTrue: 
  29434.                                     [type _ code // 32 + 1.
  29435.                                     index _ code \\ 32]
  29436.                                 ifFalse: [self error: 
  29437.                                         'Sends should be handled in SelectorNode']]]]
  29438.         ifFalse: 
  29439.             [index _ code \\ 256.
  29440.             type _ code // 256 - 1].
  29441.     aStream nextPut: mode.
  29442.     aStream nextPut: type * 64 + index!
  29443. reserve: encoder 
  29444.     "If this is a yet unused literal of type -code, reserve it."
  29445.  
  29446.     code < 0 ifTrue: [code _ self code: (encoder litIndex: key) type: 0 - code]!
  29447. sizeForEffect: encoder
  29448.  
  29449.     ^0!
  29450. sizeForValue: encoder
  29451.  
  29452.     self reserve: encoder.
  29453.     code < 256 
  29454.         ifTrue: [^1].
  29455.     ^2! !
  29456.  
  29457. !LeafNode methodsFor: 'private'!
  29458. code: index type: type
  29459.  
  29460.     index isNil 
  29461.         ifTrue: [^type negated].
  29462.     (CodeLimits at: type) > index 
  29463.         ifTrue: [^(CodeBases at: type) + index].
  29464.     ^type * 256 + index! !Path subclass: #Line
  29465.     instanceVariableNames: ''
  29466.     classVariableNames: ''
  29467.     poolDictionaries: ''
  29468.     category: 'Graphics-Paths'!
  29469. Line comment:
  29470. 'I represent the line segment specified by two points.'!
  29471.  
  29472. !Line methodsFor: 'accessing'!
  29473. beginPoint
  29474.     "Answer the first end point of the receiver."
  29475.  
  29476.     ^self first!
  29477. beginPoint: aPoint 
  29478.     "Set the first end point of the receiver to be the argument, aPoint. 
  29479.     Answer aPoint."
  29480.  
  29481.     self at: 1 put: aPoint.
  29482.     ^aPoint!
  29483. endPoint
  29484.     "Answer the last end point of the receiver."
  29485.  
  29486.     ^self last!
  29487. endPoint: aPoint 
  29488.     "Set the first end point of the receiver to be the argument, aPoint. 
  29489.     Answer aPoint."
  29490.  
  29491.     self at: 2 put: aPoint.
  29492.     ^aPoint! !
  29493.  
  29494. !Line methodsFor: 'displaying'!
  29495. displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm 
  29496.     "The form associated with this Path will be displayed, according  
  29497.     to one of the sixteen functions of two logical variables (rule), at  
  29498.     each point on the Line. Also the source form will be first anded  
  29499.     with aForm as a mask. Does not effect the state of the Path."
  29500.  
  29501.     collectionOfPoints size < 2 ifTrue: [self error: 'a line must have two points'].
  29502.     aDisplayMedium
  29503.         drawLine: self form
  29504.         from: self beginPoint + aPoint
  29505.         to: self endPoint + aPoint
  29506.         clippingBox: clipRect
  29507.         rule: anInteger
  29508.         fillColor: aForm!
  29509. displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
  29510.  
  29511.     | newPath newLine |
  29512.     newPath _ aTransformation applyTo: self.
  29513.     newLine _ Line new.
  29514.     newLine beginPoint: newPath firstPoint.
  29515.     newLine endPoint: newPath secondPoint.
  29516.     newLine form: self form.
  29517.     newLine
  29518.         displayOn: aDisplayMedium
  29519.         at: 0 @ 0
  29520.         clippingBox: clipRect
  29521.         rule: anInteger
  29522.         fillColor: aForm!
  29523. displayOnPort: aPort at: aPoint 
  29524.     aPort sourceForm: self form; combinationRule: Form under; fillColor: nil.
  29525.     aPort drawFrom: collectionOfPoints first + aPoint
  29526.         to: collectionOfPoints last + aPoint! !
  29527. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  29528.  
  29529. Line class
  29530.     instanceVariableNames: ''!
  29531.  
  29532. !Line class methodsFor: 'instance creation'!
  29533. from: beginPoint to: endPoint withForm: aForm 
  29534.     "Answer an instance of me with end points begingPoint and endPoint; 
  29535.     the source form for displaying the line is aForm."
  29536.  
  29537.     | newSelf | 
  29538.     newSelf _ super new: 2.
  29539.     newSelf add: beginPoint.
  29540.     newSelf add: endPoint.
  29541.     newSelf form: aForm.
  29542.     ^newSelf!
  29543. new
  29544.  
  29545.     | newSelf | 
  29546.     newSelf _ super new: 2.
  29547.     newSelf add: 0@0.
  29548.     newSelf add: 0@0.
  29549.     ^newSelf! !
  29550.  
  29551. !Line class methodsFor: 'examples'!
  29552. example
  29553.     "Designate two places on the screen by clicking any mouse button. A
  29554.     straight path with a square black form will be displayed connecting the
  29555.     two selected points."
  29556.  
  29557.     | aLine aForm |  
  29558.     aForm _ Form extent: 20@20.        "make a form one quarter of inch square"
  29559.     aForm fillBlack.                            "turn it black"
  29560.     aLine _ Line new.
  29561.     aLine form: aForm.                        "use the black form for display"
  29562.     aLine beginPoint: Sensor waitButton. Sensor waitNoButton.
  29563.     aForm displayOn: Display at: aLine beginPoint.    
  29564.     aLine endPoint: Sensor waitButton.
  29565.     aLine displayOn: Display.                "display the line"
  29566.  
  29567.     "Line example"! !Path subclass: #LinearFit
  29568.     instanceVariableNames: ''
  29569.     classVariableNames: ''
  29570.     poolDictionaries: ''
  29571.     category: 'Graphics-Paths'!
  29572. LinearFit comment:
  29573. 'I represent a piece-wise linear approximation to a set of points in the plane.'!
  29574.  
  29575. !LinearFit methodsFor: 'displaying'!
  29576. displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
  29577.  
  29578.     | pt line |
  29579.     line _ Line new.
  29580.     line form: self form.
  29581.     1 to: self size - 1 do: 
  29582.         [:i | 
  29583.         line beginPoint: (self at: i).
  29584.         line endPoint: (self at: i + 1).
  29585.         line displayOn: aDisplayMedium
  29586.             at: aPoint
  29587.             clippingBox: clipRect
  29588.             rule: anInteger
  29589.             fillColor: aForm]!
  29590. displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm 
  29591.  
  29592.     | newLinearFit transformedPath |
  29593.     "get the scaled and translated Path."
  29594.     transformedPath _ aTransformation applyTo: self.
  29595.     newLinearFit _ LinearFit new.
  29596.     transformedPath do: [:point | newLinearFit add: point].
  29597.     newLinearFit form: self form.
  29598.     newLinearFit
  29599.         displayOn: aDisplayMedium
  29600.         at: 0 @ 0
  29601.         clippingBox: clipRect
  29602.         rule: anInteger
  29603.         fillColor: aForm! !
  29604. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  29605.  
  29606. LinearFit class
  29607.     instanceVariableNames: ''!
  29608.  
  29609. !LinearFit class methodsFor: 'examples'!
  29610. example
  29611.     "Select points on a Path using the red button. Terminate by selecting
  29612.     any other button. Creates a Path from the points and displays it as a
  29613.     piece-wise linear approximation." 
  29614.  
  29615.     | aLinearFit aForm flag |
  29616.     aLinearFit _ LinearFit new.
  29617.     aForm _ Form extent: 1 @ 40.
  29618.     aForm  fillBlack.
  29619.     aLinearFit form: aForm.
  29620.     flag _ true.
  29621.     [flag] whileTrue:
  29622.         [Sensor waitButton.
  29623.          Sensor redButtonPressed
  29624.             ifTrue: [aLinearFit add: Sensor waitButton. Sensor waitNoButton.
  29625.                     aForm displayOn: Display at: aLinearFit last]
  29626.             ifFalse: [flag_false]].
  29627.     aLinearFit displayOn: Display
  29628.  
  29629.     "LinearFit example"! !Object subclass: #Link
  29630.     instanceVariableNames: 'nextLink '
  29631.     classVariableNames: ''
  29632.     poolDictionaries: ''
  29633.     category: 'Collections-Support'!
  29634. Link comment:
  29635. 'An instance of me is a simple record of a pointer to another Link. I am an abstract class; my concrete subclasses, for example, Process, can be stored in a LinkedList structure.'!
  29636.  
  29637. !Link methodsFor: 'accessing'!
  29638. nextLink
  29639.     "Answer the link to which the receiver points."
  29640.  
  29641.     ^nextLink!
  29642. nextLink: aLink 
  29643.     "Store the argument, aLink, as the link to which the receiver refers. 
  29644.     Answer aLink."
  29645.  
  29646.     ^nextLink _ aLink! !
  29647. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  29648.  
  29649. Link class
  29650.     instanceVariableNames: ''!
  29651.  
  29652. !Link class methodsFor: 'instance creation'!
  29653. nextLink: aLink 
  29654.     "Answer an instance of me referring to the argument, aLink."
  29655.  
  29656.     ^self new nextLink: aLink! !SequenceableCollection subclass: #LinkedList
  29657.     instanceVariableNames: 'firstLink lastLink '
  29658.     classVariableNames: ''
  29659.     poolDictionaries: ''
  29660.     category: 'Collections-Sequenceable'!
  29661. LinkedList comment:
  29662. 'I represent a collection of links, which are containers for other objects. Using the message sequence addFirst:/removeLast causes the receiver to behave as a stack; using addLast:/removeFirst causes the receiver to behave as a queue.'!
  29663.  
  29664. !LinkedList methodsFor: 'accessing'!
  29665. first
  29666.     "Answer the first link. Create an error notification if the receiver is 
  29667.     empty."
  29668.  
  29669.     self emptyCheck.
  29670.     ^firstLink!
  29671. last
  29672.     "Answer the last link. Create an error notification if the receiver is 
  29673.     empty."
  29674.  
  29675.     self emptyCheck.
  29676.     ^lastLink!
  29677. size
  29678.     "Answer how many elements the receiver contains."
  29679.  
  29680.     | tally |
  29681.     tally _ 0.
  29682.     self do: [:each | tally _ tally + 1].
  29683.     ^tally! !
  29684.  
  29685. !LinkedList methodsFor: 'testing'!
  29686. isEmpty
  29687.  
  29688.     ^firstLink == nil! !
  29689.  
  29690. !LinkedList methodsFor: 'adding'!
  29691. add: aLink 
  29692.     "Add aLink to the end of the receiver's list. Answer aLink."
  29693.  
  29694.     ^self addLast: aLink!
  29695. addFirst: aLink 
  29696.     "Add aLink to the beginning of the receiver's list. Answer aLink."
  29697.  
  29698.     self isEmpty ifTrue: [lastLink _ aLink].
  29699.     aLink nextLink: firstLink.
  29700.     firstLink _ aLink.
  29701.     ^aLink!
  29702. addLast: aLink 
  29703.     "Add aLink to the end of the receiver's list. Answer aLink."
  29704.  
  29705.     self isEmpty
  29706.         ifTrue: [firstLink _ aLink]
  29707.         ifFalse: [lastLink nextLink: aLink].
  29708.     lastLink _ aLink.
  29709.     ^aLink! !
  29710.  
  29711. !LinkedList methodsFor: 'removing'!
  29712. remove: aLink ifAbsent: aBlock  
  29713.     "Remove aLink from the receiver. If it is not there, answer the result of
  29714.     evaluating aBlock."
  29715.  
  29716.     | tempLink |
  29717.     aLink == firstLink
  29718.         ifTrue: [firstLink _ aLink nextLink.
  29719.                 aLink == lastLink
  29720.                     ifTrue: [lastLink _ nil]]
  29721.         ifFalse: [tempLink _ firstLink.
  29722.                 [tempLink == nil ifTrue: [^aBlock value].
  29723.                  tempLink nextLink == aLink]
  29724.                     whileFalse: [tempLink _ tempLink nextLink].
  29725.                 tempLink nextLink: aLink nextLink.
  29726.                 aLink == lastLink
  29727.                     ifTrue: [lastLink _ tempLink]].
  29728.     aLink nextLink: nil.
  29729.     ^aLink!
  29730. removeFirst
  29731.     "Remove the first element and answer it. If the receiver is empty, create 
  29732.     an error notification."
  29733.  
  29734.     | oldLink |
  29735.     self emptyCheck.
  29736.     oldLink _ firstLink.
  29737.     firstLink == lastLink
  29738.         ifTrue: [firstLink _ nil. lastLink _ nil]
  29739.         ifFalse: [firstLink _ oldLink nextLink].
  29740.     oldLink nextLink: nil.
  29741.     ^oldLink!
  29742. removeLast
  29743.     "Remove the receiver's last element and answer it. If the receiver is 
  29744.     empty, create an error notification."
  29745.  
  29746.     | oldLink aLink |
  29747.     self emptyCheck.
  29748.     oldLink _ lastLink.
  29749.     firstLink == lastLink
  29750.         ifTrue: [firstLink _ nil. lastLink _ nil]
  29751.         ifFalse: [aLink _ firstLink.
  29752.                 [aLink nextLink == oldLink] whileFalse:
  29753.                     [aLink _ aLink nextLink].
  29754.                  aLink nextLink: nil.
  29755.                  lastLink _ aLink].
  29756.     oldLink nextLink: nil.
  29757.     ^oldLink! !
  29758.  
  29759. !LinkedList methodsFor: 'enumerating'!
  29760. do: aBlock
  29761.  
  29762.     | aLink |
  29763.     aLink _ firstLink.
  29764.     [aLink == nil] whileFalse:
  29765.         [aBlock value: aLink.
  29766.          aLink _ aLink nextLink]! !ScrollController subclass: #ListController
  29767.     instanceVariableNames: ''
  29768.     classVariableNames: ''
  29769.     poolDictionaries: ''
  29770.     category: 'Interface-Support'!
  29771. ListController comment:
  29772. 'I am a kind of ScrollController that assumes that the view is a kind of ListView. Therefore, scrolling means moving the items in a textual list (menu) up or down. In addition, I provide the red button activity of determining when the red button is selecting an item in the list.'!
  29773.  
  29774. !ListController methodsFor: 'control defaults'!
  29775. isControlActive
  29776.  
  29777.     ^super isControlActive & sensor blueButtonPressed not! !
  29778.  
  29779. !ListController methodsFor: 'marker adjustment'!
  29780. computeMarkerRegion 
  29781.     "Refer to the comment in ScrollController|computeMarkerRegion."
  29782.  
  29783.     | viewList |
  29784.     viewList _ view list.
  29785.     viewList compositionRectangle height = 0
  29786.         ifTrue: [^ 0@0 extent: 10@scrollBar inside height].
  29787.     ^ 0@0 extent: 10@
  29788.             ((viewList clippingRectangle height asFloat /
  29789.                         viewList compositionRectangle height *
  29790.                             scrollBar inside height)
  29791.                     rounded min: scrollBar inside height)!
  29792. markerDelta
  29793.  
  29794.     | viewList |
  29795.     viewList _ view list.
  29796.     viewList compositionRectangle height == 0 ifTrue: [
  29797.         ^ (marker top - scrollBar inside top) - scrollBar inside height
  29798.     ].
  29799.     ^ (marker top - scrollBar inside top) -
  29800.         ((viewList clippingRectangle top -
  29801.                 viewList compositionRectangle top) asFloat /
  29802.             viewList compositionRectangle height asFloat *
  29803.             scrollBar inside height asFloat) rounded
  29804. !
  29805. mmarkerDelta
  29806.  
  29807.     | viewList |
  29808.     viewList _ view list.
  29809.     viewList compositionRectangle height == 0 ifTrue: [
  29810.         ^ (marker top - self mscrollGrayRect top) - (self mscrollGrayRect height - marker height)
  29811.     ].
  29812.     ^ (marker top - self mscrollGrayRect top) -
  29813.         ((viewList clippingRectangle top -
  29814.                 viewList compositionRectangle top) asFloat /
  29815.             (viewList compositionRectangle height - viewList clippingRectangle height) asFloat *
  29816.             (self mscrollGrayRect height - marker height) asFloat) rounded
  29817. ! !
  29818.  
  29819. !ListController methodsFor: 'scrolling'!
  29820. scrollAmount 
  29821.     "Refer to the comment in ScrollController|scrollAmount."
  29822.  
  29823.     ^sensor cursorPoint y - scrollBar inside top!
  29824. scrollView: anInteger 
  29825.     "Scroll the view and highlight the selection if it just came into view"
  29826.     | wasClipped |
  29827.     wasClipped _ view isSelectionBoxClipped.
  29828.     (view scrollBy: anInteger)
  29829.         ifTrue: [view isSelectionBoxClipped ifFalse:
  29830.                     [wasClipped ifTrue:  "Selection came into view"
  29831.                         [view displaySelectionBox]].
  29832.                 ^ true]
  29833.         ifFalse: [^ false]!
  29834. viewDelta 
  29835.     "Refer to the comment in ScrollController|viewDelta."
  29836.  
  29837.     | viewList |
  29838.     viewList _ view list.
  29839.     ^(viewList clippingRectangle top -
  29840.             viewList compositionRectangle top -
  29841.             ((marker top - scrollBar inside top) asFloat /
  29842.                 scrollBar inside height asFloat *
  29843.                 viewList compositionRectangle height asFloat))
  29844.         roundTo: viewList lineGrid! !
  29845.  
  29846. !ListController methodsFor: 'selecting'!
  29847. redButtonActivity
  29848.     | noSelectionMovement oldSelection selection nextSelection pt scrollFlag |
  29849.     noSelectionMovement _ true.
  29850.     scrollFlag _ false.
  29851.     oldSelection _ view selection.
  29852.     [sensor redButtonPressed]
  29853.         whileTrue: 
  29854.             [selection _ view findSelection: (pt _ sensor cursorPoint).
  29855.             selection == nil ifTrue:  "Maybe out of box - check for auto-scroll"
  29856.                     [pt y < view insetDisplayBox top ifTrue:
  29857.                         [self scrollView: view list lineGrid.
  29858.                         scrollFlag _ true.
  29859.                         selection _ view firstShown].
  29860.                     pt y > view insetDisplayBox bottom ifTrue:
  29861.                         [self scrollView: view list lineGrid negated.
  29862.                         scrollFlag _ true.
  29863.                         selection _ view lastShown]].
  29864.             selection == nil ifFalse:
  29865.                     [view moveSelectionBox: (nextSelection _ selection).
  29866.                     nextSelection ~= oldSelection
  29867.                         ifTrue: [noSelectionMovement _ false]]].
  29868.     nextSelection ~~ nil & (nextSelection = oldSelection
  29869.             ifTrue: [noSelectionMovement]
  29870.             ifFalse: [true]) ifTrue: [self changeModelSelection: nextSelection].
  29871.     scrollFlag ifTrue: [self moveMarker]! !
  29872.  
  29873. !ListController methodsFor: 'private'!
  29874. changeModelSelection: anInteger
  29875.     model toggleListIndex: anInteger! !ListController subclass: #ListControllerOfMany
  29876.     instanceVariableNames: ''
  29877.     classVariableNames: ''
  29878.     poolDictionaries: ''
  29879.     category: 'Interface-Support'!
  29880. ListControllerOfMany comment:
  29881. 'This class supports the control of lists with multiple selections'!
  29882.  
  29883. !ListControllerOfMany methodsFor: 'selecting'!
  29884. redButtonActivity
  29885.     | selection firstHit turningOn lastSelection pt scrollFlag |
  29886.     firstHit _ true.
  29887.     scrollFlag _ false.
  29888.     lastSelection _ 0.
  29889.     [sensor redButtonPressed] whileTrue: 
  29890.         [selection _ view findSelection: (pt _ sensor cursorPoint).
  29891.         selection == nil ifTrue:  "Maybe out of box - check for auto-scroll"
  29892.             [pt y < view insetDisplayBox top ifTrue:
  29893.                 [self scrollView: view list lineGrid.
  29894.                 scrollFlag _ true.
  29895.                 selection _ view firstShown].
  29896.             pt y > view insetDisplayBox bottom ifTrue:
  29897.                 [self scrollView: view list lineGrid negated.
  29898.                 scrollFlag _ true.
  29899.                 selection _ view lastShown]].
  29900.         (selection == nil or: [selection = lastSelection]) ifFalse: 
  29901.             [firstHit ifTrue:
  29902.                 [firstHit _ false.
  29903.                 turningOn _ (model listSelectionAt: selection) not].
  29904.             view selection: selection.
  29905.             (model listSelectionAt: selection) == turningOn ifFalse:
  29906.                 [view displaySelectionBox.
  29907.                 model listSelectionAt: selection put: turningOn].
  29908.             lastSelection _ selection]].
  29909.     selection notNil ifTrue:
  29910.         ["Normal protocol delivers change, so unchange first (ugh)"
  29911.         model listSelectionAt: selection put: (model listSelectionAt: selection) not.
  29912.         self changeModelSelection: selection].
  29913.     scrollFlag ifTrue: [self moveMarker]! !
  29914.  
  29915. !ListControllerOfMany methodsFor: 'scrolling'!
  29916. scrollView: anInteger 
  29917.     "Need to minimize the selections which get recomputed"
  29918.     | oldLimit |
  29919.     oldLimit _ anInteger > 0
  29920.         ifTrue: [view firstShown]
  29921.         ifFalse: [view lastShown].
  29922.     (view scrollBy: anInteger)
  29923.         ifTrue: [anInteger > 0  "Highlight selections brought into view"
  29924.                     ifTrue: [view highlightFrom: view firstShown
  29925.                                 to: (oldLimit-1 min: view lastShown)]
  29926.                     ifFalse: [view highlightFrom: (oldLimit+1 max: view firstShown)
  29927.                                 to: view lastShown].
  29928.                 ^ true]
  29929.         ifFalse: [^ false]! !Paragraph subclass: #ListParagraph
  29930.     instanceVariableNames: ''
  29931.     classVariableNames: ''
  29932.     poolDictionaries: ''
  29933.     category: 'Graphics-Display Objects'!
  29934. ListParagraph comment:
  29935. 'I represent a special type of Paragraph that is used in the list panes of a browser.  I  avoid all the composition done by more general Paragraphs, because I know the structure of my Text.'!
  29936.  
  29937. !ListParagraph methodsFor: 'composition'!
  29938. composeAll
  29939.     "No composition is necessary once the ListParagraph is created."
  29940.     
  29941.     lastLine isNil ifTrue: [lastLine _ 0].    
  29942.         "Because composeAll is called once in the process of creating the ListParagraph."
  29943.     ^compositionRectangle width! !
  29944.  
  29945. !ListParagraph methodsFor: 'private'!
  29946. trimLinesTo: lastLineInteger
  29947.     "Since ListParagraphs are not designed to be changed, we can cut back the
  29948.         lines field to lastLineInteger."
  29949.     lastLine _ lastLineInteger.
  29950.     lines _ lines copyFrom: 1 to: lastLine!
  29951. withArray: anArray 
  29952.     "Modifies self to contain the list of strings in anArray"
  29953.     | startOfLine endOfLine lineIndex aString item interval |
  29954.     lines _ Array new: 20.
  29955.     lastLine _ 0.
  29956.     startOfLine _ 1.
  29957.     endOfLine _ 1.
  29958.     lineIndex _ 0.
  29959.     anArray do: 
  29960.         [:item | 
  29961.         endOfLine _ startOfLine + item size.        "this computation allows for a cr after each line..."
  29962.                                                 "...but later we will adjust for no cr after last line"
  29963.         lineIndex _ lineIndex + 1.
  29964.         self lineAt: lineIndex put: (TextLineInterval
  29965.                 start: startOfLine
  29966.                 stop: endOfLine
  29967.                 internalSpaces: 0
  29968.                 paddingWidth: 0).
  29969.         startOfLine _ endOfLine + 1].
  29970.     endOfLine _ endOfLine - 1.        "endOfLine is now the total size of the text"
  29971.     self trimLinesTo: lineIndex.
  29972.     aString _ String new: endOfLine.
  29973.     anArray with: lines do: 
  29974.         [:item :interval | 
  29975.         aString
  29976.             replaceFrom: interval first
  29977.             to: interval last - 1
  29978.             with: item
  29979.             startingAt: 1.
  29980.         interval last <= endOfLine ifTrue: [aString at: interval last put: Character cr]].
  29981.     lineIndex > 0 ifTrue: [(lines at: lineIndex) stop: endOfLine].    "adjust for no cr after last line"
  29982.     self text: aString asText.
  29983.     self updateCompositionHeight! !
  29984. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  29985.  
  29986. ListParagraph class
  29987.     instanceVariableNames: ''!
  29988.  
  29989. !ListParagraph class methodsFor: 'instance creation'!
  29990. withArray: anArray
  29991.     "Convert an array of strings into a ListParagraph."
  29992.  
  29993.     ^super new withArray: anArray!
  29994. withArray: anArray lineSpacing: spacing
  29995.     "Convert an array of strings into a ListParagraph."
  29996.     ^ (super new gridWithLead: spacing) withArray: anArray! !View subclass: #ListView
  29997.     instanceVariableNames: 'list selection topDelimiter bottomDelimiter lineSpacing isEmpty '
  29998.     classVariableNames: ''
  29999.     poolDictionaries: ''
  30000.     category: 'Interface-Support'!
  30001. ListView comment:
  30002. 'I am an abstract View of a list of items. I provide support for storing a selection of one item, as well as formatting the list for presentation on the screen. My instances'' default controller is ListController.'!
  30003.  
  30004. !ListView methodsFor: 'initialize-release'!
  30005. initialize 
  30006.     "Refer to the comment in View|initialize."
  30007.  
  30008.     super initialize.
  30009.     topDelimiter _ '------------'.
  30010.     bottomDelimiter _ '------------'.
  30011.     lineSpacing _ 0.
  30012.     isEmpty _ true.
  30013.     self list: Array new! !
  30014.  
  30015. !ListView methodsFor: 'list access'!
  30016. list
  30017.     "Answer the list of items the receiver displays."
  30018.  
  30019.     ^list!
  30020. list: anArray 
  30021.     "Set the list of items the receiver displays to be anArray."
  30022.  
  30023.     | arrayCopy i |
  30024.     isEmpty _ anArray isEmpty.
  30025.     arrayCopy _ Array new: (anArray size + 2).
  30026.     arrayCopy at: 1 put: topDelimiter.
  30027.     arrayCopy at: arrayCopy size put: bottomDelimiter.
  30028.     i _ 2.
  30029.     anArray do: [:el | arrayCopy at: i put: el. i _ i+1].
  30030.     "arrayCopy _ Array with: topDelimiter with: bottomDelimiter.
  30031.     arrayCopy _ arrayCopy copyReplaceFrom: 2 to: 1 with: anArray."
  30032.     arrayCopy _ arrayCopy copyWithout: nil.
  30033.     list _ ListParagraph withArray: arrayCopy lineSpacing: lineSpacing.
  30034.     selection _ 0.
  30035.     self positionList!
  30036. reset
  30037.     "Set the list of items displayed to be empty."
  30038.  
  30039.     isEmpty _ true.
  30040.     self list: Array new!
  30041. resetAndDisplayView
  30042.     "Set the list of items displayed to be empty and redisplay the receiver."
  30043.  
  30044.     isEmpty
  30045.         ifFalse: 
  30046.             [self reset.
  30047.             self displayView]!
  30048. selection: selIndex
  30049.     selection _ selIndex! !
  30050.  
  30051. !ListView methodsFor: 'delimiters'!
  30052. bottomDelimiter
  30053.     "Answer the string used to indicate the bottom of the list."
  30054.  
  30055.     ^bottomDelimiter!
  30056. bottomDelimiter: aString 
  30057.     "Set the string used to indicate the bottom of the list."
  30058.  
  30059.     bottomDelimiter _ aString!
  30060. noBottomDelimiter
  30061.     "Set the string used to indicate the bottom of the list to be nothing."
  30062.  
  30063.     bottomDelimiter _ nil!
  30064. noTopDelimiter
  30065.     "Set the string used to indicate the top of the list to be nothing."
  30066.  
  30067.     topDelimiter _ nil!
  30068. topDelimiter
  30069.     "Answer the string used to indicate the top of the list."
  30070.  
  30071.     ^topDelimiter!
  30072. topDelimiter: aString 
  30073.     "Set the string used to indicate the top of the list."
  30074.  
  30075.     topDelimiter _ aString! !
  30076.  
  30077. !ListView methodsFor: 'line spacing'!
  30078. lineSpacing
  30079.     "Answer the integer representing the amount of extra space between line 
  30080.     items."
  30081.  
  30082.     ^lineSpacing!
  30083. lineSpacing: anInteger 
  30084.     "Set anInteger to be the amount of extra space between line items."
  30085.  
  30086.     lineSpacing _ anInteger! !
  30087.  
  30088. !ListView methodsFor: 'displaying'!
  30089. deEmphasizeSelectionBox
  30090.     self displaySelectionBox!
  30091. display 
  30092.     "Refer to the comment in View.display."
  30093.     (self isUnlocked and: [self clippingBox ~= list clippingRectangle])
  30094.         ifTrue:  "Recompose the list if the window changed"
  30095.             [selection isNil ifTrue: [selection _ 0].
  30096.             self positionList].
  30097.     super display!
  30098. displaySelectionBox
  30099.     "If the receiver has a selection and that selection is visible on the display 
  30100.     screen, then highlight it."
  30101.     selection ~= 0 ifTrue:
  30102.         [Display reverse: (self selectionBox intersect: self clippingBox)]!
  30103. displayView 
  30104.     "Refer to the comment in View|displayView."
  30105.  
  30106.     self clearInside.
  30107.     list foregroundColor: self foregroundColor
  30108.         backgroundColor: self backgroundColor.
  30109.     list displayOn: Display!
  30110. scrollBy: anInteger 
  30111.     "Scroll up by this amount adjusted by lineSpacing and list limits"
  30112.     | maximumAmount minimumAmount amount wasClipped |
  30113.     maximumAmount _ 0 max:
  30114.         list clippingRectangle top - list compositionRectangle top.
  30115.     minimumAmount _ 0 min:
  30116.         list clippingRectangle bottom - list compositionRectangle bottom.
  30117.     amount _ (anInteger min: maximumAmount) max: minimumAmount.
  30118.     amount ~= 0
  30119.         ifTrue: [list scrollBy: amount negated.  ^ true]
  30120.         ifFalse: [^ false]  "Return false if no scrolling took place"!
  30121. scrollSelectionIntoView
  30122.     "Selection is assumed to be on and clipped out of view.
  30123.     Uses controller scrollView to keep selection right"
  30124.     | delta |
  30125.     (delta _ self insetDisplayBox bottom - self selectionBox bottom) < 0
  30126.         ifTrue: [^ controller scrollView: delta - (list lineGrid-1)]. "up"
  30127.     (delta _ self insetDisplayBox top - self selectionBox top) > 0
  30128.         ifTrue: [^ controller scrollView: delta + 1] "down"! !
  30129.  
  30130. !ListView methodsFor: 'deEmphasizing'!
  30131. deEmphasizeView 
  30132.     "Refer to the comment in View|deEmphasizeView."
  30133.     ^ self deEmphasizeSelectionBox!
  30134. emphasizeView 
  30135.     "List emphasis is its own inverse."
  30136.     ^ self deEmphasizeView! !
  30137.  
  30138. !ListView methodsFor: 'controller access'!
  30139. defaultControllerClass 
  30140.     "Refer to the comment in View|defaultControllerClass."
  30141.  
  30142.     ^ListController! !
  30143.  
  30144. !ListView methodsFor: 'display box access'!
  30145. boundingBox 
  30146.     "Refer to the comment in View|boundingBox."
  30147.  
  30148.     ^list boundingBox! !
  30149.  
  30150. !ListView methodsFor: 'clipping box access'!
  30151. clippingBox
  30152.     "Answer the rectangle in which the model can be displayed--this is the 
  30153.     insetDisplayBox inset by the height of a line for an item."
  30154.  
  30155.     ^self insetDisplayBox insetBy: 
  30156.         (Rectangle
  30157.             left: 0
  30158.             right: 0
  30159.             top: 0
  30160.             bottom: self insetDisplayBox height \\ list lineGrid)! !
  30161.  
  30162. !ListView methodsFor: 'selecting'!
  30163. deselect
  30164.     "If the receiver has a selection, then it is highlighted. Remove the 
  30165.     highlighting."
  30166.  
  30167.     selection ~= 0 ifTrue: [Display reverse: (self selectionBox intersect: self clippingBox)]!
  30168. findSelection: aPoint 
  30169.     "Determine which selection is displayed in an area containing the point, 
  30170.     aPoint. Answer the selection if one contains the point, answer nil 
  30171.     otherwise."
  30172.  
  30173.     | trialSelection |
  30174.     (self clippingBox containsPoint: aPoint) ifFalse: [^nil].
  30175.     trialSelection _ aPoint y - list compositionRectangle top // list lineGrid + 1.
  30176.     topDelimiter == nil ifFalse: [trialSelection _ trialSelection - 1].
  30177.     (trialSelection < 1) | (trialSelection > self maximumSelection)
  30178.         ifTrue: [^ nil]
  30179.         ifFalse: [^ trialSelection]!
  30180. isSelectionBoxClipped
  30181.     "Answer whether there is a selection and whether the selection is visible 
  30182.     on the screen."
  30183.  
  30184.     ^selection ~= 0 & (self selectionBox intersects: self clippingBox) not!
  30185. maximumSelection
  30186.     "Answer which selection is the last possible one."
  30187.     ^ list numberOfLines
  30188.         - (topDelimiter == nil ifTrue: [0] ifFalse: [1])
  30189.         - (bottomDelimiter == nil ifTrue: [0] ifFalse: [1])!
  30190. minimumSelection
  30191.     "Answer which selection is the first possible one."
  30192.     ^ 1!
  30193. moveSelectionBox: anInteger 
  30194.     "Presumably the selection has changed to be anInteger. Deselect the 
  30195.     previous selection and display the new one, highlighted."
  30196.  
  30197.     selection ~= anInteger
  30198.         ifTrue: 
  30199.             [self deselect.
  30200.             selection _ anInteger.
  30201.             self displaySelectionBox].
  30202.     self isSelectionBoxClipped
  30203.         ifTrue: [self scrollSelectionIntoView]!
  30204. selection
  30205.     "Answer the receiver's current selection."
  30206.  
  30207.     ^selection!
  30208. selectionBox
  30209.     "Answer the rectangle in which the current selection is displayed."
  30210.  
  30211.     ^(self insetDisplayBox left @ (list compositionRectangle top + self selectionBoxOffset) 
  30212.         extent: self insetDisplayBox width @ list lineGrid)
  30213.         insetBy: (Rectangle left: 1 right: 1 top: 1 bottom: 0)!
  30214. selectionBoxOffset
  30215.     "Answer an integer that determines the y position for the display box of 
  30216.     the current selection."
  30217.  
  30218.     ^ (selection - 1 + (topDelimiter == nil ifTrue: [0] ifFalse: [1]))
  30219.         * list lineGrid! !
  30220.  
  30221. !ListView methodsFor: 'updating'!
  30222. update: aSymbol 
  30223.     "Refer to the comment in View|update:."
  30224.  
  30225.     aSymbol == #list
  30226.         ifTrue: 
  30227.             [self list: model list.
  30228.             self displayView.
  30229.             ^self].
  30230.     aSymbol == #listIndex
  30231.         ifTrue: 
  30232.             [self moveSelectionBox: model listIndex.
  30233.             ^self]! !
  30234.  
  30235. !ListView methodsFor: 'private'!
  30236. firstShown
  30237.     "Return the index of the top item currently visible"
  30238.     | trial |
  30239.     trial _ self findSelection: self insetDisplayBox topLeft.
  30240.     ^ trial == nil
  30241.         ifTrue: [1]
  30242.         ifFalse: [trial]!
  30243. lastShown
  30244.     "Return the index of the bottom item currently visible"
  30245.     | trial bottomMargin |
  30246.     bottomMargin _ self insetDisplayBox height \\ list lineGrid.
  30247.     trial _ self findSelection: self insetDisplayBox bottomLeft - (0@bottomMargin).
  30248.     trial == nil
  30249.         ifTrue: [trial _ self findSelection: self insetDisplayBox bottomLeft
  30250.                     - (0@(list lineGrid+bottomMargin))].
  30251.     ^ trial == nil
  30252.         ifTrue: [list numberOfLines - 2]
  30253.         ifFalse: [trial]!
  30254. positionList
  30255.  
  30256.     list wrappingBox: self wrappingBox clippingBox: self clippingBox !
  30257. wrappingBox
  30258.  
  30259.     | aRectangle |
  30260.     aRectangle _ self insetDisplayBox. 
  30261.     selection = 0
  30262.         ifTrue: [^aRectangle topLeft + (4 @ 0) extent: list compositionRectangle extent]
  30263.         ifFalse: [^aRectangle left + 4 @ 
  30264.                     (aRectangle top - 
  30265.                         (self selectionBoxOffset 
  30266.                             min: ((list height - aRectangle height 
  30267.                                     + list lineGrid truncateTo: list lineGrid)
  30268.                             max: 0))) 
  30269.                     extent: list compositionRectangle extent]! !
  30270.  
  30271. !ListView methodsFor: 'lock access'!
  30272. lock
  30273.     "Refer to the comment in view|lock.  Must do at least what display would do to lock the view."
  30274.  
  30275.     (self isUnlocked and: [self clippingBox ~= list clippingRectangle])
  30276.         ifTrue:  "Recompose the list if the window changed"
  30277.             [self positionList].
  30278.     super lock! !ListView subclass: #ListViewOfMany
  30279.     instanceVariableNames: 'selections '
  30280.     classVariableNames: ''
  30281.     poolDictionaries: ''
  30282.     category: 'Interface-Support'!
  30283. ListViewOfMany comment:
  30284. 'Just like ListView, except that multiple entries can be selected.
  30285. The model is required to support the messages selecitonAt: and
  30286. selectionAt:put: to communicate which items are selected.
  30287. The normal listIndex logic is ignored for the most part, except in 
  30288. the use of some routines inherited from ListView.'!
  30289.  
  30290. !ListViewOfMany methodsFor: 'displaying'!
  30291. deEmphasizeView 
  30292.     "Refer to the comment in View|deEmphasizeView."
  30293.     selection _ 0.
  30294.     1 to: self maximumSelection do:
  30295.         [:i | selection _ i.
  30296.         (model listSelectionAt: i) ifTrue: [self deEmphasizeSelectionBox]].
  30297.     selection _ 0!
  30298. highlightFrom: start to: stop
  30299.     (start == nil or: [stop == nil]) ifTrue: [^ self displayView].
  30300.     start to: stop do:
  30301.         [:i | selection _ i.
  30302.         (model listSelectionAt: selection) ifTrue: [self displaySelectionBox]].
  30303.     selection _ 0! !
  30304.  
  30305. !ListViewOfMany methodsFor: 'selecting'!
  30306. moveSelectionBox: anInteger 
  30307.     "Presumably the selection has changed to be anInteger. Deselect the 
  30308.     previous selection and display the new one, highlighted."
  30309.     selection ~= anInteger
  30310.         ifTrue: 
  30311.             [selection _ anInteger.
  30312.             self displaySelectionBox]!
  30313. selection
  30314.     "Have to override normal controller smarts about deselection"
  30315.     ^ 0! !
  30316.  
  30317. !ListViewOfMany methodsFor: 'updating'!
  30318. update: aSymbol 
  30319.     aSymbol == #allSelections
  30320.         ifTrue: [^ self displayView; emphasizeView].
  30321.     ^ super update: aSymbol! !Dictionary subclass: #LiteralDictionary
  30322.     instanceVariableNames: ''
  30323.     classVariableNames: ''
  30324.     poolDictionaries: ''
  30325.     category: 'System-Compiler'!
  30326. LiteralDictionary comment:
  30327. 'A LiteralDictionary, like an IdentityDictionary, has a special test for equality.  In this case it is simple equality between objects of like class.  This allows equal Float or String literals to be shared without the possibility of erroneously sharing, say, 1 and 1.0'!
  30328.  
  30329. !LiteralDictionary methodsFor: 'as yet unclassified'!
  30330. scanFor: key from: start to: finish
  30331.     "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches the key. Answer the index of that slot or zero if no slot is found within the given range of indices."
  30332.  
  30333.     | element |
  30334.     "this speeds up a common case: key is in the first slot"
  30335.     ((element _ array at: start) == nil or:
  30336.      [(element key class == key class) and:
  30337.      [element key = key]])
  30338.         ifTrue: [ ^ start ].
  30339.  
  30340.     start + 1 to: finish do: [ :index |
  30341.         ((element _ array at: index) == nil or:
  30342.          [(element key class == key class) and:
  30343.          [element key = key]])
  30344.             ifTrue: [ ^ index ].
  30345.     ].
  30346.     ^ 0
  30347. ! !LeafNode subclass: #LiteralNode
  30348.     instanceVariableNames: ''
  30349.     classVariableNames: ''
  30350.     poolDictionaries: ''
  30351.     category: 'System-Compiler'!
  30352. LiteralNode comment:
  30353. 'I am a parse tree leaf representing a literal string or number.'!
  30354.  
  30355. !LiteralNode methodsFor: 'code generation'!
  30356. emitForValue: stack on: strm
  30357.  
  30358.     code < 256
  30359.         ifTrue: [strm nextPut: code]
  30360.         ifFalse: [self emitLong: LdInstLong on: strm].
  30361.     stack push: 1! !
  30362.  
  30363. !LiteralNode methodsFor: 'testing'!
  30364. isConstantNumber
  30365.     ^ key isNumber!
  30366. isSpecialConstant
  30367.     ^ code between: LdTrue and: LdMinus1+3!
  30368. literalValue
  30369.  
  30370.     ^key! !
  30371.  
  30372. !LiteralNode methodsFor: 'printing'!
  30373. printOn: aStream indent: level
  30374.  
  30375.     (key isMemberOf: Association)
  30376.         ifTrue:
  30377.             [key key isNil
  30378.                 ifTrue:
  30379.                     [aStream nextPutAll: '###';
  30380.                          nextPutAll: key value soleInstance name]
  30381.                 ifFalse:
  30382.                     [aStream nextPutAll: '##';
  30383.                         nextPutAll: key key]]
  30384.         ifFalse: [key storeOn: aStream]! !
  30385.  
  30386. !LiteralNode methodsFor: 'equation translation'!
  30387. collectVariables
  30388.     ^#()!
  30389. copyReplacingVariables: varDict 
  30390.     ^self copy!
  30391. specificMatch: aTree using: matchDict 
  30392.     ^key = aTree key! !
  30393.  
  30394. !LiteralNode methodsFor: 'C translation'! !SwitchController subclass: #LockedSwitchController
  30395.     instanceVariableNames: ''
  30396.     classVariableNames: ''
  30397.     poolDictionaries: ''
  30398.     category: 'Interface-Menus'!
  30399. LockedSwitchController comment:
  30400. 'I am a SwitchController that will not take control if the model is locked. Rather the view is "flashed" (complemented twice in succession).'!
  30401.  
  30402. !LockedSwitchController methodsFor: 'control defaults'!
  30403. isControlWanted
  30404.     sensor flushKeyboard.
  30405.     self viewHasCursor ifFalse: [^ false].
  30406.     sensor redButtonPressed ifFalse: [^ false].
  30407.     ^ model okToChange  "Dont change selection if model is locked"! !Magnitude subclass: #LookupKey
  30408.     instanceVariableNames: 'key '
  30409.     classVariableNames: ''
  30410.     poolDictionaries: ''
  30411.     category: 'Collections-Support'!
  30412. LookupKey comment:
  30413. 'I represent a key for looking up entries in a data structure. Subclasses of me, such as Association, typically represent dictionary entries.'!
  30414.  
  30415. !LookupKey methodsFor: 'accessing'!
  30416. key
  30417.     "Answer the lookup key of the receiver."
  30418.  
  30419.     ^key!
  30420. key: anObject 
  30421.     "Store the argument, anObject, as the lookup key of the receiver."
  30422.  
  30423.     key _ anObject! !
  30424.  
  30425. !LookupKey methodsFor: 'comparing'!
  30426. < aLookupKey 
  30427.     "Refer to the comment in Magnitude|<."
  30428.  
  30429.     ^key < aLookupKey key!
  30430. = aLookupKey
  30431.  
  30432.     self species = aLookupKey species
  30433.         ifTrue: [^key = aLookupKey key]
  30434.         ifFalse: [^false]!
  30435. hash
  30436.     "Hash is reimplemented because = is implemented."
  30437.  
  30438.     ^key hash!
  30439. hashMappedBy: map
  30440.     "Answer what my hash would be if oops changed according to map."
  30441.  
  30442.     ^key hashMappedBy: map! !
  30443.  
  30444. !LookupKey methodsFor: 'printing'!
  30445. printOn: aStream
  30446.  
  30447.     key printOn: aStream! !
  30448. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  30449.  
  30450. LookupKey class
  30451.     instanceVariableNames: ''!
  30452.  
  30453. !LookupKey class methodsFor: 'instance creation'!
  30454. key: aKey 
  30455.     "Answer an instance of me with the argument as the lookup up."
  30456.  
  30457.     ^self new key: aKey! !FileDirectory subclass: #MacFileDirectory
  30458.     instanceVariableNames: ''
  30459.     classVariableNames: ''
  30460.     poolDictionaries: ''
  30461.     category: 'System-Files'!
  30462. MacFileDirectory comment:
  30463. 'Represents a minimal, flat directory, for use with the simplest implementation of files.  2/5/96 sw'!
  30464.  
  30465. !MacFileDirectory methodsFor: 'file creation'!
  30466. fileClass
  30467.     ^ StandardFileStream! !
  30468. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  30469.  
  30470. MacFileDirectory class
  30471.     instanceVariableNames: ''!
  30472.  
  30473. !MacFileDirectory class methodsFor: 'initialization'!
  30474. pathNameDelimiter
  30475.     ^ $:!
  30476. setMacFileNamed: fileName type: typeString creator: creatorString
  30477.     "Set the Macintosh file type and creator info for the file with the given name. Fails if the file does not exist or if the type and creator type arguments are not strings of length 4."
  30478.     "Mac specific; noop on other platforms."
  30479.  
  30480.      <primitive: 169>
  30481.     self primitiveFailed.! !Object subclass: #Magnitude
  30482.     instanceVariableNames: ''
  30483.     classVariableNames: ''
  30484.     poolDictionaries: ''
  30485.     category: 'Numeric-Magnitudes'!
  30486. Magnitude comment:
  30487. 'I am an abstract representation of objects that measure something linear. Examples are dates, times, and numbers.'!
  30488.  
  30489. !Magnitude methodsFor: 'comparing'!
  30490. < aMagnitude 
  30491.     "Answer whether the receiver is less than the argument."
  30492.  
  30493.     ^self subclassResponsibility!
  30494. <= aMagnitude 
  30495.     "Answer whether the receiver is less than or equal to the argument."
  30496.  
  30497.     ^(self > aMagnitude) not!
  30498. = aMagnitude 
  30499.     "Compare the receiver with the argument and answer with true if the 
  30500.     receiver is equal to the argument. Otherwise answer false."
  30501.  
  30502.     ^self subclassResponsibility!
  30503. > aMagnitude 
  30504.     "Answer whether the receiver is greater than the argument."
  30505.  
  30506.     ^aMagnitude < self!
  30507. >= aMagnitude 
  30508.     "Answer whether the receiver is greater than or equal to the argument."
  30509.  
  30510.     ^(self < aMagnitude) not!
  30511. between: min and: max 
  30512.     "Answer whether the receiver is less than or equal to the argument, max, 
  30513.     and greater than or equal to the argument, min."
  30514.  
  30515.     ^self >= min and: [self <= max]!
  30516. hash
  30517.     "Hash must be redefined whenever = is redefined."
  30518.  
  30519.     ^self subclassResponsibility!
  30520. hashMappedBy: map
  30521.     "My hash is independent of my oop."
  30522.  
  30523.     ^self hash! !
  30524.  
  30525. !Magnitude methodsFor: 'testing'!
  30526. max: aMagnitude 
  30527.     "Answer the receiver or the argument, whichever has the greater 
  30528.     magnitude."
  30529.  
  30530.     self > aMagnitude
  30531.         ifTrue: [^self]
  30532.         ifFalse: [^aMagnitude]!
  30533. min: aMagnitude 
  30534.     "Answer the receiver or the argument, whichever has the lesser 
  30535.     magnitude."
  30536.  
  30537.     self < aMagnitude
  30538.         ifTrue: [^self]
  30539.         ifFalse: [^aMagnitude]!
  30540. min: aMin max: aMax 
  30541.  
  30542.     ^ (self min: aMin) max: aMax! !Collection subclass: #MappedCollection
  30543.     instanceVariableNames: 'domain map '
  30544.     classVariableNames: ''
  30545.     poolDictionaries: ''
  30546.     category: 'Collections-Sequenceable'!
  30547. MappedCollection comment:
  30548. 'I represent an access mechanism for a sequencable collection re-ordering or filtering its elements.'!
  30549.  
  30550. !MappedCollection methodsFor: 'accessing'!
  30551. at: anIndex
  30552.  
  30553.     ^domain at: (map at: anIndex)!
  30554. at: anIndex put: anObject
  30555.  
  30556.     ^domain at: (map at: anIndex) put: anObject!
  30557. atPin: anIndex 
  30558.     "Return this element of an indexable object.  Return the first or last element if index is out of bounds.  6/18/96 tk"
  30559.  
  30560.     ^domain at: (map atPin: anIndex)!
  30561. atWrap: anIndex 
  30562.     "Return this element of an indexable object.  If index is out of bounds, let it wrap around from the end to the beginning unil it is in bounds.  6/18/96 tk"
  30563.  
  30564.     ^domain at: (map atWrap: anIndex)!
  30565. contents
  30566.     "Answer the receiver's domain for mapping, a Dictionary or 
  30567.     SequenceableCollection."
  30568.  
  30569.     ^map collect: [:mappedIndex | domain at: mappedIndex]!
  30570. size
  30571.  
  30572.     ^map size! !
  30573.  
  30574. !MappedCollection methodsFor: 'adding'!
  30575. add: newObject
  30576.  
  30577.     self shouldNotImplement! !
  30578.  
  30579. !MappedCollection methodsFor: 'copying'!
  30580. copy
  30581.     "This returns another MappedCollection whereas copyFrom:to: will return
  30582.     an object like my domain."
  30583.  
  30584.     ^MappedCollection collection: domain map: map! !
  30585.  
  30586. !MappedCollection methodsFor: 'enumerating'!
  30587. collect: aBlock 
  30588.     "Refer to the comment in Collection|collect:."
  30589.  
  30590.     | aStream |
  30591.     aStream _ WriteStream on: (self species new: self size).
  30592.     self do:
  30593.         [:domainValue | 
  30594.         aStream nextPut: (aBlock value: domainValue)].
  30595.     ^aStream contents!
  30596. do: aBlock 
  30597.     "Refer to the comment in Collection|do:."
  30598.  
  30599.     map do:
  30600.         [:mapValue | aBlock value: (domain at: mapValue)]!
  30601. select: aBlock 
  30602.     "Refer to the comment in Collection|select:."
  30603.  
  30604.     | aStream |
  30605.     aStream _ WriteStream on: (self species new: self size).
  30606.     self do:
  30607.         [:domainValue | 
  30608.         (aBlock value: domainValue)
  30609.             ifTrue: [aStream nextPut: domainValue]].
  30610.     ^aStream contents! !
  30611.  
  30612. !MappedCollection methodsFor: 'printing'!
  30613. storeOn: aStream
  30614.  
  30615.     aStream nextPut: $(.
  30616.     domain storeOn: aStream.
  30617.     aStream nextPutAll: ' mappedBy: '.
  30618.     map storeOn: aStream.
  30619.     aStream nextPut: $)! !
  30620.  
  30621. !MappedCollection methodsFor: 'private'!
  30622. setCollection: aCollection map: aDictionary
  30623.  
  30624.     domain _ aCollection.
  30625.     map _ aDictionary!
  30626. species
  30627.  
  30628.     ^domain species! !
  30629. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  30630.  
  30631. MappedCollection class
  30632.     instanceVariableNames: ''!
  30633.  
  30634. !MappedCollection class methodsFor: 'instance creation'!
  30635. collection: aCollection map: aSequenceableCollection 
  30636.     "Answer an instance of me that maps aCollection by 
  30637.     aSequenceableCollection."
  30638.  
  30639.     ^self basicNew setCollection: aCollection map: aSequenceableCollection!
  30640. new
  30641.  
  30642.     self error: 'MappedCollections must be created using the collection:map: message'!
  30643. newFrom: aCollection 
  30644.     "Answer an instance of me containing the same elements as aCollection."
  30645.  
  30646.     ^ self collection: aCollection map: (1 to: aCollection size)
  30647.  
  30648. "    MappedCollection newFrom: {1. 2. 3}
  30649.     {4. 3. 8} as: MappedCollection
  30650. "! !DisplayObject subclass: #MaskedForm
  30651.     instanceVariableNames: 'theForm mask transparentPixelValue colorMap rawColorMap '
  30652.     classVariableNames: ''
  30653.     poolDictionaries: ''
  30654.     category: 'Graphics-Display Objects'!
  30655. MaskedForm comment:
  30656. 'A transparent Form.  It consists of theForm and a one-bit-deep mask.  When a MaskedForm is displayed, theForm is transparent where the mask is white, and opaque where the mask is black.  
  30657.     The user may specify a mask explicitly.  Or the user may submit only theForm and a color that stands for transparent.  Thus a MaskedForm can do blue-screening (also called chroma-keying).
  30658.     When a user submits theForm with a mask, she must say what happens to the colored bits in the transparent area.  They can be removed or not.  If the user does not remove the overlap, the bits will be combined using OR with the background, producing strange colors.
  30659.     Think of theForm as unchanged, but we have to change it behind the user''s back for speed.  When the users asks for it, we change it back.
  30660.  
  30661. <<ColorMap support in next version.  Problem: colorMap belongs to sourceForm, but is used by BitBlt.  Messages are sent to destForm or to Bitblt, so sourceForm never gets to install the colorMap.>> 
  30662.     In addition to MaskedForm''s normal use, the user may submit a colorMap.  (Normally one does not need to do this.)  If you have an 8-bit deep Form that was created with colors other than the standard 256 colors we supply, the user can submit a 256 long Array of Colors.  MaskedForm will choose the closest 256 colors it can and display the form using those.  transparentPixelValue and transparentColor are in terms of the original unmapped Form.  The original Form is transformed by the map at each display.  Using a map preserves the colors in case you later want to display the Form at a different depth.
  30663.  
  30664. Instance variables:
  30665.     theForm        Internal rep of the Form to be displayed.  This may different from the Form submitted, but the original Form is recomputed upon request by using ''form''.
  30666.     mask            A one-bit form. white=transparent, black=opaque.
  30667.     transparentPixelValue    The bit value in the original Form that should be treated as transparent. 
  30668.     colorMap        An array of Colors.  Size = 2^(maskedForm depth).  Stored as a copy, so it can''t change without our knowing about it.  If you want to change an entry in the colorMap, make the change in your own array and then call colorMap:  again. 
  30669.     rawColorMap    A cached internal rep to be sent to BitBlt.
  30670.  
  30671. Messages:
  30672.     colorAt: x@y put: aColor  Write a Color into a pixel.  (Checks if writing over transparent and changes the mask.)
  30673.     pixelValueAt: x@y put: i     Write a raw pixelValue into a pixel.
  30674.     transparentColor: aColor       Change the transparent color.  Alters the mask as needed. 
  30675.     transparentPixelValue: i        Specify the transparent color by its internal bit pattern.
  30676.     form    Returns the original form.  It is in terms of the colorMap, if one was specified.  Transparent pixels once again have the chosen transparent color in them.
  30677.     colorMap:    Install a new color map (normally not needed).  A colorMap is an array of Colors.  It is depth independent, except that its length should be at least 2^N where N is the pixel depth of the Form.  (We try to get away with colorMap being an Array instead of an instance of a separate class.)  The map is copied from the one you submit.  If you change an entry, you must submit the map again using colorMap:.
  30678.  
  30679. Class messages: 
  30680.     form: f mask: m removeOverlap: true        create a MaskedForm.  Remove the colored pixels in this form from its transparent area.
  30681.     form: f transparentColor: aColor        create a MaskedForm
  30682.     transparentBorder: aForm        Answer an instance of me that looks like aForm, but is transparent in regions near the edge.
  30683.     transparentFromUser: f         Displays the Form and asks the user to click on the color that should be transparent.
  30684. '!
  30685.  
  30686. !MaskedForm methodsFor: 'access'!
  30687. basicForm
  30688.     "Return the form part of me, regardless of how the transparent color has been replaced with 0.  9/6/96 tk"
  30689.     ^ theForm!
  30690. borderWidth: anInteger
  30691.  
  30692.     theForm borderWidth: anInteger.
  30693.     mask borderWidth: anInteger!
  30694. colorMap
  30695.     "Map the pixelValues in theForm to the colors is this array.  6/28/96 tk"
  30696.  
  30697.     ^ colorMap!
  30698. colorMap: anArray
  30699.     "Map the pixelValues in theForm through the colors is this array.  Array should be 2^(theForm depth) long.  If shorter, will be padded.  If longer, truncated.  Map is cached in rawColorMap.  6/28/96 tk"
  30700.  
  30701.     | d mapSize |
  30702.     anArray == nil ifTrue: ["clear it"
  30703.         colorMap _ nil.
  30704.         rawColorMap _ nil].    "uncache"
  30705.     d _ theForm depth.
  30706.     colorMap _ anArray.
  30707.     mapSize _ (1 bitShift: d) min: (512 max: anArray size).
  30708.         "Want 2^^depth, except where huge, except if big map supplied"
  30709.     rawColorMap _ Bitmap new: mapSize.
  30710.     colorMap doWithIndex: [:color :ind |
  30711.         rawColorMap at: ind put: (color pixelWordForDepth: d)].
  30712.         "Note that we don't supply default colors in the added part of the map.  We assume no pixel values are used outside the supplied map." !
  30713. depth
  30714.     ^ theForm depth!
  30715. form
  30716.     ^ self theForm!
  30717. mask
  30718.     ^mask!
  30719. offset
  30720.     ^ theForm offset!
  30721. offset: aPoint 
  30722.     "Refer to the comment in DisplayObject.offset."
  30723.  
  30724.     theForm offset: aPoint.
  30725.     mask offset: aPoint!
  30726. rawColorMap
  30727.     "Map the pixelValues in theForm to the colors is this array.  This is what BitBlt wants and is computed for theForm's depth.  6/28/96 tk"
  30728.  
  30729.     ^ rawColorMap!
  30730. theForm
  30731.     "Return the original Form.  Restore it's transparent color if it was zeroed to make the area truly transparent.  6/22/96 tk"
  30732.  
  30733.     | copy |
  30734.     transparentPixelValue == nil ifTrue: [^ theForm].
  30735.     copy _ self deepCopy.    "Use one in Object"
  30736.     copy restoreOverlap.
  30737.     ^ copy theForm        "won't recurse because transparentPixelValue is now nil"!
  30738. theFormReally
  30739.     ^ theForm!
  30740. transparentColor
  30741.     "Return the color that is being used as transparent.  Not all pixels with this color are transparent if there is more than one internal pixelValue for this color.  6/21/96 tk"
  30742.  
  30743.     transparentPixelValue == nil ifTrue: [^ nil].
  30744.     ^ Color colorFromPixelValue: transparentPixelValue depth: theForm depth!
  30745. transparentColor: aColor
  30746.     "Change the transparent color.  Alters the mask as needed.  Checks to see if more than one code used in theForm has this color.  If so, asks the user to click on the color that should be transparent.
  30747.      1. recompute original form
  30748.     2. change transp color
  30749.     3. compute new theForm and mask
  30750. 6/21/96 tk"
  30751.  
  30752.     self restoreOverlap.    "recompute the original colors in theForm"
  30753.     self setForm: theForm transparentColor: aColor
  30754.  
  30755.  
  30756. !
  30757. transparentPixelValue
  30758.     "The internal pixel value (for this depth) that is being used to stand for transparent.  6/21/96 tk"
  30759.  
  30760.     ^ transparentPixelValue
  30761.  
  30762. !
  30763. transparentPixelValue: pixVal
  30764.     "Specify the transparent color by its internal raw bit pattern.  Changes the transparent color.  Alters the mask as needed.
  30765.      1. recompute original form
  30766.     2. change transp color
  30767.     3. compute new theForm and mask
  30768. 6/21/96 tk"
  30769.  
  30770.     self restoreOverlap.    "recompute the original colors in theForm"
  30771.     self setForm: theForm transparentPixelValue: pixVal
  30772.     
  30773.  
  30774.  
  30775. !
  30776. withTransparentPixelValue: pixVal
  30777.     "Just note this special pixelValue"
  30778.     transparentPixelValue _ pixVal
  30779.     
  30780.  
  30781.  
  30782. ! !
  30783.  
  30784. !MaskedForm methodsFor: 'editing'!
  30785. bitEdit
  30786.     "Create and schedule a view located in an area designated by the user that contains a view of the receiver magnified by 8@8 that can be modified using the Bit Editor. It also contains a view of the original form."
  30787.  
  30788.     BitEditor openOnForm: self
  30789.  
  30790.     "MaskedForm makeStar bitEdit."! !
  30791.  
  30792. !MaskedForm methodsFor: 'pattern'!
  30793. applyColorMap
  30794.     "Convert theForm to the best approximation of the colors in colorMap.  Then make the map be nil.  Informaion will be lost.  Converts the arbitrary 256 colors in the picture (via the map) to the standard 256 colors.  When colorMaps are fully supported, stop using this.  7/1/96 tk"
  30795.  
  30796.     | port |
  30797.     port _ BitBlt toForm: theForm.
  30798.     port colorMap: self rawColorMap.
  30799.     theForm displayOnPort: port at: 0@0.
  30800.         "Write over self using the transforming color map"
  30801.     colorMap _ nil.!
  30802. colorAt: aPoint 
  30803.     "Answer the color at the receiver's position aPoint.  If transparent there, return the color being used for transparent.  (Watch out for two colors with the same value). 6/20/96 tk"
  30804.  
  30805.     | pix |
  30806.     pix _ theForm pixelValueAt: aPoint.
  30807.     (mask pixelValueAt: aPoint) = 0 ifTrue: ["transparent"
  30808.             pix _ (pix = 0) & (transparentPixelValue ~~ nil)
  30809.                 ifTrue: [transparentPixelValue]
  30810.                 ifFalse: [pix]].
  30811.     ^ Color colorFromPixelValue: pix depth: theForm depth!
  30812. colorAt: aPoint put: aColor
  30813.     "Store the color at the receiver's position aPoint.  Assumed to be opaque (so correct color will show) unless it is the value used for transparent. 6/22/96 tk"
  30814.  
  30815.     ^ self pixelValueAt: aPoint 
  30816.         put: (aColor pixelValueForDepth: theForm depth)
  30817. !
  30818. pixelValueAt: aPoint 
  30819.     "Answer the value at the receiver's position aPoint.  Adjust so transparent value is correct. 6/20/96 tk"
  30820.  
  30821.     | pix |
  30822.     pix _ theForm pixelValueAt: aPoint.
  30823.     (mask pixelValueAt: aPoint) = 0 ifTrue: ["transparent"
  30824.         ^ (pix = 0) & (transparentPixelValue ~~ nil)
  30825.                 ifTrue: [transparentPixelValue]
  30826.                 ifFalse: [pix]].
  30827.     ^ pix!
  30828. pixelValueAt: aPoint put: newVal
  30829.     "Store the value at the receiver's position aPoint.  Assumed to be opaque (so correct color will show) unless it is the values used for transparent. 6/20/96 tk"
  30830.  
  30831. newVal = transparentPixelValue 
  30832.     ifTrue: [theForm pixelValueAt: aPoint put: 0.
  30833.         mask pixelValueAt: aPoint put: 0]
  30834.     ifFalse: [theForm pixelValueAt: aPoint put: newVal.
  30835.         mask pixelValueAt: aPoint put: 1].
  30836. ^ newVal! !
  30837.  
  30838. !MaskedForm methodsFor: 'display box access'!
  30839. computeBoundingBox 
  30840.     "Refer to the comment in DisplayObject.computeBoundingBox."
  30841.  
  30842.     ^theForm boundingBox! !
  30843.  
  30844. !MaskedForm methodsFor: 'displaying'!
  30845. copyBits: copyRect from: sourceForm at: destPoint clippingBox: clipRect rule: rule fillColor: fillColor 
  30846.     "Do the same transformation to both theForm and mask.  If not what you want, do them separately.  6/20/96 tk"
  30847.  
  30848.     | sourceFigure sourceShape |
  30849.     (sourceForm isMemberOf: MaskedForm)
  30850.         ifTrue:
  30851.             [sourceFigure _ sourceForm theFormReally.
  30852.             sourceShape _ sourceForm mask]
  30853.         ifFalse: [sourceFigure _ sourceShape _ sourceForm].
  30854.     theForm copyBits: copyRect
  30855.         from: sourceFigure
  30856.         at: destPoint
  30857.         clippingBox: clipRect
  30858.         rule: rule
  30859.         fillColor: fillColor.
  30860.     mask copyBits: copyRect
  30861.         from: sourceShape
  30862.         at: destPoint
  30863.         clippingBox: clipRect
  30864.         rule: rule
  30865.         fillColor: fillColor!
  30866. displayOffset
  30867.  
  30868. "Answer the offset from the bottom center to the origin (top left corner)."
  30869.  
  30870.     ^mask displayOffset!
  30871. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: fillColor
  30872.     "This is the real display message.  Remove the area of the mask, and OR in theForm."
  30873.  
  30874.     (aDisplayMedium isKindOf: MaskedForm)
  30875.         ifFalse: ["aDisplayMedium is a normal Form"
  30876.             mask displayOn: aDisplayMedium
  30877.                 at: aDisplayPoint
  30878.                 clippingBox: clipRectangle
  30879.                 rule: Form erase1bitShape
  30880.                 fillColor: nil.    "Cut a hole in the picture with my mask"
  30881.             theForm displayOn: aDisplayMedium
  30882.                 at: aDisplayPoint
  30883.                 clippingBox: clipRectangle
  30884.                 rule: Form under    "OR my picture into the hole"
  30885.                 fillColor: fillColor]
  30886.         ifTrue: ["aDisplayMedium is a MaskedForm"
  30887.             mask displayOn: aDisplayMedium mask
  30888.                 at: aDisplayPoint
  30889.                 clippingBox: clipRectangle
  30890.                 rule: Form under
  30891.                 fillColor: nil.    "OR my mask into the mask"
  30892.             mask displayOn: aDisplayMedium form
  30893.                 at: aDisplayPoint
  30894.                 clippingBox: clipRectangle
  30895.                 rule: Form erase1bitShape
  30896.                 fillColor: nil.    "Cut a hole in the picture with my mask"
  30897.             theForm displayOn: aDisplayMedium form
  30898.                 at: aDisplayPoint
  30899.                 clippingBox: clipRectangle
  30900.                 rule: Form under    "OR my picture into the hole"
  30901.                 fillColor: fillColor]!
  30902. displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aForm 
  30903.     "Copied from Form, basically"
  30904.     | absolutePoint scale magnifiedForm |
  30905.     absolutePoint _ displayTransformation applyTo: relativePoint.
  30906.     absolutePoint _ absolutePoint x asInteger @ absolutePoint y asInteger.
  30907.     displayTransformation noScale
  30908.         ifTrue: [magnifiedForm _ self]
  30909.         ifFalse: 
  30910.             [scale _ displayTransformation scale.
  30911.             scale _ scale x rounded @ scale y rounded.
  30912.             (1@1 = scale)
  30913.                     ifTrue: [scale _ nil. magnifiedForm _ self]
  30914.                     ifFalse: [magnifiedForm _ self magnify: self boundingBox by: scale]].
  30915.     magnifiedForm
  30916.         displayOn: aDisplayMedium
  30917.         at: absolutePoint - alignmentPoint
  30918.         clippingBox: clipRectangle
  30919.         rule: ruleInteger
  30920.         fillColor: aForm!
  30921. displayOnPort: port at: location
  30922.     port copyForm: mask to: location rule: Form erase1bitShape.
  30923.     port copyForm: theForm to: location rule: Form under! !
  30924.  
  30925. !MaskedForm methodsFor: 'form support'!
  30926. border: aRectangle widthRectangle: insets rule: combinationRule fillColor: aHalfTone
  30927.     "Part of regular Form protocol; pass the message on to the receiver's figure form.  6/10/96 sw"
  30928.  
  30929.     theForm border: aRectangle widthRectangle: insets rule: combinationRule fillColor: aHalfTone!
  30930. clear
  30931.     "Clear both of the underlying forms of the receiver.  5/21/96 sw"
  30932.  
  30933.     mask clear.
  30934.     theForm clear!
  30935. fill: aRectangle fillColor: aForm
  30936.     "Pass this message on to the receiver's figure form.  6/10/96 sw
  30937.     Watch out if not changing the mask at the same time.  See colorAt:Put:  6/26/96 tk"
  30938.  
  30939.     theForm fill: aRectangle fillColor: aForm!
  30940. fill: aRectangle rule: anInteger fillColor: aForm 
  30941.     "5/29/96 sw: have the receiver's figure process the request.
  30942.     Watch out if not changing the mask at the same time.  See colorAt:Put:  6/26/96 tk"
  30943.  
  30944.     theForm fill: aRectangle rule: anInteger fillColor: aForm!
  30945. fillWithColor: aColor
  30946.     "Pass this message on to the receiver's figure form.  6/10/96 sw
  30947.     Watch out if not changing the mask at the same time.  See colorAt:Put:  6/26/96 tk"
  30948.  
  30949.     theForm fillWithColor: aColor.
  30950.     mask fillWithColor: Color black.! !
  30951.  
  30952. !MaskedForm methodsFor: 'scaling'!
  30953. magnify: aRectangle by: scale 
  30954.     "Answer an MaskedForm created as a multiple of the receiver; the result is smaller. Each bit in the new form corresponds to scale number of bits in the receiver."
  30955.  
  30956.     ^ MaskedForm new setForm: (theForm magnify: aRectangle by: scale)
  30957.         mask: (mask magnify: aRectangle by: scale)
  30958.         removeOverlap: false transpPixVal: transparentPixelValue!
  30959. shrink: aRectangle by: scale 
  30960.     "Answer an MaskedForm created as a multiple of the receiver; the result is smaller. Each bit in the new form corresponds to scale number of bits in the receiver."
  30961.  
  30962.     ^MaskedForm new setForm: (theForm shrink: aRectangle by: scale)
  30963.         mask: (mask shrink: aRectangle by: scale)
  30964.         removeOverlap: false transpPixVal: transparentPixelValue! !
  30965.  
  30966. !MaskedForm methodsFor: 'fileIn/Out'!
  30967. readFrom: file
  30968.     "Read the receiver from the file as two forms."
  30969.     theForm _ Form new readFrom: file.
  30970.     mask _ Form new readFrom: file.
  30971.  
  30972. "For compatibility with old OpaqueForms that are files, only read what they have."
  30973. "  nil allowed also in these fields.
  30974.     transparentPixelValue _ Integer readFrom: file.    
  30975.     colorMap _ Array readFrom: file.    
  30976.     rawColorMap _ Bitmap readFrom: file.    
  30977. "!
  30978. writeOn: file
  30979.     "Write the receiver out on the given file, in a format which can be subsequently read back in by the companion method readFrom:.  By di 5/96; lost in the color transition, recreated 7/10/96 tk"
  30980.  
  30981.     theForm writeOn: file.
  30982.     mask writeOn: file! !
  30983.  
  30984. !MaskedForm methodsFor: 'setup'!
  30985. removeOverlap
  30986.     "Erase everything in theForm where the mask is tansparent (white).  Often what you want when theForm is more than one bit deep.  Modifies the theForm.  6/20/96 tk."
  30987.  
  30988.     mask reverse.
  30989.     mask displayOn: theForm
  30990.         at: 0@0
  30991.         clippingBox: theForm boundingBox
  30992.         rule: Form erase1bitShape
  30993.         fillColor: nil.
  30994.     mask reverse.    "back to original"
  30995. !
  30996. restoreOverlap
  30997.     "Put back the transparentPixelValue in theForm where the mask is tansparent (white).  Undo what removeOverlap did.  Current transparent area must not have any colors in it now (must be 0).  Modifies the theForm.  6/20/96 tk."
  30998.  
  30999.     transparentPixelValue == nil ifTrue: [
  31000.         ^ self error: 'Don''t know what color it was.'].
  31001.     mask reverse.
  31002.     mask displayOn: theForm
  31003.         at: 0@0
  31004.         clippingBox: theForm boundingBox
  31005.         rule: Form paint
  31006.         fillColor: (Color new pixelValue: transparentPixelValue 
  31007.             toBitPatternDepth: theForm depth).
  31008.     mask reverse.    "back to original"
  31009.     transparentPixelValue _ nil.!
  31010. setForm: form mask: m removeOverlap: remove
  31011.     "Install the form and the mask.  theForm is transparent where the mask is white, and opaque where the mask is black.  If remove is true, remove the colored pixels in this Form from its transparent area.  6/20/96 tk"
  31012.  
  31013.     theForm _ form.
  31014.     mask _ m.
  31015.     theForm extent = mask extent ifFalse: [
  31016.         self error: 'mask must be same size.'].
  31017.     mask depth = 1 ifFalse: [
  31018.         mask = theForm
  31019.             ifTrue: [^ self class transparentBorder: theForm]
  31020.             ifFalse: [^ self error: 'make the mask be 1 bit deep']].
  31021.                 "Use form:transparentColor:"
  31022.     remove ifTrue: [self removeOverlap].
  31023.  
  31024.     !
  31025. setForm: form mask: m removeOverlap: remove transpPixVal: p
  31026.     "Install the form and the mask.  theForm is transparent where the mask is white, and opaque where the mask is black.  If remove is true, remove the colored pixels in this Form from its transparent area.  6/20/96 tk"
  31027.  
  31028.     theForm _ form.
  31029.     mask _ m.
  31030.     transparentPixelValue _ p.
  31031.     theForm extent = mask extent ifFalse: [
  31032.         self error: 'mask must be same size.'].
  31033.     mask depth = 1 ifFalse: [
  31034.         mask = theForm
  31035.             ifTrue: [^ self class transparentBorder: theForm]
  31036.             ifFalse: [^ self error: 'make the mask be 1 bit deep']].
  31037.                 "Use form:transparentColor:"
  31038.     remove ifTrue: [self removeOverlap].
  31039.  
  31040.     !
  31041. setForm: aForm transparentColor: aColor
  31042.     "Create a MaskedForm with transparent where aColor is.  Substitute 0 into theForm where the mask is 1.  6/21/96 tk"
  31043.  
  31044.     | d |
  31045.     theForm _ aForm.
  31046.     aColor == nil ifTrue: [
  31047.         "no transparency, take whole form, don't mask off any of it."
  31048.         mask _ Form extent: theForm extent offset: theForm offset.
  31049.         mask fillWithColor: #black.
  31050.         ^ self].
  31051.     d _ theForm depth.
  31052.     transparentPixelValue _ aColor pixelValueForDepth: d.
  31053.     mask _ Form extent: theForm extent offset: theForm offset.
  31054.       "Copy the figure"
  31055.     colorMap _ Bitmap new: (1 bitShift: d) withAll: 1.
  31056.     colorMap at: transparentPixelValue+1 put: 0.
  31057.     mask copyBits: mask boundingBox from: theForm 
  31058.         at: 0@0 colorMap: colorMap.
  31059.  
  31060.     "Erase the color pixelValues where theForm needs to be transparent"
  31061.     transparentPixelValue = 0 ifFalse: [self removeOverlap].
  31062. !
  31063. setForm: aForm transparentPixelValue: pixVal
  31064.     "Create a MaskedForm with transparent where aColor is.  Substitute 0 into theForm where the mask is 1.  6/21/96 tk"
  31065.  
  31066.     theForm _ aForm.
  31067.     transparentPixelValue _ pixVal.
  31068.     mask _ Form extent: theForm extent offset: theForm offset.
  31069.       "Copy the figure, depth 1"
  31070.     colorMap _ Bitmap new: (1 bitShift: theForm depth) withAll: 1.
  31071.     colorMap at: transparentPixelValue+1 put: 0.
  31072.     mask copyBits: mask boundingBox from: theForm 
  31073.         at: 0@0 colorMap: colorMap.
  31074.  
  31075.     "Erase the color pixelValues where theForm needs to be transparent"
  31076.     transparentPixelValue = 0 ifFalse: [self removeOverlap].
  31077.         ! !
  31078. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  31079.  
  31080. MaskedForm class
  31081.     instanceVariableNames: ''!
  31082.  
  31083. !MaskedForm class methodsFor: 'examples'!
  31084. example
  31085.  
  31086.     Cursor blank showWhile:
  31087.         [self makeStar follow: [Sensor cursorPoint] while: [Sensor noButtonPressed]]
  31088.  
  31089.     "MaskedForm example"
  31090.     "MaskedForm makeStar bitEdit"!
  31091. makeStar
  31092.     | sampleForm pen |
  31093.     sampleForm _ Form extent: 50@50.  "Make a form"
  31094.     pen _ Pen newOnForm: sampleForm.
  31095.     pen place: 24@50; turn: 18.        "Draw a 5-pointed star on it."
  31096.     1 to: 5 do: [:i | pen go: 19; turn: 72; go: 19; turn: -144].
  31097.     ^ Cursor wait showWhile:        "Transparent around the outside"
  31098.         [self transparentBorder: sampleForm]
  31099. "
  31100. MaskedForm makeStar follow: [Sensor cursorPoint]
  31101.                         while: [Sensor noButtonPressed]
  31102. "! !
  31103.  
  31104. !MaskedForm class methodsFor: 'instance creation'!
  31105. extent: extentPoint depth: bitsPerPixel
  31106.     "Create a new MaskedForm that is blank.  All of it is transparent."
  31107.  
  31108.     ^ self new setForm: (Form extent: extentPoint depth: bitsPerPixel)
  31109.         mask: (Form extent: extentPoint) "one bit deep, transparent" 
  31110.         removeOverlap: false
  31111. !
  31112. form: form mask: mask removeOverlap: remove
  31113.     "create a MaskedForm.  If remove is true, remove the colored pixels in this Form from its transparent area.  6/20/96 tk"
  31114.  
  31115.     ^ self new setForm: form mask: mask removeOverlap: remove!
  31116. form: aForm transparentColor: aColor
  31117.     "Create a MaskedForm with transparent where aColor is.  6/21/96 tk"
  31118.  
  31119.     ^ self new setForm: aForm transparentColor: aColor!
  31120. form: aForm transparentPixelValue: pixVal
  31121.     "Create a MaskedForm with transparent where the raw pixel value is pixVal.  6/21/96 tk"
  31122.  
  31123.     ^ self new setForm: aForm transparentPixelValue: pixVal!
  31124. from: aForm box: aRect
  31125.       "From Alan's 2/96 painting code."
  31126.  
  31127.     | oform |
  31128.     oform _ Form extent: aRect extent depth: aForm depth.
  31129.     oform copyBits: aRect from: aForm at: 0@0 
  31130.         clippingBox: oform boundingBox rule: Form over fillColor: nil.
  31131.     ^ self transparentBorder: oform
  31132. !
  31133. makeShip: aScale hd: aHeading
  31134.     "Make a 'ship' (arrowhead-shaped) facing in the heading given by aHeading.   Use s as scale factor.
  31135.      By Alan Kay 2/96.  Simplified and reformatted by 5/30/96 sw"
  31136.  
  31137.     | sampleForm scaled aPen m n r loc  box | 
  31138.  
  31139.     scaled _ (80 * aScale) asInteger.
  31140.     sampleForm _ Form extent: (scaled@scaled).  "Make a form"
  31141.     aPen _ Pen newOnForm: sampleForm. 
  31142.  
  31143. "make a ship shape"
  31144.     loc _ 40@40.         
  31145.     m _ 8. n _ 20. r _ 54.
  31146.     aPen place: loc. aPen north.
  31147.         box _ loc corner: loc.
  31148.     aPen turn: aHeading +180; up.
  31149.     aPen go: m * aScale; down; turn: 45.
  31150.         box _ box encompass: aPen location.
  31151.     aPen go: n * aScale.
  31152.         box _ box encompass: aPen location.
  31153.     aPen turn: 150; go: r * aScale.
  31154.         box _ box encompass: aPen location.
  31155.     aPen place: loc. aPen north.
  31156.     aPen turn: aHeading + 180; up.
  31157.     aPen go: m * aScale; down; turn: -45.
  31158.         box _ box encompass: aPen location.
  31159.     aPen go: n* aScale.
  31160.         box _ box encompass: aPen location.
  31161.     aPen turn: -150; go: r * aScale.
  31162.         box _ box encompass: aPen location.
  31163.  
  31164.     ^ Cursor wait showWhile:        "Transparent around the outside"
  31165.         [self from: sampleForm box: ((box truncated) expandBy: 2)].
  31166.  
  31167. "Try it.
  31168.     (MaskedForm makeShip: 1 hd: 0) followCursor
  31169. "
  31170.  
  31171.  
  31172. !
  31173. transparentBorder: aForm
  31174.     "Answer an instance of me that looks like aForm,
  31175.     but is transparent in regions near the edge."
  31176.  
  31177.     | shape colorMap shapeCopy edgeColor figure |
  31178.     shape _ Form extent: aForm extent offset: aForm offset.  "Copy the figure 1 bit deep"
  31179.     colorMap _ Bitmap new: (1 bitShift: aForm depth) withAll: 1.
  31180.     colorMap at: (edgeColor _ aForm peripheralColor) + 1 put: 0.
  31181.     shape copyBits: shape boundingBox from: aForm at: 0@0 colorMap: colorMap.
  31182.     shapeCopy _ shape deepCopy.
  31183.     shape fillPeriphery: (Color black).  "Blacken edge regions"
  31184.     shapeCopy displayOn: shape at: 0@0 rule: Form reverse.
  31185.     "Now shape is just the edge region"
  31186.     edgeColor = 0
  31187.         ifTrue: ["The original form can serve as the figure"
  31188.                 figure _ aForm.
  31189.                 edgeColor _ nil]
  31190.         ifFalse: ["Need to copy the original form and zero the edge
  31191.                 region if it wasn't a true zero before"
  31192.                 figure _ aForm deepCopy.
  31193.                 shape displayOn: figure at: 0@0
  31194.                     clippingBox: figure boundingBox
  31195.                     rule: Form erase1bitShape fillColor: nil].
  31196.     shape reverse.  "Reverse to get just the inside (non-edge) region"
  31197.     ^ self new setForm: figure mask: shape 
  31198.         removeOverlap: false transpPixVal: edgeColor
  31199.  
  31200.     "Cursor blank showWhile:
  31201.         [(MaskedForm transparentBorder: Form fromUser)
  31202.             followCursor]]."!
  31203. transparentFromUser: aForm
  31204.     "Displays the Form and asks the user to click on the color that should be transparent.  Creates a MaskedForm.  6/21/96 tk"
  31205.  
  31206.     | save pt pixVal c |
  31207.     save _ Form fromDisplay: (0@0 extent: aForm extent).
  31208.     aForm displayAt: 0@0.
  31209.     [Sensor anyButtonPressed] whileFalse.
  31210.     pt _ Sensor cursorPoint.
  31211.     pt < aForm extent
  31212.         ifTrue: [pixVal _ aForm pixelValueAt: pt]
  31213.         ifFalse: [pixVal _ Display pixelValueAt: pt.
  31214.             Display depth ~= aForm depth ifTrue: [
  31215.                 c _ Color colorFromPixelValue: pixVal 
  31216.                     depth: Display depth.
  31217.                 pixVal _ c pixelValueForDepth: aForm depth]].
  31218.     save displayAt: 0@0.
  31219.     Sensor waitNoButton.
  31220.     
  31221.     ^ self new setForm: aForm transparentPixelValue: pixVal
  31222.  
  31223. "    (MaskedForm transparentFromUser: (Form fromUser)) followCursor
  31224. "! !Object subclass: #Message
  31225.     instanceVariableNames: 'selector args '
  31226.     classVariableNames: ''
  31227.     poolDictionaries: ''
  31228.     category: 'Kernel-Methods'!
  31229. Message comment:
  31230. 'I represent a selector and its argument values.
  31231.     
  31232. Generally, the system does not use instances of Message for efficiency reasons. However, when a message is not understood by its receiver, the interpreter will make up an instance of me in order to capture the information involved in an actual message transmission. This instance is sent it as an argument with the message doesNotUnderstand: to the receiver.'!
  31233.  
  31234. !Message methodsFor: 'accessing'!
  31235. argument
  31236.     "Answer the first (presumably sole) argument"
  31237.  
  31238.     ^args at: 1!
  31239. argument: newValue
  31240.     "Change the first argument to newValue and answer self"
  31241.  
  31242.     args at: 1 put: newValue!
  31243. arguments
  31244.     "Answer the arguments of the receiver."
  31245.  
  31246.     ^args!
  31247. selector
  31248.     "Answer the selector of the receiver."
  31249.  
  31250.     ^selector!
  31251. sends: aSelector
  31252.     "answer whether this message's selector is aSelector"
  31253.  
  31254.     ^selector == aSelector! !
  31255.  
  31256. !Message methodsFor: 'printing'!
  31257. printOn: aStream 
  31258.     "Refer to the comment in Object|printOn:."
  31259.  
  31260.     aStream nextPutAll: 'a Message with selector: '.
  31261.     selector printOn: aStream.
  31262.     aStream nextPutAll: ' and arguments: '.
  31263.     args printOn: aStream.
  31264.     ^aStream!
  31265. storeOn: aStream 
  31266.     "Refer to the comment in Object|storeOn:."
  31267.  
  31268.     aStream nextPut: $(.
  31269.     aStream nextPutAll: 'Message selector: '.
  31270.     selector storeOn: aStream.
  31271.     aStream nextPutAll: ' arguments: '.
  31272.     args storeOn: aStream.
  31273.     aStream nextPut: $)! !
  31274.  
  31275. !Message methodsFor: 'private'!
  31276. setSelector: aSymbol arguments: anArray
  31277.  
  31278.     selector _ aSymbol.
  31279.     args _ anArray! !
  31280.  
  31281. !Message methodsFor: 'sending'!
  31282. sentTo: receiver
  31283.     "answer the result of sending this message to receiver"
  31284.  
  31285.     ^receiver perform: selector withArguments: args! !
  31286. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  31287.  
  31288. Message class
  31289.     instanceVariableNames: ''!
  31290.  
  31291. !Message class methodsFor: 'instance creation'!
  31292. selector: aSymbol
  31293.     "Answer an instance of me with unary selector, aSymbol."
  31294.  
  31295.     ^self new setSelector: aSymbol arguments: (Array new: 0)!
  31296. selector: aSymbol argument: anObject 
  31297.     "Answer an instance of me whose selector is aSymbol and single 
  31298.     argument is anObject."
  31299.  
  31300.     ^self new setSelector: aSymbol arguments: (Array with: anObject)!
  31301. selector: aSymbol arguments: anArray 
  31302.     "Answer an instance of me with selector, aSymbol, and arguments, 
  31303.     anArray."
  31304.  
  31305.     ^self new setSelector: aSymbol arguments: anArray! !BrowserListController subclass: #MessageCategoryListController
  31306.     instanceVariableNames: ''
  31307.     classVariableNames: 'MessageCategoryListYellowButtonMessages MessageCategoryListYellowButtonMenu '
  31308.     poolDictionaries: ''
  31309.     category: 'Interface-Browser'!
  31310. MessageCategoryListController comment:
  31311. 'I am a kind of LockedListController that creates a yellow button menu so that messages can be sent to the list selection (a Message Category) to:
  31312.     browse    create a message category browser
  31313.     fileOut    print a description of the methods in this category onto an external file'!
  31314.  
  31315. !MessageCategoryListController methodsFor: 'initialize-release'!
  31316. initialize
  31317.  
  31318.     super initialize.
  31319.     self initializeYellowButtonMenu! !
  31320.  
  31321. !MessageCategoryListController methodsFor: 'menu messages'!
  31322. add
  31323.     "Add a new category."
  31324.     self controlTerminate.
  31325.     model addCategory.
  31326.     self controlInitialize!
  31327. browse
  31328.     "Create and schedule a message category browser on the selected message 
  31329.     category."
  31330.  
  31331.     self controlTerminate.
  31332.     model buildMessageCategoryBrowser.
  31333.     self controlInitialize!
  31334. fileOut
  31335.     "Print a description of the messages in the selected category onto an 
  31336.     external file."
  31337.  
  31338.     self controlTerminate.
  31339.     Cursor write showWhile:
  31340.         [model fileOutMessageCategories].
  31341.     self controlInitialize!
  31342. printOut
  31343.     "Make a file with the description of the selected mesage category.
  31344.     Defaults to the same file as fileOut, but could be changed in any given
  31345.     implementation to have a prettier format."
  31346.  
  31347.     self fileOut!
  31348. remove
  31349.     "Remove the messages in the selected category."
  31350.  
  31351.     self controlTerminate.
  31352.     model removeMessageCategory.
  31353.     self controlInitialize!
  31354. rename
  31355.     "Rename the selected category."
  31356.     self controlTerminate.
  31357.     model renameCategory.
  31358.     self controlInitialize!
  31359. reorganize
  31360.     "Request to view the entire organization of the selected class
  31361.     so that it can be edited."
  31362.     self controlTerminate.
  31363.     model editMessageCategories.
  31364.     self controlInitialize! !
  31365.  
  31366. !MessageCategoryListController methodsFor: 'private'!
  31367. changeModelSelection: anInteger
  31368.     model toggleMessageCategoryListIndex: anInteger!
  31369. initializeYellowButtonMenu
  31370.  
  31371.     self yellowButtonMenu: MessageCategoryListYellowButtonMenu 
  31372.         yellowButtonMessages: MessageCategoryListYellowButtonMessages ! !
  31373. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  31374.  
  31375. MessageCategoryListController class
  31376.     instanceVariableNames: ''!
  31377.  
  31378. !MessageCategoryListController class methodsFor: 'class initialization'!
  31379. initialize
  31380.  
  31381.     MessageCategoryListYellowButtonMenu _ 
  31382.         PopUpMenu labels:
  31383. 'browse
  31384. printOut
  31385. fileOut
  31386. reorganize
  31387. add item...
  31388. rename...
  31389. remove'
  31390.         lines: #(3 4).
  31391.     MessageCategoryListYellowButtonMessages _
  31392.         #(browse printOut fileOut
  31393.         reorganize
  31394.         add rename remove )
  31395.     "
  31396.     MessageCategoryListController initialize.
  31397.     MessageCategoryListController allInstancesDo:
  31398.         [:x | x initializeYellowButtonMenu].
  31399.     "! !
  31400.  
  31401. MessageCategoryListController initialize!
  31402. BrowserListView subclass: #MessageCategoryListView
  31403.     instanceVariableNames: ''
  31404.     classVariableNames: ''
  31405.     poolDictionaries: ''
  31406.     category: 'Interface-Browser'!
  31407. MessageCategoryListView comment:
  31408. 'I am a BrowserListView whose items are the message categories of the currently selected class in the Browser I view. MessageCategoryListController is my default controller.'!
  31409.  
  31410. !MessageCategoryListView methodsFor: 'updating'!
  31411. getList 
  31412.     "Refer to the comment in BrowserListView|getList."
  31413.  
  31414.     singleItemMode
  31415.         ifTrue: [^Array with: model selectedMessageCategoryName asSymbol]
  31416.         ifFalse: [^model messageCategoryList]!
  31417. list: anArray 
  31418.     super list: anArray.
  31419.     list numberOfLines = 3 ifTrue: [
  31420.         controller isNil ifFalse: [
  31421.             controller changeModelSelection: 1]].
  31422. !
  31423. update: aSymbol
  31424.  
  31425.     (aSymbol == #systemCategorySelectionChanged) |
  31426.     (aSymbol == #editSystemCategories)
  31427.         ifTrue: [self resetAndDisplayView. ^self].
  31428.     (aSymbol == #classSelectionChanged)
  31429.         ifTrue: [self getListAndDisplayView. ^self].
  31430.     (aSymbol == #messageCategorySelectionChanged)
  31431.         ifTrue:  [self moveSelectionBox: model messageCategoryListIndex. ^self]! !
  31432.  
  31433. !MessageCategoryListView methodsFor: 'controller access'!
  31434. defaultControllerClass
  31435.  
  31436.     ^MessageCategoryListController! !BrowserListController subclass: #MessageListController
  31437.     instanceVariableNames: ''
  31438.     classVariableNames: 'MessageListYellowButtonMessages MessageListYellowButtonMenu '
  31439.     poolDictionaries: ''
  31440.     category: 'Interface-Browser'!
  31441. MessageListController comment:
  31442. 'I am a kind of LockedListController that creates a yellow button menu so that messages can be sent to the list selection (a Message Selector) to:
  31443.     browse    create a message browser
  31444.     implementors    create a message set browser for all methods that implement the message
  31445.     messages    create a message set browser for all methods sent by the message
  31446.     senders    create a message set browser for all methods that send the message
  31447.     remove    expunge the message from the class description'!
  31448.  
  31449. !MessageListController methodsFor: 'initialize-release'!
  31450. initialize
  31451.  
  31452.     super initialize.
  31453.     self initializeYellowButtonMenu! !
  31454.  
  31455. !MessageListController methodsFor: 'menu messages'!
  31456. allImplementorsOf
  31457.     "Create and schedule a message set browser on all implementors of all
  31458.     the messages sent by the current method."
  31459.  
  31460.     self controlTerminate.
  31461.     model browseAllMessages.
  31462.     self controlInitialize!
  31463. browse
  31464.     "Create and schedule a message browser on the selected message."
  31465.  
  31466.     self controlTerminate.
  31467.     model buildMessageBrowser.
  31468.     self controlInitialize!
  31469. browseClass
  31470.     "Create and schedule a class browser on the selected class and message."
  31471.  
  31472.     | myClass |
  31473.     self controlTerminate.
  31474.     myClass _ model selectedClassOrMetaClass.
  31475.     myClass notNil ifTrue: [
  31476.         Browser postOpenSuggestion: 
  31477.             (Array with: myClass with: model selectedMessageName).
  31478.         Browser newOnClass: model selectedClass].
  31479.     self controlInitialize!
  31480. browseClassRefs
  31481.     "Inspect all instances of the selected class and all its subclasses  1/26/96 sw"
  31482.  
  31483.     | aClass |
  31484.     self controlTerminate.
  31485.     aClass _ model selectedClassOrMetaClass.
  31486.     aClass ~~ nil ifTrue:
  31487.         [aClass _ aClass theNonMetaClass.
  31488.          Smalltalk browseAllCallsOn: (Smalltalk associationAt: aClass name)].
  31489.     self controlInitialize!
  31490. browseClassVariables
  31491.     "Request a browser on the class variables of the selected class.  2/1/96 sw"
  31492.  
  31493.     | aClass |
  31494.     self controlTerminate.
  31495.     (aClass _ model selectedClassOrMetaClass) notNil ifTrue: 
  31496.         [aClass browseClassVariables].
  31497.     self controlInitialize!
  31498. browseFull
  31499.     "Create and schedule a full Browser and then select the current class and message.  1/12/96 sw"
  31500.  
  31501.     | myClass |
  31502.     (myClass _ model selectedClassOrMetaClass) notNil ifTrue: 
  31503.         [BrowserView browseFullForClass: myClass method: model selectedMessageName from: self]!
  31504. browseInstVarDefs
  31505.     "Request a browser of methods that store to a chosen instance variable.
  31506.     7/30/96 sw: made this di feature for Browsers also available in Msg List browsers."
  31507.  
  31508.     | aClass |
  31509.     self controlTerminate.
  31510.     (aClass _ model selectedClassOrMetaClass) notNil ifTrue: 
  31511.         [aClass browseInstVarDefs].
  31512.     self controlInitialize!
  31513. browseInstVarRefs
  31514.     "Request a browser of methods that access a chosen instance variable.
  31515.     1/15/96 sw"
  31516.  
  31517.     | aClass |
  31518.     self controlTerminate.
  31519.     (aClass _ model selectedClassOrMetaClass) notNil ifTrue: 
  31520.         [aClass browseInstVarRefs].
  31521.     self controlInitialize!
  31522. browseSendersOfMessages
  31523.     "Create and schedule a message set browser on the senders of messages sent by     the selected message."
  31524.  
  31525.     self controlTerminate.
  31526.     model browseSendersOfMessages.
  31527.     self controlInitialize!
  31528. classVarRefs
  31529.     "Request a browser of methods that access a chosen class variable.
  31530.     1/17/96 sw"
  31531.  
  31532.     | aClass |
  31533.     self controlTerminate.
  31534.     (aClass _ model selectedClass) notNil ifTrue: 
  31535.         [aClass browseClassVarRefs].
  31536.     self controlInitialize!
  31537. fileOut
  31538.     "Write a description of the selected message on an external file."
  31539.     self controlTerminate.
  31540.     Cursor write showWhile:
  31541.         [model fileOutMessage].
  31542.     self controlInitialize!
  31543. implementors
  31544.     "Create and schedule a message set browser on the implementations of the 
  31545.     selected message."
  31546.  
  31547.     self controlTerminate.
  31548.     model browseImplementors.
  31549.     self controlInitialize!
  31550. inspectInstances
  31551.     "Inspect all instances of the selected class.  1/26/96 sw"
  31552.  
  31553.     | myClass |
  31554.     self controlTerminate.
  31555.     myClass _ model selectedClassOrMetaClass.
  31556.     myClass ~~ nil ifTrue:
  31557.         [myClass theNonMetaClass inspectAllInstances].
  31558.     self controlInitialize!
  31559. inspectSubInstances
  31560.     "Inspect all instances of the selected class and all its subclasses  1/26/96 sw"
  31561.  
  31562.     | aClass |
  31563.     self controlTerminate.
  31564.     aClass _ model selectedClassOrMetaClass.
  31565.     aClass ~~ nil ifTrue:
  31566.         [aClass _ aClass theNonMetaClass.
  31567.          aClass inspectSubInstances].
  31568.     self controlInitialize!
  31569. messages
  31570.     "Create and schedule a message set browser on the message you pick from the
  31571.     list of messages sent by the current method."
  31572.  
  31573.     self controlTerminate.
  31574.     model browseMessages.
  31575.     self controlInitialize!
  31576. printOut
  31577.     self fileOut!
  31578. remove
  31579.     "Remove the selected message from the system. A Confirmer is created."
  31580.  
  31581.     self controlTerminate.
  31582.     model removeMessage.
  31583.     self controlInitialize!
  31584. removeMessageFromBrowser
  31585.     "Remove the selected message from the browser, but NOT from the system"
  31586.     self controlTerminate.
  31587.     (model respondsTo: #removeMessageFromBrowser) ifTrue: [model removeMessageFromBrowser].
  31588.     self controlInitialize!
  31589. senders
  31590.     "Create and schedule a message set browser on the methods in which the 
  31591.     selected message is sent."
  31592.  
  31593.     self controlTerminate.
  31594.     model browseSenders.
  31595.     self controlInitialize!
  31596. sendersOf
  31597.     "Create and schedule a message set browser on the message you pick from the
  31598.     list of messages sent by the current method."
  31599.  
  31600.     self controlTerminate.
  31601.     model browseSendersOfMessages.
  31602.     self controlInitialize!
  31603. shiftedYellowButtonMenu
  31604.     "Answer the menu to be put up when shift key is down.  1/26/96 sw"
  31605.  
  31606.     ^ PopUpMenu labels: 'browse full
  31607. browse method
  31608. implementors of sent messages
  31609. inspect instances
  31610. inspect subinstances
  31611. remove from browser
  31612. more...' 
  31613. lines: #(3 5)!
  31614. shiftedYellowButtonMessages
  31615.     "Answer the messages corresponding to the shifted-yellow-button menu, to be put up when shift key is down.  1/26/96 sw.  Adjustments, 2/5/96 sw"
  31616.  
  31617.     ^ #(browseFull browse allImplementorsOf inspectInstances inspectSubInstances removeMessageFromBrowser unshiftedYellowButtonActivity)!
  31618. versions
  31619.     "Create and schedule a changelist browser on the versions of the 
  31620.     selected message."
  31621.  
  31622.     self controlTerminate.
  31623.     model browseVersions.
  31624.     self controlInitialize! !
  31625.  
  31626. !MessageListController methodsFor: 'private'!
  31627. changeModelSelection: anInteger
  31628.     model toggleMessageListIndex: anInteger!
  31629. initializeYellowButtonMenu
  31630.  
  31631.     self yellowButtonMenu: MessageListYellowButtonMenu 
  31632.         yellowButtonMessages: MessageListYellowButtonMessages! !
  31633. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  31634.  
  31635. MessageListController class
  31636.     instanceVariableNames: ''!
  31637.  
  31638. !MessageListController class methodsFor: 'class initialization'!
  31639. initialize
  31640.     "Initialize the yellow button menu for message lists.  2/1/96 sw
  31641.      7/30/96 sw: added browseInstVarDefs"
  31642.  
  31643.     MessageListYellowButtonMenu _ 
  31644.         PopUpMenu 
  31645.             labels:
  31646. 'browse class
  31647. fileOut
  31648. senders
  31649. implementors
  31650. senders of...
  31651. implementors of...
  31652. versions
  31653. inst var refs...
  31654. inst var defs...
  31655. class var refs...
  31656. class variables
  31657. class refs
  31658. remove
  31659. more...'
  31660.             lines: #(2 6 7 9 12).
  31661.     MessageListYellowButtonMessages _
  31662.         #( browseClass  fileOut
  31663.         senders implementors  browseSendersOfMessages messages
  31664.         versions browseInstVarRefs browseInstVarDefs classVarRefs browseClassVariables browseClassRefs remove 
  31665.         shiftedYellowButtonActivity )
  31666. "
  31667.     MessageListController initialize.
  31668.     MessageListController allInstancesDo:
  31669.         [:x | x initializeYellowButtonMenu].
  31670. "! !
  31671.  
  31672. MessageListController initialize!
  31673. BrowserListView subclass: #MessageListView
  31674.     instanceVariableNames: ''
  31675.     classVariableNames: 'Once '
  31676.     poolDictionaries: ''
  31677.     category: 'Interface-Browser'!
  31678. MessageListView comment:
  31679. 'I am a BrowserListView whose items are the messages of the currently selected message category of the currently selected class in the Browser I view. MessageListController is my default controller.'!
  31680.  
  31681. !MessageListView methodsFor: 'updating'!
  31682. displayView 
  31683.     "Refer to the comment in View|displayView."
  31684.  
  31685.     | aClass sel index baseClass |
  31686.     Browser postOpenSuggestion == nil ifFalse: [
  31687.         "Set the class and message"
  31688.         aClass _ Browser postOpenSuggestion first.
  31689.         sel _ Browser postOpenSuggestion last.
  31690.         Browser postOpenSuggestion: nil.
  31691.         baseClass _ aClass theNonMetaClass.
  31692.         index _ SystemOrganization numberOfCategoryOfElement: baseClass name.
  31693.         model metaClassIndicated: aClass isMeta.
  31694.         model systemCategoryListIndex: index.
  31695.         model metaClassIndicated: aClass isMeta.
  31696.         model classListIndex: ((SystemOrganization listAtCategoryNumber: index)
  31697.                 findFirst: [:each | each == baseClass name]).
  31698.         sel notNil ifTrue: [
  31699.             index _ aClass organization numberOfCategoryOfElement: sel.
  31700.             model messageCategoryListIndex: index.
  31701.             model messageListIndex: 
  31702.                 ((aClass organization listAtCategoryNumber: index) indexOf: sel)
  31703.             ].
  31704.         ^ self topView deEmphasize.   "a redisplay has already been done"
  31705.         ].
  31706.     super displayView.!
  31707. getList 
  31708.     "Refer to the comment in BrowserListView|getList."
  31709.  
  31710.     | selectedMessageName |
  31711.     singleItemMode
  31712.         ifTrue: 
  31713.             [selectedMessageName _ model selectedMessageName.
  31714.             selectedMessageName == nil ifTrue: [selectedMessageName _ '    '].
  31715.             ^Array with: selectedMessageName asSymbol]
  31716.         ifFalse: [^model messageList]!
  31717. list: anArray 
  31718.     super list: anArray.
  31719.     list numberOfLines = 3 ifTrue: [
  31720.         controller isNil ifFalse: [
  31721.             controller changeModelSelection: 1]].
  31722. !
  31723. update: aSymbol
  31724.     "What to do to the message list when Browser changes.
  31725.     If there is only one item, select and show it." 
  31726.     aSymbol == #messageSelectionChanged
  31727.         ifTrue: [self updateMessageSelection. ^self].
  31728.  
  31729.     (aSymbol == #systemCategorySelectionChanged) |
  31730.     (aSymbol == #editSystemCategories) |
  31731.     (aSymbol == #editClass) |
  31732.     (aSymbol == #editMessageCategories)
  31733.         ifTrue: [self resetAndDisplayView. ^self].
  31734.  
  31735.     (aSymbol == #messageCategorySelectionChanged) |
  31736.     (aSymbol == #messageListChanged) 
  31737.         ifTrue: [self updateMessageList. ^self].
  31738.  
  31739.     (aSymbol == #classSelectionChanged) ifTrue: [
  31740.         model messageCategoryListIndex = 1
  31741.             ifTrue: ["self updateMessageList." ^self]
  31742.             ifFalse: [self resetAndDisplayView. ^self]].! !
  31743.  
  31744. !MessageListView methodsFor: 'controller access'!
  31745. defaultControllerClass
  31746.  
  31747.     ^MessageListController! !
  31748.  
  31749. !MessageListView methodsFor: 'private'!
  31750. updateMessageList
  31751.  
  31752.     singleItemMode ifFalse: [self getListAndDisplayView] !
  31753. updateMessageSelection
  31754.  
  31755.     singleItemMode
  31756.         ifTrue: [self getListAndDisplayView] 
  31757.         ifFalse: [self moveSelectionBox: model messageListIndex]! !ParseNode subclass: #MessageNode
  31758.     instanceVariableNames: 'receiver selector precedence special arguments sizes pc equalNode caseErrorNode '
  31759.     classVariableNames: 'MacroTransformers MacroSizers MacroPrinters MacroSelectors ThenFlag MacroEmitters StdTypers '
  31760.     poolDictionaries: ''
  31761.     category: 'System-Compiler'!
  31762. MessageNode comment:
  31763. 'I represent a receiver and its message.
  31764.     
  31765. Precedence codes:
  31766.     1 unary
  31767.     2 binary
  31768.     3 keyword
  31769.     4 other
  31770.     
  31771. If special>0, I compile special code in-line instead of sending messages with literal methods as remotely copied contexts.'!
  31772.  
  31773. !MessageNode methodsFor: 'initialize-release'!
  31774. receiver: rcvr selector: selNode arguments: args precedence: p 
  31775.     "Decompile."
  31776.  
  31777.     self receiver: rcvr
  31778.         arguments: args
  31779.         precedence: p.
  31780.     special _ MacroSelectors indexOf: selNode key.
  31781.     selector _ selNode.
  31782.     "self pvtCheckForPvtSelector: encoder"    "We could test code being decompiled, but the compiler should've checked already. And where to send the complaint?"!
  31783. receiver: rcvr selector: selName arguments: args precedence: p from: encoder 
  31784.     "Compile."
  31785.  
  31786.     self receiver: rcvr
  31787.         arguments: args
  31788.         precedence: p.
  31789.     special _ MacroSelectors indexOf: selName.
  31790.     (self transform: encoder)
  31791.         ifTrue: 
  31792.             [selector isNil
  31793.                 ifTrue: [selector _ SelectorNode new 
  31794.                             key: (MacroSelectors at: special)
  31795.                             code: #macro]]
  31796.         ifFalse: 
  31797.             [selector _ encoder encodeSelector: selName.
  31798.             rcvr == NodeSuper ifTrue: [encoder noteSuper]].
  31799.     self pvtCheckForPvtSelector: encoder!
  31800. receiver: rcvr selector: selName arguments: args precedence: p from: encoder sourceRange: range 
  31801.     "Compile."
  31802.  
  31803.     encoder noteSourceRange: range forNode: self.
  31804.     ^self
  31805.         receiver: rcvr
  31806.         selector: selName
  31807.         arguments: args
  31808.         precedence: p
  31809.         from: encoder! !
  31810.  
  31811. !MessageNode methodsFor: 'testing'!
  31812. canCascade
  31813.  
  31814.     ^(receiver == NodeSuper or: [special > 0]) not!
  31815. isComplex
  31816.     
  31817.     ^(special between: 1 and: 10) or: [arguments size > 2 or: [receiver isComplex]]!
  31818. isMessage: selSymbol receiver: rcvrPred arguments: argsPred
  31819.     "Answer whether selector is selSymbol, and the predicates rcvrPred and argsPred
  31820.      evaluate to true with respect to receiver and the list of arguments.  If selSymbol or
  31821.      either predicate is nil, it means 'don't care'.  Note that argsPred takes numArgs
  31822.      arguments.  All block arguments are ParseNodes."
  31823.  
  31824.     ^(selSymbol isNil or: [selSymbol==selector key]) and:
  31825.         [(rcvrPred isNil or: [rcvrPred value: receiver]) and:
  31826.             [(argsPred isNil or: [argsPred valueWithArguments: arguments])]]!
  31827. isReturningIf
  31828.  
  31829.     ^(special between: 3 and: 4)
  31830.         and: [arguments first returns and: [arguments last returns]]!
  31831. isTemp
  31832.     "May be masquerading for debugger access to temps."
  31833.     ^ selector key == #tempAt:!
  31834. prefersValue
  31835.     "return true of this node generates shorter code when it leaves a value
  31836.     on the stack"
  31837.     ^ (special =3 or: [special =4]) and: [self isReturningIf not]!
  31838. toDoIncrement: variable
  31839.     (receiver = variable and: [selector key = #+]) 
  31840.         ifFalse: [^ nil].
  31841.     arguments first isConstantNumber
  31842.         ifTrue: [^ arguments first]
  31843.         ifFalse: [^ nil]!
  31844. toDoLimit: variable
  31845.     (receiver = variable and: [selector key = #<= or: [selector key = #>=]]) 
  31846.         ifTrue: [^ arguments first]
  31847.         ifFalse: [^ nil]! !
  31848.  
  31849. !MessageNode methodsFor: 'cascading'!
  31850. cascadeReceiver
  31851.     "Nil out rcvr (to indicate cascade) and return what it had been."
  31852.  
  31853.     | rcvr |
  31854.     rcvr _ receiver.
  31855.     receiver _ nil.
  31856.     ^rcvr! !
  31857.  
  31858. !MessageNode methodsFor: 'macro transformations'!
  31859. transform: encoder
  31860.     special = 0 ifTrue: [^false].
  31861.     (self perform: (MacroTransformers at: special) with: encoder)
  31862.         ifTrue: 
  31863.             [^true]
  31864.         ifFalse: 
  31865.             [special _ 0. ^false]!
  31866. transformAnd: encoder
  31867.     (self transformBoolean: encoder)
  31868.         ifTrue: 
  31869.             [arguments _ 
  31870.                 Array 
  31871.                     with: (arguments at: 1)
  31872.                     with: (BlockNode withJust: NodeFalse).
  31873.             ^true]
  31874.         ifFalse: 
  31875.             [^false]!
  31876. transformBoolean: encoder
  31877.     ^self
  31878.         checkBlock: (arguments at: 1)
  31879.         as: 'argument'
  31880.         from: encoder!
  31881. transformIfFalse: encoder
  31882.     (self transformBoolean: encoder)
  31883.         ifTrue: 
  31884.             [arguments _ 
  31885.                 Array 
  31886.                     with: (BlockNode withJust: NodeNil)
  31887.                     with: (arguments at: 1).
  31888.             ^true]
  31889.         ifFalse:
  31890.             [^false]!
  31891. transformIfFalseIfTrue: encoder
  31892.     ((self checkBlock: (arguments at: 1) as: 'False arg' from: encoder)
  31893.         and: [self checkBlock: (arguments at: 2) as: 'True arg' from: encoder])
  31894.         ifTrue: 
  31895.             [selector _ #ifTrue:ifFalse:.
  31896.             arguments swap: 1 with: 2.
  31897.             ^true]
  31898.         ifFalse: 
  31899.             [^false]!
  31900. transformIfTrue: encoder
  31901.     (self transformBoolean: encoder)
  31902.         ifTrue: 
  31903.             [arguments _ 
  31904.                 Array 
  31905.                     with: (arguments at: 1)
  31906.                     with: (BlockNode withJust: NodeNil).
  31907.             ^true]
  31908.         ifFalse: 
  31909.             [^false]!
  31910. transformIfTrueIfFalse: encoder
  31911.     ^ (self checkBlock: (arguments at: 1) as: 'True arg' from: encoder)
  31912.         and: [self checkBlock: (arguments at: 2) as: 'False arg' from: encoder]!
  31913. transformOr: encoder
  31914.     (self transformBoolean: encoder)
  31915.         ifTrue: 
  31916.             [arguments _ 
  31917.                 Array 
  31918.                     with: (BlockNode withJust: NodeTrue)
  31919.                     with: (arguments at: 1).
  31920.             ^true]
  31921.         ifFalse: 
  31922.             [^false]!
  31923. transformToDo: encoder
  31924.     " var _ rcvr. L1: [var <= arg1] Bfp(L2) [block body. var _ var + inc] Jmp(L1) L2: "
  31925.     | limit increment block initStmt test incStmt limitInit blockVar |
  31926.     "First check for valid arguments"
  31927.     (receiver isConstantNumber
  31928.         and: [(arguments last isMemberOf: BlockNode)
  31929.                 and: [arguments last numberOfArguments = 1]])
  31930.         ifFalse: [^ false].
  31931.     arguments last firstArgument isVariableReference
  31932.         ifFalse: [^ false]. "As with debugger remote vars"
  31933.     arguments size = 3
  31934.         ifTrue: [increment _ arguments at: 2.
  31935.                 increment isConstantNumber ifFalse: [^ false]]
  31936.         ifFalse: [increment _ encoder encodeLiteral: 1].
  31937.     arguments size < 3 ifTrue:   "transform to full form"
  31938.         [selector _ SelectorNode new key: #to:by:do: code: #macro].
  31939.  
  31940.     "Now generate auxiliary structures"
  31941.     block _ arguments last.
  31942.     blockVar _ block firstArgument.
  31943.     initStmt _ AssignmentNode new variable: blockVar value: receiver.
  31944.     limit _ arguments at: 1.
  31945.     limit isVariableReference | limit isConstantNumber
  31946.         ifTrue: [limitInit _ nil]
  31947.         ifFalse:  "Need to store limit in a var"
  31948.             [limit _ encoder autoBind: blockVar key , 'LimiT'.
  31949.             limitInit _ AssignmentNode new
  31950.                     variable: limit
  31951.                     value: (arguments at: 1)].
  31952.     test _ MessageNode new receiver: blockVar
  31953.             selector: (increment key > 0 ifTrue: [#<=] ifFalse: [#>=])
  31954.             arguments: (Array with: limit)
  31955.             precedence: precedence from: encoder.
  31956.     incStmt _ AssignmentNode new
  31957.             variable: blockVar
  31958.             value: (MessageNode new
  31959.                 receiver: blockVar selector: #+
  31960.                 arguments: (Array with: increment)
  31961.                 precedence: precedence from: encoder).
  31962.     arguments _ (Array with: limit with: increment with: block)
  31963.         , (Array with: initStmt with: test with: incStmt with: limitInit).
  31964.     ^ true!
  31965. transformWhile: encoder
  31966.     (self checkBlock: receiver as: 'receiver' from: encoder)
  31967.         ifFalse: [^ false].
  31968.     arguments size = 0   "transform bodyless form to body form"
  31969.         ifTrue: [selector _ SelectorNode new
  31970.                     key: (special = 10 ifTrue: [#whileTrue:] ifFalse: [#whileFalse:])
  31971.                     code: #macro.
  31972.                 arguments _ Array with: (BlockNode withJust: NodeNil).
  31973.                 ^ true]
  31974.         ifFalse: [^ self transformBoolean: encoder]!
  31975. whileAsToDo: initStmt
  31976.     "Return nil, or a to:do: expression equivalent to this whileTrue:"
  31977.     | variable increment limit toDoBlock body test |
  31978.     (selector key == #whileTrue: and: [initStmt isMemberOf: AssignmentNode])
  31979.         ifFalse: [^ nil].
  31980.     variable _ initStmt variable.
  31981.     variable isConstantNumber  "Otherwise would decompile some "
  31982.         ifFalse: [^ nil].   " whiles into to:do:s that work differently."
  31983.     body _ arguments last statements.
  31984.     increment _ body last toDoIncrement: variable.
  31985.     (increment == nil or: [receiver statements size ~= 1])
  31986.         ifTrue: [^ nil].
  31987.     test _ receiver statements first.
  31988.     ((test isMemberOf: MessageNode)
  31989.         and: [(limit _ test toDoLimit: variable) notNil])
  31990.         ifFalse: [^ nil].
  31991.     toDoBlock _ BlockNode new
  31992.             statements: (body copyFrom: 1 to: body size-1)
  31993.             returns: false.
  31994.     toDoBlock arguments: (Array with: variable).
  31995.     ^ MessageNode new
  31996.         receiver: initStmt value
  31997.         selector: (SelectorNode new key: #to:by:do: code: #macro)
  31998.         arguments: (Array with: limit with: increment with: toDoBlock)
  31999.         precedence: precedence! !
  32000.  
  32001. !MessageNode methodsFor: 'code generation'!
  32002. emitAs: stack on: strm value: forValue 
  32003.     " {...} as: .. -- handoff to receiver, which already incorporates argument."
  32004.  
  32005.     forValue
  32006.         ifTrue: [receiver emitForValue: stack on: strm]
  32007.         ifFalse: [receiver emitForEffect: stack on: strm]!
  32008. emitCase: stack on: strm value: forValue
  32009.  
  32010.     | braceNode sizeStream thenSize elseSize |
  32011.     forValue not
  32012.         ifTrue: [^super emitForEffect: stack on: strm].
  32013.     braceNode _ arguments first.
  32014.     sizeStream _ ReadStream on: sizes.
  32015.     receiver emitForValue: stack on: strm.
  32016.     braceNode casesForwardDo:
  32017.         [:keyNode :valueNode :last |
  32018.         thenSize _ sizeStream next.
  32019.         elseSize _ sizeStream next.
  32020.         last ifFalse: [strm nextPut: Dup. stack push: 1].
  32021.         keyNode emitForEvaluatedValue: stack on: strm.
  32022.         equalNode emit: stack args: 1 on: strm.
  32023.         self emitBranchOn: false dist: thenSize pop: stack on: strm.
  32024.         valueNode emitForEvaluatedValue: stack on: strm.
  32025.         stack pop: 1.
  32026.         valueNode returns ifFalse: [self emitJump: elseSize on: strm]].
  32027.     arguments size = 2
  32028.         ifTrue:
  32029.             [arguments last emitForEvaluatedValue: stack on: strm] "otherwise: [...]"
  32030.         ifFalse:
  32031.             [NodeSelf emitForValue: stack on: strm.
  32032.             caseErrorNode emit: stack args: 0 on: strm]!
  32033. emitForEffect: stack on: strm
  32034.  
  32035.     special > 0
  32036.         ifTrue: 
  32037.             [self perform: (MacroEmitters at: special) with: stack with: strm with: false.
  32038.             pc _ 0]
  32039.         ifFalse: 
  32040.             [super emitForEffect: stack on: strm]!
  32041. emitForValue: stack on: strm
  32042.  
  32043.     | argument |
  32044.     special > 0
  32045.         ifTrue: 
  32046.             [self perform: (MacroEmitters at: special) with: stack with: strm with: true.
  32047.             pc _ 0]
  32048.         ifFalse: 
  32049.             [receiver ~~ nil ifTrue: [receiver emitForValue: stack on: strm].
  32050.             arguments do: [:argument | argument emitForValue: stack on: strm].
  32051.             selector
  32052.                 emit: stack
  32053.                 args: arguments size
  32054.                 on: strm
  32055.                 super: receiver == NodeSuper.
  32056.             pc _ strm position]!
  32057. emitIf: stack on: strm value: forValue
  32058.     | thenExpr thenSize elseExpr elseSize |
  32059.     thenSize _ sizes at: 1.
  32060.     elseSize _ sizes at: 2.
  32061.     (forValue not and: [(elseSize*thenSize) > 0])
  32062.         ifTrue:  "Two-armed IFs forEffect share a single pop"
  32063.             [^ super emitForEffect: stack on: strm].
  32064.     thenExpr _ arguments at: 1.
  32065.     elseExpr _ arguments at: 2.
  32066.     receiver emitForValue: stack on: strm.
  32067.     forValue
  32068.         ifTrue:  "Code all forValue as two-armed"
  32069.             [self emitBranchOn: false dist: thenSize pop: stack on: strm.
  32070.             thenExpr emitForEvaluatedValue: stack on: strm.
  32071.             stack pop: 1.  "then and else alternate; they don't accumulate"
  32072.             thenExpr returns not
  32073.                 ifTrue:  "Elide jump over else after a return"
  32074.                     [self emitJump: elseSize on: strm].
  32075.             elseExpr emitForEvaluatedValue: stack on: strm]
  32076.         ifFalse:  "One arm is empty here (two-arms code forValue)"
  32077.             [thenSize > 0
  32078.                 ifTrue:
  32079.                     [self emitBranchOn: false dist: thenSize pop: stack on: strm.
  32080.                     thenExpr emitForEvaluatedEffect: stack on: strm]
  32081.                 ifFalse:
  32082.                     [self emitBranchOn: true dist: elseSize pop: stack on: strm.
  32083.                     elseExpr emitForEvaluatedEffect: stack on: strm]]!
  32084. emitToDo: stack on: strm value: forValue 
  32085.     " var _ rcvr. L1: [var <= arg1] Bfp(L2) [block body. var _ var + inc] Jmp(L1) L2: "
  32086.     | loopSize initStmt limitInit test block incStmt blockSize |
  32087.     initStmt _ arguments at: 4.
  32088.     limitInit _ arguments at: 7.
  32089.     test _ arguments at: 5.
  32090.     block _ arguments at: 3.
  32091.     incStmt _ arguments at: 6.
  32092.     blockSize _ sizes at: 1.
  32093.     loopSize _ sizes at: 2.
  32094.     limitInit == nil
  32095.         ifFalse: [limitInit emitForEffect: stack on: strm].
  32096.     initStmt emitForEffect: stack on: strm.
  32097.     test emitForValue: stack on: strm.
  32098.     self emitBranchOn: false dist: blockSize pop: stack on: strm. 
  32099.     block emitForEvaluatedEffect: stack on: strm.
  32100.     incStmt emitForEffect: stack on: strm.
  32101.     self emitJump: 0 - loopSize on: strm.
  32102.     forValue ifTrue: [strm nextPut: LdNil. stack push: 1]!
  32103. emitWhile: stack on: strm value: forValue 
  32104.     " L1: ... Bfp(L2)|Btp(L2) ... Jmp(L1) L2: "
  32105.     | cond stmt stmtSize loopSize |
  32106.     cond _ receiver.
  32107.     stmt _ arguments at: 1.
  32108.     stmtSize _ sizes at: 1.
  32109.     loopSize _ sizes at: 2.
  32110.     cond emitForEvaluatedValue: stack on: strm.
  32111.     self emitBranchOn: (selector key == #whileFalse:)  "Bfp for whileTrue"
  32112.                     dist: stmtSize pop: stack on: strm.   "Btp for whileFalse"
  32113.     stmt emitForEvaluatedEffect: stack on: strm.
  32114.     self emitJump: 0 - loopSize on: strm.
  32115.     forValue ifTrue: [strm nextPut: LdNil. stack push: 1]!
  32116. pc
  32117.     "Used by encoder source mapping."
  32118.  
  32119.     pc==nil ifTrue: [^0] ifFalse: [^pc]!
  32120. sizeAs: encoder value: forValue 
  32121.     "Only receiver generates any code."
  32122.  
  32123.     ^forValue
  32124.         ifTrue: [receiver sizeForValue: encoder]
  32125.         ifFalse: [receiver sizeForEffect: encoder]!
  32126. sizeCase: encoder value: forValue
  32127.  
  32128.     | braceNode sizeIndex thenSize elseSize |
  32129.     forValue not
  32130.         ifTrue: [^super sizeForEffect: encoder].
  32131.     equalNode _ encoder encodeSelector: #=.
  32132.     braceNode _ arguments first.
  32133.     sizes _ Array new: 2 * braceNode numElements.
  32134.     sizeIndex _ sizes size.
  32135.     elseSize _ arguments size = 2
  32136.         ifTrue:
  32137.             [arguments last sizeForEvaluatedValue: encoder] "otherwise: [...]"
  32138.         ifFalse:
  32139.             [caseErrorNode _ encoder encodeSelector: #caseError.
  32140.              1 + (caseErrorNode size: encoder args: 0 super: false)]. "self caseError"
  32141.     braceNode casesReverseDo:
  32142.         [:keyNode :valueNode :last |
  32143.         sizes at: sizeIndex put: elseSize.
  32144.         thenSize _ valueNode sizeForEvaluatedValue: encoder.
  32145.         valueNode returns ifFalse: [thenSize _ thenSize + (self sizeJump: elseSize)].
  32146.         sizes at: sizeIndex-1 put: thenSize.
  32147.         last ifFalse: [elseSize _ elseSize + 1]. "Dup"
  32148.         elseSize _ elseSize + (keyNode sizeForEvaluatedValue: encoder) +
  32149.             (equalNode size: encoder args: 1 super: false) +
  32150.             (self sizeBranchOn: false dist: thenSize) + thenSize.
  32151.         sizeIndex _ sizeIndex - 2].
  32152.     ^(receiver sizeForValue: encoder) + elseSize
  32153. !
  32154. sizeForEffect: encoder
  32155.  
  32156.     special > 0 
  32157.         ifTrue: [^self perform: (MacroSizers at: special) with: encoder with: false].
  32158.     ^super sizeForEffect: encoder!
  32159. sizeForValue: encoder
  32160.  
  32161.     | arg total argSize |
  32162.     special > 0 
  32163.         ifTrue: [^self perform: (MacroSizers at: special) with: encoder with: true].
  32164.     receiver == NodeSuper
  32165.         ifTrue: [selector _ selector copy "only necess for splOops"].
  32166.     total _ selector size: encoder args: arguments size super: receiver == NodeSuper.
  32167.     receiver == nil 
  32168.         ifFalse: [total _ total + (receiver sizeForValue: encoder)].
  32169.     sizes _ arguments collect: 
  32170.                     [:arg | 
  32171.                     argSize _ arg sizeForValue: encoder.
  32172.                     total _ total + argSize.
  32173.                     argSize].
  32174.     ^total!
  32175. sizeIf: encoder value: forValue
  32176.     | thenExpr elseExpr branchSize thenSize elseSize |
  32177.     thenExpr _ arguments at: 1.
  32178.     elseExpr _ arguments at: 2.
  32179.     (forValue
  32180.         or: [(thenExpr isJust: NodeNil)
  32181.         or: [elseExpr isJust: NodeNil]]) not
  32182.             "(...not ifTrue: avoids using ifFalse: alone during this compile)"
  32183.         ifTrue:  "Two-armed IFs forEffect share a single pop"
  32184.             [^ super sizeForEffect: encoder].
  32185.     forValue
  32186.         ifTrue:  "Code all forValue as two-armed"
  32187.             [elseSize _ elseExpr sizeForEvaluatedValue: encoder.
  32188.             thenSize _ (thenExpr sizeForEvaluatedValue: encoder)
  32189.                     + (thenExpr returns
  32190.                         ifTrue: [0]  "Elide jump over else after a return"
  32191.                         ifFalse: [self sizeJump: elseSize]).
  32192.             branchSize _ self sizeBranchOn: false dist: thenSize]
  32193.         ifFalse:  "One arm is empty here (two-arms code forValue)"
  32194.             [(elseExpr isJust: NodeNil)
  32195.                 ifTrue:
  32196.                     [elseSize _ 0.
  32197.                     thenSize _ thenExpr sizeForEvaluatedEffect: encoder.
  32198.                     branchSize _ self sizeBranchOn: false dist: thenSize]
  32199.                 ifFalse:
  32200.                     [thenSize _ 0.
  32201.                     elseSize _ elseExpr sizeForEvaluatedEffect: encoder.
  32202.                     branchSize _ self sizeBranchOn: true dist: elseSize]].
  32203.     sizes _ Array with: thenSize with: elseSize.
  32204.     ^ (receiver sizeForValue: encoder) + branchSize
  32205.             + thenSize + elseSize!
  32206. sizeToDo: encoder value: forValue 
  32207.     " var _ rcvr. L1: [var <= arg1] Bfp(L2) [block body. var _ var + inc] Jmp(L1) L2: "
  32208.     | loopSize initStmt test block incStmt blockSize blockVar initSize limitInit |
  32209.     block _ arguments at: 3.
  32210.     blockVar _ block firstArgument.
  32211.     initStmt _ arguments at: 4.
  32212.     test _ arguments at: 5.
  32213.     incStmt _ arguments at: 6.
  32214.     limitInit _ arguments at: 7.
  32215.     initSize _ initStmt sizeForEffect: encoder.
  32216.     limitInit == nil
  32217.         ifFalse: [initSize _ initSize + (limitInit sizeForEffect: encoder)].
  32218.     blockSize _ (block sizeForEvaluatedEffect: encoder)
  32219.             + (incStmt sizeForEffect: encoder) + 2.  "+2 for Jmp backward"
  32220.     loopSize _ (test sizeForValue: encoder)
  32221.             + (self sizeBranchOn: false dist: blockSize)
  32222.             + blockSize.
  32223.     sizes _ Array with: blockSize with: loopSize.
  32224.     ^ initSize + loopSize
  32225.             + (forValue ifTrue: [1] ifFalse: [0])    " +1 for value (push nil) "!
  32226. sizeWhile: encoder value: forValue 
  32227.     "L1: ... Bfp(L2) ... Jmp(L1) L2: nil (nil for value only);
  32228.     justStmt, wholeLoop, justJump."
  32229.     | cond stmt stmtSize loopSize branchSize |
  32230.     cond _ receiver.
  32231.     stmt _ arguments at: 1.
  32232.     stmtSize _ (stmt sizeForEvaluatedEffect: encoder) + 2.
  32233.     branchSize _ self sizeBranchOn: (selector key == #whileFalse:)  "Btp for whileFalse"
  32234.                     dist: stmtSize.
  32235.     loopSize _ (cond sizeForEvaluatedValue: encoder)
  32236.             + branchSize + stmtSize.
  32237.     sizes _ Array with: stmtSize with: loopSize.
  32238.     ^ loopSize    " +1 for value (push nil) "
  32239.         + (forValue ifTrue: [1] ifFalse: [0])! !
  32240.  
  32241. !MessageNode methodsFor: 'debugger temp access'!
  32242. asStorableNode: encoder
  32243.     "This node is a message masquerading as a temporary variable.
  32244.     It currently has the form {homeContext tempAt: offset}.
  32245.     We need to generate code for {expr storeAt: offset inTempFrame: homeContext},
  32246.     where the expr, the block argument, is already on the stack.
  32247.     This, in turn will get turned into {homeContext tempAt: offset put: expr}
  32248.     at runtime if nobody disturbs storeAt:inTempFrame: in Object (not clean)"
  32249.     ^ MessageNode new
  32250.         receiver: nil  "suppress code generation for reciever already on stack"
  32251.         selector: #storeAt:inTempFrame:
  32252.         arguments: (arguments copyWith: receiver)
  32253.         precedence: precedence
  32254.         from: encoder!
  32255. emitStorePop: stack on: codeStream
  32256.     "This node has the form {expr storeAt: offset inTempFrame: homeContext},
  32257.     where the expr, the block argument, is already on the stack."
  32258.     ^ self emitForEffect: stack on: codeStream!
  32259. sizeForStorePop: encoder
  32260.     "This node has the form {expr storeAt: offset inTempFrame: homeContext},
  32261.     where the expr, the block argument, is already on the stack."
  32262.     ^ self sizeForEffect: encoder!
  32263. store: expr from: encoder 
  32264.     "ctxt tempAt: n -> ctxt tempAt: n put: expr (see Assignment).
  32265.     For assigning into temps of a context being debugged."
  32266.  
  32267.     selector key ~= #tempAt: 
  32268.         ifTrue: [^self error: 'cant transform this message'].
  32269.     ^MessageNode new
  32270.         receiver: receiver
  32271.         selector: #tempAt:put:
  32272.         arguments: (arguments copyWith: expr)
  32273.         precedence: precedence
  32274.         from: encoder! !
  32275.  
  32276. !MessageNode methodsFor: 'printing'!
  32277. precedence
  32278.  
  32279.     ^precedence!
  32280. printAs: aStream indent: level
  32281.  
  32282.     self printKeywords: #as:
  32283.         arguments: arguments
  32284.         on: aStream
  32285.         indent: level!
  32286. printAsOn: aStream indent: level
  32287.  
  32288.     self printKeywords: #as:
  32289.         arguments: arguments
  32290.         on: aStream
  32291.         indent: level!
  32292. printCaseOn: aStream indent: level
  32293.     "receiver caseOf: {[key]->[value]. ...} otherwise: [otherwise]"
  32294.  
  32295.     | braceNode otherwise extra |
  32296.     braceNode _ arguments first.
  32297.     otherwise _ arguments last.
  32298.     ((arguments size = 1) or: [otherwise isJustCaseError])
  32299.         ifTrue: [otherwise _ nil].
  32300.     receiver printOn: aStream indent: level precedence: 3.
  32301.     aStream nextPutAll: ' caseOf: {'; crtab: level+1.
  32302.     braceNode casesForwardDo:
  32303.         [:keyNode :valueNode :last |
  32304.         keyNode printOn: aStream indent: level+1.
  32305.          aStream nextPutAll: ' -> '.
  32306.         extra _ valueNode isComplex ifTrue: [aStream crtab: level+2. 1] ifFalse: [0].
  32307.          valueNode printOn: aStream indent: level+1+extra.
  32308.          last ifTrue: [aStream nextPut: $}] ifFalse: [aStream nextPut: $.; crtab: level+1]].
  32309.     otherwise isNil
  32310.         ifFalse:
  32311.             [aStream crtab: level+1; nextPutAll: 'otherwise: '.
  32312.              extra _ otherwise isComplex ifTrue: [aStream crtab: level+2. 1] ifFalse: [0].
  32313.              otherwise printOn: aStream indent: level+1+extra]!
  32314. printIfOn: aStream indent: level
  32315.  
  32316.     (arguments last isJust: NodeNil) ifTrue:
  32317.         [^self printKeywords: #ifTrue: arguments: (Array with: arguments first)
  32318.                     on: aStream indent: level].
  32319.     (arguments last isJust: NodeFalse) ifTrue:
  32320.         [^self printKeywords: #and: arguments: (Array with: arguments first)
  32321.                     on: aStream indent: level].
  32322.     (arguments first isJust: NodeNil) ifTrue:
  32323.         [^self printKeywords: #ifFalse: arguments: (Array with: arguments last)
  32324.                     on: aStream indent: level].
  32325.     (arguments first isJust: NodeTrue) ifTrue:
  32326.         [^self printKeywords: #or: arguments: (Array with: arguments last)
  32327.                     on: aStream indent: level].
  32328.     self printKeywords: #ifTrue:ifFalse: arguments: arguments
  32329.                     on: aStream indent: level!
  32330. printKeywords: key arguments: args on: aStream indent: level
  32331.  
  32332.     | keywords part prev arg indent thisKey |
  32333.     args size = 0 
  32334.         ifTrue: [aStream space; nextPutAll: key. ^self].
  32335.     keywords _ key keywords.
  32336.     prev _ receiver.
  32337.     1 to: args size do:
  32338.         [:part | arg _ args at: part.
  32339.         thisKey _ keywords at: part.
  32340.         (prev isMemberOf: BlockNode)
  32341.          | ((prev isMemberOf: MessageNode) and: [prev precedence >= 3])
  32342.          | ((arg isMemberOf: BlockNode) and: [arg isComplex and: [thisKey ~= #do:]])
  32343.          | (args size > 2)
  32344.          | (key = #ifTrue:ifFalse:)
  32345.             ifTrue: [aStream crtab: level+1. indent _ 1] "newline after big args"
  32346.             ifFalse: [aStream space. indent _ 0].
  32347.         aStream nextPutAll: thisKey; space.
  32348.         arg  printOn: aStream indent: level + 1 + indent
  32349.              precedence: (precedence = 2 ifTrue: [1] ifFalse: [precedence]).
  32350.         prev _ arg]!
  32351. printOn: aStream indent: level
  32352.  
  32353.     | printer |
  32354.     special > 0 ifTrue: [printer _ MacroPrinters at: special].
  32355.     (printer == #printCaseOn:indent:) ifTrue: 
  32356.         [^self printCaseOn: aStream indent: level].
  32357.     receiver == nil 
  32358.         ifFalse: [receiver printOn: aStream indent: level precedence: precedence].
  32359.     (special > 0)
  32360.         ifTrue: 
  32361.             [self perform: printer with: aStream with: level]
  32362.         ifFalse: 
  32363.             [self 
  32364.                 printKeywords: selector key
  32365.                 arguments: arguments
  32366.                 on: aStream
  32367.                 indent: level]!
  32368. printOn: strm indent: level precedence: p
  32369.  
  32370.     | parenthesize |
  32371.     parenthesize _ 
  32372.         precedence > p or: [p = 3 and: [precedence = 3 "both keywords"]].
  32373.     parenthesize ifTrue: [strm nextPutAll: '('].
  32374.     self printOn: strm indent: level.
  32375.     parenthesize ifTrue: [strm nextPutAll: ')']!
  32376. printToDoOn: aStream indent: level
  32377.     (selector key = #to:by:do:
  32378.             and: [(arguments at: 2) isConstantNumber
  32379.                 and: [(arguments at: 2) key = 1]])
  32380.         ifTrue: [self printKeywords: #to:do:
  32381.                     arguments: (Array with: arguments first with: arguments last)
  32382.                     on: aStream indent: level]
  32383.         ifFalse: [self printKeywords: selector key
  32384.                     arguments: arguments
  32385.                     on: aStream indent: level]!
  32386. printWhileOn: aStream indent: level
  32387.     (arguments first isJust: NodeNil) ifTrue:
  32388.             [selector _ SelectorNode new
  32389.                     key: (selector key == #whileTrue:
  32390.                         ifTrue: [#whileTrue] ifFalse: [#whileFalse])
  32391.                     code: #macro.
  32392.             arguments _ Array new].
  32393.     ^ self 
  32394.         printKeywords: selector key
  32395.         arguments: arguments
  32396.         on: aStream
  32397.         indent: level! !
  32398.  
  32399. !MessageNode methodsFor: 'private'!
  32400. checkBlock: node as: nodeName from: encoder
  32401.  
  32402.     node canBeSpecialArgument ifTrue: [^node isMemberOf: BlockNode].
  32403.     ((node isKindOf: BlockNode) and: [node numberOfArguments > 0])
  32404.         ifTrue:    [^encoder notify: '<- ', nodeName , ' of ' ,
  32405.                     (MacroSelectors at: special) , ' must be 0-argument block']
  32406.         ifFalse: [^encoder notify: '<- ', nodeName , ' of ' ,
  32407.                     (MacroSelectors at: special) , ' must be a block or variable']!
  32408. pvtCheckForPvtSelector: encoder
  32409.     "If the code being compiled is trying to send a private message (e.g. 'pvtCheckForPvtSelector:') to anyone other than self, then complain to encoder."
  32410.  
  32411.     selector isPvtSelector ifTrue:
  32412.         [receiver isSelfPsuedoVariable ifFalse:
  32413.             [encoder notify: 'Private messages may only be sent to self']].!
  32414. receiver: rcvr arguments: args precedence: p
  32415.  
  32416.     receiver _ rcvr.
  32417.     arguments _ args.
  32418.     sizes _ Array new: arguments size.
  32419.     precedence _ p!
  32420. transformAs: encoder
  32421.  
  32422.     (receiver isKindOf: BraceNode)
  32423.         ifTrue: 
  32424.             [receiver collClass: arguments first.
  32425.             ^true]
  32426.         ifFalse: 
  32427.             [^false]!
  32428. transformCase: encoder
  32429.  
  32430.     | caseNode |
  32431.     caseNode _ arguments first.
  32432.     (caseNode isKindOf: BraceNode)
  32433.         ifTrue:
  32434.             [^(caseNode blockAssociationCheck: encoder) and:
  32435.                  [arguments size = 1 or:
  32436.                     [self checkBlock: arguments last as: 'otherwise arg' from: encoder]]].
  32437.     (caseNode canBeSpecialArgument and: [(caseNode isMemberOf: BlockNode) not])
  32438.         ifTrue:
  32439.             [^false]. "caseOf: variable"
  32440.     ^encoder notify: 'caseOf: argument must be a brace construct or a variable'! !
  32441.  
  32442. !MessageNode methodsFor: 'equation translation'!
  32443. arguments
  32444.     ^arguments!
  32445. collectVariables
  32446.     ^arguments inject: receiver collectVariables into: [:array :argument | array, argument collectVariables]!
  32447. copyReplacingVariables: varDict
  32448.     | t1 t2 t3 |  
  32449.     t1 _ receiver copyReplacingVariables: varDict.
  32450.     t2 _ selector copyReplacingVariables: varDict.
  32451.     t3 _ arguments collect: [:a | a copyReplacingVariables: varDict].
  32452.     ^self class new receiver: t1 selector: t2 arguments: t3 precedence: precedence!
  32453. receiver
  32454.     ^receiver!
  32455. receiver: val
  32456.     ^receiver _ val!
  32457. selector
  32458.     ^selector!
  32459. specificMatch: aTree using: matchDict 
  32460.     (receiver match: aTree receiver using: matchDict)
  32461.         ifFalse: [^false].
  32462.     (selector match: aTree selector using: matchDict)
  32463.         ifFalse: [^false].
  32464.     arguments with: aTree arguments do: [:a1 :a2 |
  32465.         (a1 match: a2 using: matchDict)
  32466.             ifFalse: [^false]].
  32467.     ^true! !
  32468.  
  32469. !MessageNode methodsFor: 'C translation'! !
  32470. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  32471.  
  32472. MessageNode class
  32473.     instanceVariableNames: ''!
  32474.  
  32475. !MessageNode class methodsFor: 'class initialization'!
  32476. initialize        "MessageNode initialize"
  32477.     MacroSelectors _ 
  32478.         #(ifTrue: ifFalse: ifTrue:ifFalse: ifFalse:ifTrue:
  32479.             and: or:
  32480.             whileFalse: whileTrue: whileFalse whileTrue
  32481.             to:do: to:by:do:
  32482.             caseOf: caseOf:otherwise: as: ).
  32483.     MacroTransformers _ 
  32484.         #(transformIfTrue: transformIfFalse: transformIfTrueIfFalse: transformIfFalseIfTrue:
  32485.             transformAnd: transformOr:
  32486.             transformWhile: transformWhile: transformWhile: transformWhile:
  32487.             transformToDo: transformToDo:
  32488.             transformCase: transformCase: transformAs: ).
  32489.     MacroEmitters _ 
  32490.         #(emitIf:on:value: emitIf:on:value: emitIf:on:value: emitIf:on:value:
  32491.             emitIf:on:value: emitIf:on:value:
  32492.             emitWhile:on:value: emitWhile:on:value: emitWhile:on:value: emitWhile:on:value:
  32493.             emitToDo:on:value: emitToDo:on:value:
  32494.             emitCase:on:value: emitCase:on:value: emitAs:on:value: ).
  32495.     MacroSizers _ 
  32496.         #(sizeIf:value: sizeIf:value: sizeIf:value: sizeIf:value:
  32497.             sizeIf:value: sizeIf:value:
  32498.             sizeWhile:value: sizeWhile:value: sizeWhile:value: sizeWhile:value:
  32499.             sizeToDo:value: sizeToDo:value:
  32500.             sizeCase:value: sizeCase:value: sizeAs:value: ).
  32501.     MacroPrinters _ 
  32502.         #(printIfOn:indent: printIfOn:indent: printIfOn:indent: printIfOn:indent:
  32503.             printIfOn:indent: printIfOn:indent:
  32504.             printWhileOn:indent: printWhileOn:indent: printWhileOn:indent: printWhileOn:indent:
  32505.             printToDoOn:indent: printToDoOn:indent:
  32506.             printCase:indent: printCase:indent: printAs:indent: )! !
  32507.  
  32508. MessageNode initialize!
  32509. Browser subclass: #MessageSet
  32510.     instanceVariableNames: 'messageList autoSelectString '
  32511.     classVariableNames: ''
  32512.     poolDictionaries: ''
  32513.     category: 'Interface-Browser'!
  32514. MessageSet comment:
  32515. 'I represent a query path of the retrieval result of making a query about methods in the system. The result is a set of methods, denoted by a message selector and the class in which the method was found. As a StringHolder, the string I represent is the source code of the currently selected method. I am typically viewed in a Message Set Browser consisting of a MessageListView and a BrowserCodeView.'!
  32516.  
  32517. !MessageSet methodsFor: 'message list'!
  32518. messageList
  32519.     "Answer the current list of messages."
  32520.  
  32521.     ^messageList!
  32522. messageListIndex: anInteger 
  32523.     "Set the index of the selected item to be anInteger."
  32524.  
  32525.     messageListIndex _ anInteger.
  32526.     contents _ 
  32527.         messageListIndex ~= 0
  32528.             ifTrue: [self selectedMessage]
  32529.             ifFalse: [''].
  32530.     self changed: #messageSelectionChanged.
  32531.     (messageListIndex ~= 0 and: [autoSelectString notNil])
  32532.         ifTrue: [self changed: #autoSelect]!
  32533. selectedMessage
  32534.     "Answer the source method for the currently selected message."
  32535.     self setClassAndSelectorIn:
  32536.             [:class :selector | ^ class sourceMethodAt: selector]!
  32537. selectedMessageName
  32538.     "Answer the name of the currently selected message."
  32539.     self setClassAndSelectorIn: [:class :selector | ^ selector]! !
  32540.  
  32541. !MessageSet methodsFor: 'message functions'!
  32542. removeMessage
  32543.     "Remove the selected message from the system. 1/15/96 sw"
  32544.  
  32545.     | message messageName confirmation |
  32546.  
  32547.     messageListIndex = 0 ifTrue: [^ self].
  32548.     self okToChange ifFalse: [^ self].
  32549.     messageName _ self selectedMessageName.
  32550.     confirmation _ self selectedClassOrMetaClass confirmRemovalOf: messageName.
  32551.     confirmation == 3 ifTrue: [^ self].
  32552.  
  32553.     self selectedClassOrMetaClass removeSelector: messageName.
  32554.     self initializeMessageList: (messageList copyWithout: self selection).
  32555.     self messageListIndex: 0.
  32556.     self changed: #messageListChanged.
  32557.  
  32558.     confirmation == 2 ifTrue:
  32559.         [Smalltalk sendersOf: messageName]!
  32560. removeMessageFromBrowser
  32561.     "Remove the selected message from the browser."
  32562.     messageListIndex = 0 ifTrue: [^ self].
  32563.     self initializeMessageList: (messageList copyWithout: self selection).
  32564.     self messageListIndex: 0.
  32565.     self changed: #messageListChanged!
  32566. spawn: aString 
  32567.     "Create and schedule a message browser with the edited, but not yet 
  32568.     accepted, code (aString) displayed in the text view part of the browser."
  32569.  
  32570.     ^self buildMessageBrowserEditString: aString! !
  32571.  
  32572. !MessageSet methodsFor: 'class list'!
  32573. metaClassIndicated
  32574.     "Answer the boolean flag that indicates whether
  32575.     this is a class method."
  32576.  
  32577.     ^ self selectedClassOrMetaClass isMeta!
  32578. selectedClass 
  32579.     "Return the base class for the current selection.  1/17/96 sw fixed up so that it doesn't fall into a debugger in a msg browser that has no message selected"
  32580.  
  32581.     | aClass |
  32582.     ^ (aClass _ self selectedClassOrMetaClass) == nil
  32583.         ifTrue:
  32584.             [nil]
  32585.         ifFalse:
  32586.             [aClass theNonMetaClass]!
  32587. selectedClassOrMetaClass
  32588.     "Answer the currently selected class (or metaclass)."
  32589.     messageListIndex = 0 ifTrue: [^nil].
  32590.     self setClassAndSelectorIn: [:c :s | ^c]!
  32591. selectedMessageCategoryName 
  32592.     "Answer the name of the selected message category or nil."
  32593.     messageListIndex = 0 ifTrue: [^ nil].
  32594.     ^ self selectedClassOrMetaClass organization categoryOfElement: self selectedMessageName! !
  32595.  
  32596. !MessageSet methodsFor: 'contents'!
  32597. contents
  32598.     contents == nil
  32599.         ifTrue: [^ '']
  32600.         ifFalse: [^ contents]!
  32601. contents: aString notifying: aController 
  32602.     "Compile the code in aString. Notify aController of any syntax errors. 
  32603.     Create an error if the category of the selected message is unknown. 
  32604.     Answer false if the compilation fails. Otherwise, if the compilation 
  32605.     created a new method, deselect the current selection. Then answer true."
  32606.     | category selector class oldSelector notice |
  32607.     messageListIndex = 0 ifTrue: [^ false].
  32608.     self setClassAndSelectorIn: [:class :oldSelector].
  32609.     category _ class organization categoryOfElement: oldSelector.
  32610.     selector _ class
  32611.                 compile: aString
  32612.                 classified: category
  32613.                 notifying: aController.
  32614.     selector == nil ifTrue: [^false].
  32615.     selector == oldSelector ifFalse: [self messageListIndex: 0].
  32616.     notice _ class checkForPerform: selector in: aController.
  32617.     notice size = 0 ifFalse: ["insert the notice"
  32618.             aController notify: notice
  32619.                 at: contents size + 1
  32620.                 in: nil.
  32621.             self lock  "code is dirty"].
  32622.     ^true! !
  32623.  
  32624. !MessageSet methodsFor: 'private'!
  32625. autoSelectString
  32626.     "Return the string to be highlighted when making new selections"
  32627.     ^ autoSelectString!
  32628. autoSelectString: aString
  32629.     "Set the string to be highlighted when making new selections"
  32630.     autoSelectString _ aString!
  32631. defaultBackgroundColor
  32632.     ^ #lightBlue!
  32633. initializeMessageList: anArray
  32634.     messageList _ anArray.
  32635.     messageListIndex _ 0.
  32636.     contents _ ''!
  32637. selection
  32638.     "Answer the item in the list that is currently selected."
  32639.  
  32640.     ^messageList at: messageListIndex!
  32641. setClassAndSelectorIn: csBlock
  32642.     "Decode strings of the form <className> [class] <selectorName>."
  32643.     ^ MessageSet parse: self selection toClassAndSelector: csBlock! !
  32644. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  32645.  
  32646. MessageSet class
  32647.     instanceVariableNames: ''!
  32648.  
  32649. !MessageSet class methodsFor: 'instance creation'!
  32650. messageList: anArray 
  32651.     "Answer an instance of me with message list anArray."
  32652.  
  32653.     ^self new initializeMessageList: anArray!
  32654. open: aMessageSet name: aString 
  32655.     "Create a standard system view for the messageSet, aMessageSet, whose label is aString."
  32656.  
  32657.     | topView aListView aBrowserCodeView |
  32658.     topView _ StandardSystemView new.
  32659.     topView model: aMessageSet.
  32660.     topView label: aString.
  32661.     topView minimumSize: 180 @ 120.
  32662.     aListView _ MessageListView new.
  32663.     aListView model: aMessageSet.
  32664.     aListView list: aMessageSet messageList.
  32665.     aListView window: (0 @ 0 extent: 180 @ 100).
  32666.     aListView
  32667.         borderWidthLeft: 2
  32668.         right: 2
  32669.         top: 2
  32670.         bottom: 0.
  32671.     topView addSubView: aListView.
  32672.     aBrowserCodeView _ BrowserCodeView new.
  32673.     aBrowserCodeView model: aMessageSet.
  32674.     aBrowserCodeView window: (0 @ 0 extent: 180 @ 300).
  32675.     aBrowserCodeView
  32676.         borderWidthLeft: 2
  32677.         right: 2
  32678.         top: 2
  32679.         bottom: 2.
  32680.     topView
  32681.         addSubView: aBrowserCodeView
  32682.         align: aBrowserCodeView viewport topLeft
  32683.         with: aListView viewport bottomLeft.
  32684.     topView controller open!
  32685. openMessageList: anArray name: aString 
  32686.     "Create a standard system view for the message set on the list, anArray. 
  32687.     The label of the view is aString."
  32688.  
  32689.     self open: (self messageList: anArray) name: aString!
  32690. openMessageList: messageList name: labelString autoSelect: autoSelectString
  32691.     "Open a system view for a MessageSet on messageList. 
  32692.      1/24/96 sw: the there-are-no msg now supplied by my sender"
  32693.  
  32694.     | messageSet |
  32695.  
  32696.     messageSet _ self messageList: messageList.
  32697.     messageSet autoSelectString: autoSelectString.
  32698.     ScheduledControllers scheduleActive: 
  32699.                     (self open: messageSet name: labelString)!
  32700. parse: messageString toClassAndSelector: csBlock
  32701.     "Decode strings of the form <className> [class] <selectorName>."
  32702.     | tuple cl |
  32703.     tuple _ messageString findTokens: ' '.
  32704.     cl _ Smalltalk at: tuple first asSymbol.
  32705.     tuple size = 2
  32706.         ifTrue: [^ csBlock value: cl value: tuple last asSymbol]
  32707.         ifFalse: [^ csBlock value: cl class value: tuple last asSymbol]! !Magnitude subclass: #MessageTally
  32708.     instanceVariableNames: 'class method tally receivers senders '
  32709.     classVariableNames: 'ObservedProcess Timer '
  32710.     poolDictionaries: ''
  32711.     category: 'System-Support'!
  32712. MessageTally comment:
  32713. 'My instances observe and report the amount of time spent in methods. Observing a method implies observing all messages it sends.'!
  32714.  
  32715. !MessageTally methodsFor: 'initialize-release'!
  32716. close
  32717.  
  32718.     (Timer isMemberOf: Process) ifTrue: [Timer terminate].
  32719.     Timer _ ObservedProcess _ nil.
  32720.     class _ method _ tally _ receivers _ nil!
  32721. spyEvery: millisecs on: aBlock 
  32722.     "Create a spy and spy on the given block at the specified rate."
  32723.  
  32724.     | myDelay value |
  32725.     (aBlock isMemberOf: BlockContext)
  32726.         ifFalse: [self error: 'spy needs a block here'].
  32727.     self class: aBlock receiver class method: aBlock method.
  32728.         "set up the probe"
  32729.     ObservedProcess _ Processor activeProcess.
  32730.     myDelay _ Delay forMilliseconds: millisecs.
  32731.     Timer _
  32732.         [[true] whileTrue: 
  32733.             [myDelay wait.
  32734.             self tally: ObservedProcess suspendedContext].
  32735.         nil] newProcess.
  32736.     Timer priority: Processor userInterruptPriority.
  32737.         "activate the probe and evaluate the block"
  32738.     Timer resume.
  32739.     value _ aBlock value.
  32740.         "cancel the probe and return the value"
  32741.     Timer terminate.
  32742.     ^value! !
  32743.  
  32744. !MessageTally methodsFor: 'comparing'!
  32745. < aMessageTally 
  32746.     "Refer to the comment in Magnitude|<."
  32747.  
  32748.     ^tally > aMessageTally tally!
  32749. = aMessageTally
  32750.  
  32751.     ^aMessageTally method == method!
  32752. > aMessageTally 
  32753.     "Refer to the comment in Magnitude|>."
  32754.  
  32755.     ^tally < aMessageTally tally!
  32756. hash
  32757.     "Hash is reimplemented because = is implemented."
  32758.  
  32759.     ^method asOop!
  32760. isPrimitives
  32761.     "Detect pseudo node used to carry tally of local hits"
  32762.     ^ receivers == nil!
  32763. sonsOver: threshold
  32764.  
  32765.     | hereTally last sons |
  32766.     (receivers == nil or: [receivers size = 0]) ifTrue: [^#()].
  32767.     hereTally _ tally.
  32768.     sons _ receivers select:  "subtract subNode tallies for primitive hits here"
  32769.         [:son |
  32770.         hereTally _ hereTally - son tally.
  32771.         son tally > threshold].
  32772.     hereTally > threshold
  32773.         ifTrue: 
  32774.             [last _ MessageTally new class: class method: method.
  32775.             ^sons copyWith: (last primitives: hereTally)].
  32776.     ^sons! !
  32777.  
  32778. !MessageTally methodsFor: 'tallying'!
  32779. bump
  32780.  
  32781.     tally _ tally + 1!
  32782. tally: context 
  32783.     "Explicitly tally the specified context and its stack."
  32784.     | root |
  32785.     context method == method ifTrue: [^self bump].
  32786.     (root _ context home sender) == nil ifTrue: [^self bump tallyPath: context].
  32787.     ^(self tally: root) tallyPath: context!
  32788. tallyPath: context
  32789.  
  32790.     | aMethod path |
  32791.     aMethod _ context method.
  32792.     receivers do: 
  32793.         [:aMessageTally | 
  32794.         aMessageTally method == aMethod ifTrue: [path _ aMessageTally]].
  32795.     path == nil
  32796.         ifTrue: 
  32797.             [path _ MessageTally new class: context receiver class method: aMethod.
  32798.             receivers _ receivers copyWith: path].
  32799.     ^path bump! !
  32800.  
  32801. !MessageTally methodsFor: 'collecting leaves'!
  32802. bump: hitCount
  32803.     tally _ tally + hitCount!
  32804. bump: hitCount fromSender: senderTally
  32805.     "Add this hitCount to the total, and include a reference to the
  32806.     sender responsible for the increment"
  32807.     self bump: hitCount.
  32808.     senders == nil ifTrue: [senders _ OrderedCollection new].
  32809.     senderTally == nil
  32810.         ifFalse: [senders add: (senderTally copyWithTally: hitCount)]!
  32811. into: leafDict fromSender: senderTally
  32812.     | leafNode |
  32813.     leafNode _ leafDict at: method
  32814.         ifAbsent: [leafDict at: method
  32815.             put: (MessageTally new class: class method: method)].
  32816.     leafNode bump: tally fromSender: senderTally!
  32817. leavesInto: leafDict fromSender: senderTally
  32818.     | rcvrs |
  32819.     rcvrs _ self sonsOver: 0.
  32820.     rcvrs size = 0
  32821.         ifTrue: [self into: leafDict fromSender: senderTally]
  32822.         ifFalse: [rcvrs do:
  32823.                 [:node |
  32824.                 node isPrimitives
  32825.                     ifTrue: [node leavesInto: leafDict fromSender: senderTally]
  32826.                     ifFalse: [node leavesInto: leafDict fromSender: self]]]! !
  32827.  
  32828. !MessageTally methodsFor: 'reporting'!
  32829. report: strm 
  32830.     "Print a report, with cutoff percentage of each element of the tree 
  32831.     (leaves, roots, tree)=2, on the stream, strm."
  32832.  
  32833.     self report: strm cutoff: 2!
  32834. report: strm cutoff: threshold 
  32835.     tally = 0
  32836.         ifTrue: [strm nextPutAll: ' - no tallies obtained']
  32837.         ifFalse: 
  32838.             [strm nextPutAll: ' - '; print: tally; nextPutAll: ' tallies.'; cr; cr.
  32839.             self fullPrintOn: strm tallyExact: false orThreshold: threshold]! !
  32840.  
  32841. !MessageTally methodsFor: 'printing'!
  32842. fullPrintOn: aStream tallyExact: isExact orThreshold: perCent
  32843.     | threshold |  
  32844.     isExact ifFalse: [threshold _ (perCent asFloat / 100 * tally) rounded].
  32845.     aStream nextPutAll: '**Tree**'; cr.
  32846.     self treePrintOn: aStream
  32847.         tabs: OrderedCollection new
  32848.         thisTab: ''
  32849.         total: tally
  32850.         tallyExact: isExact
  32851.         orThreshold: threshold.
  32852.     aStream nextPut: Character newPage; cr.
  32853.     aStream nextPutAll: '**Leaves**'; cr.
  32854.     self leavesPrintOn: aStream
  32855.         tallyExact: isExact
  32856.         orThreshold: threshold!
  32857. leavesPrintOn: aStream tallyExact: isExact orThreshold: threshold
  32858.     | dict |
  32859.     dict _ IdentityDictionary new: 100.
  32860.     self leavesInto: dict fromSender: nil.
  32861.     isExact ifTrue: 
  32862.         [dict asSortedCollection
  32863.             do: [:node |
  32864.                 node printOn: aStream total: tally tallyExact: isExact.
  32865.                 node printSenderCountsOn: aStream]]
  32866.         ifFalse:
  32867.         [(dict asOrderedCollection
  32868.                 select: [:node | node tally > threshold])
  32869.             asSortedCollection
  32870.             do: [:node |
  32871.                 node printOn: aStream total: tally tallyExact: isExact]]!
  32872. printOn: aStream
  32873.     | aSelector className |
  32874.     aSelector _ class selectorAtMethod: method setClass: [:aClass].
  32875.     className _ aClass name contractTo: 30.
  32876.     aStream nextPutAll: className; nextPutAll: ' >> ';
  32877.             nextPutAll: (aSelector contractTo: 60-className size)!
  32878. printOn: aStream total: total tallyExact: isExact
  32879.     | aSelector aClass className myTally |
  32880.     isExact ifTrue:
  32881.         [myTally _ tally.
  32882.         receivers == nil
  32883.             ifFalse: [receivers do: [:r | myTally _ myTally - r tally]].
  32884.         aStream print: myTally; space]
  32885.         ifFalse:
  32886.         [aStream print: (tally asFloat / total * 100.0 roundTo: 0.1); space].
  32887.     receivers == nil
  32888.         ifTrue: [aStream nextPutAll: 'primitives'; cr]
  32889.         ifFalse: 
  32890.             [aSelector _ class selectorAtMethod: method setClass: [:aClass].
  32891.             className _ aClass name contractTo: 30.
  32892.             aStream nextPutAll: className; space;
  32893.                 nextPutAll: (aSelector contractTo: 60-className size); cr]!
  32894. printSenderCountsOn: aStream
  32895.     | mergedSenders mergedNode |
  32896.     mergedSenders _ IdentityDictionary new.
  32897.     senders do:
  32898.         [:node |
  32899.         mergedNode _ mergedSenders at: node method ifAbsent: [nil].
  32900.         mergedNode == nil
  32901.             ifTrue: [mergedSenders at: node method put: node]
  32902.             ifFalse: [mergedNode bump: node tally]].
  32903.     mergedSenders asSortedCollection do:
  32904.         [:node | 
  32905.         10 to: node tally printString size by: -1 do: [:i | aStream space].
  32906.         node printOn: aStream total: tally tallyExact: true]!
  32907. treePrintOn: aStream tabs: tabs thisTab: myTab
  32908.     total: total tallyExact: isExact orThreshold: threshold
  32909.     | sons sonTab |
  32910.     tabs do: [:tab | aStream nextPutAll: tab].
  32911.     tabs size > 0 ifTrue: [self printOn: aStream total: total tallyExact: isExact].
  32912.     sons _ isExact
  32913.         ifTrue: [receivers]
  32914.         ifFalse: [self sonsOver: threshold].
  32915.     sons isEmpty ifFalse:
  32916.         [tabs addLast: myTab.
  32917.         sons _ sons asSortedCollection.
  32918.         (1 to: sons size) do: 
  32919.             [:i |
  32920.             sonTab _ i < sons size ifTrue: ['  |'] ifFalse: ['  '].
  32921.             (sons at: i) treePrintOn: aStream
  32922.                 tabs: (tabs size < 18
  32923.                     ifTrue: [tabs]
  32924.                     ifFalse: [(tabs select: [:x | x = '[']) copyWith: '['])
  32925.                 thisTab: sonTab total: total
  32926.                 tallyExact: isExact orThreshold: threshold].
  32927.         tabs removeLast]! !
  32928.  
  32929. !MessageTally methodsFor: 'private'!
  32930. class: aClass method: aMethod
  32931.  
  32932.     class _ aClass.
  32933.     method _ aMethod.
  32934.     tally _ 0.
  32935.     receivers _ Array new: 0!
  32936. copyWithTally: hitCount
  32937.     ^ (MessageTally new class: class method: method) bump: hitCount!
  32938. method
  32939.  
  32940.     ^method!
  32941. primitives: anInteger
  32942.  
  32943.     tally _ anInteger.
  32944.     receivers _ nil!
  32945. tally
  32946.  
  32947.     ^tally! !
  32948. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  32949.  
  32950. MessageTally class
  32951.     instanceVariableNames: ''!
  32952.  
  32953. !MessageTally class methodsFor: 'spying'!
  32954. spyOn: aBlock    "MessageTally spyOn: [100 timesRepeat: [3.14159 printString]]"
  32955.     | node |
  32956.     node _ self new.
  32957.     node spyEvery: 16 on: aBlock.
  32958.     StringHolderView open: (StringHolder new contents:
  32959.                 (String streamContents: [:s | node report: s; close]))
  32960.         label: 'Spy Results'!
  32961. spyOn: aBlock toFileNamed: fileName 
  32962.     "Spy on the evaluation of aBlock. Write the data collected on a file
  32963.     named fileName."
  32964.  
  32965.     | file value node |
  32966.     node _ self new.
  32967.     value _ node spyEvery: 16 on: aBlock.
  32968.     file _ FileStream newFileNamed: fileName.
  32969.     node report: file; close.
  32970.     file close.
  32971.     ^value!
  32972. tallySends: aBlock   "MessageTally tallySends: [3.14159 printString]"
  32973.     ^ self tallySendsTo: nil inBlock: aBlock showTree: true!
  32974. tallySendsTo: receiver inBlock: aBlock showTree: treeOption
  32975.     "MessageTally tallySends: [3.14159 printString]"
  32976.     "This method uses the simulator to count the number of calls on each method
  32977.     invoked in evaluating aBlock. If receiver is not nil, then only sends
  32978.     to that receiver are tallied.
  32979.     Results are presented as leaves, sorted by frequency,
  32980.     preceded, optionally, by the whole tree."
  32981.     | prev current tallies |
  32982.     tallies _ MessageTally new class: aBlock receiver class
  32983.                             method: aBlock method.
  32984.     prev _ aBlock.
  32985.     thisContext sender
  32986.         runSimulated: aBlock
  32987.         contextAtEachStep:
  32988.             [:current |
  32989.             current == prev ifFalse: 
  32990.                 ["call or return"
  32991.                 prev sender == nil ifFalse: 
  32992.                     ["call only"
  32993.                     (receiver == nil or: [current receiver == receiver])
  32994.                         ifTrue: [tallies tally: current]].
  32995.                 prev _ current]].
  32996.  
  32997.     StringHolderView open: (StringHolder new contents:
  32998.         (String streamContents:
  32999.             [:s |
  33000.             treeOption
  33001.                 ifTrue: [tallies fullPrintOn: s tallyExact: true orThreshold: 0]
  33002.                 ifFalse: [tallies leavesPrintOn: s tallyExact: true orThreshold: 0].
  33003.             tallies close]))
  33004.         label: 'Spy Results'! !ClassDescription subclass: #Metaclass
  33005.     instanceVariableNames: 'thisClass '
  33006.     classVariableNames: ''
  33007.     poolDictionaries: ''
  33008.     category: 'Kernel-Classes'!
  33009. Metaclass comment:
  33010. 'My instances add instance-specific behavior to various class-describing objects in the system. This typically includes messages for initializing class variables and instance creation messages particular to a class. There is only one instance of a particular Metaclass, namely the class which is being described. A Metaclass shares the class variables of its instance.
  33011.     
  33012. [Subtle] In general, the superclass hierarchy for metaclasses parallels that for classes. Thus,
  33013.     Integer superclass == Number, and
  33014.     Integer class superclass == Number class.
  33015. However there is a singularity at Object. Here the class hierarchy terminates, but the metaclass hierarchy must wrap around to Class, since ALL metaclasses are subclasses of Class. Thus,
  33016.     Object superclass == nil, and
  33017.     Object class superclass == Class.'!
  33018.  
  33019. !Metaclass methodsFor: 'initialize-release'!
  33020. instanceVariableNames: instVarString 
  33021.     "Declare additional named variables for my instance."
  33022.     | newMeta invalid ok |
  33023.     newMeta _ self copyForValidation.
  33024.     invalid _ newMeta
  33025.                 subclassOf: superclass
  33026.                 oldClass: self
  33027.                 instanceVariableNames: instVarString
  33028.                 variable: false
  33029.                 words: true
  33030.                 pointers: true
  33031.                 ifBad: [^false].
  33032.     (invalid  "But since invalid doesn't get set by adding instVars..."
  33033.         or: [instVarString ~= self instanceVariablesString])
  33034.         ifTrue: [newMeta validateFrom: self
  33035.                     in: Smalltalk
  33036.                     instanceVariableNames: true
  33037.                     methods: true.
  33038.                 Smalltalk changes changeClass: self]!
  33039. newNamed: aSymbol 
  33040.     "Answer an instance of me whose name is the argument, aSymbol."
  33041.  
  33042.     ^(self class subclassOf: self) new
  33043.         superclass: Object
  33044.         methodDict: MethodDictionary new
  33045.         format: Object format
  33046.         name: aSymbol
  33047.         organization: (ClassOrganizer defaultList: Array new)
  33048.         instVarNames: nil
  33049.         classPool: nil
  33050.         sharedPools: nil!
  33051. subclassOf: superMeta 
  33052.     "Change the receiver to be a subclass of the argument, superMeta, a 
  33053.     metaclass. Reset the receiver's method dictionary and properties."
  33054.  
  33055.     superclass _ superMeta.
  33056.     methodDict _ MethodDictionary new.
  33057.     format _ superMeta format.
  33058.     instanceVariables _ nil!
  33059. superclass: superMeta 
  33060.     "Change the receiver's superclass to be the argument, superMeta, a 
  33061.     metaclass."
  33062.  
  33063.     superclass _ superMeta! !
  33064.  
  33065. !Metaclass methodsFor: 'accessing'!
  33066. isMeta
  33067.     ^ true!
  33068. name
  33069.     "Answer a String that is the name of the receiver, either 'Metaclass' or 
  33070.     the name of the receiver's class followed by ' class'."
  33071.  
  33072.     thisClass == nil
  33073.         ifTrue: [^'a Metaclass']
  33074.         ifFalse: [^thisClass name , ' class']!
  33075. soleInstance
  33076.     "The receiver has only one instance. Answer it."
  33077.  
  33078.     ^thisClass!
  33079. theNonMetaClass
  33080.     "Sent to a class or metaclass, always return the class"
  33081.  
  33082.     ^thisClass! !
  33083.  
  33084. !Metaclass methodsFor: 'copying'!
  33085. copy
  33086.     "Make a copy of the receiver without a list of subclasses. Share the 
  33087.     reference to the sole instance."
  33088.  
  33089.     | copy t |
  33090.     t _ thisClass.
  33091.     thisClass _ nil.
  33092.     copy _ super copy.
  33093.     thisClass _ t.
  33094.     ^copy!
  33095. copyForValidation
  33096.     "Special copy for ClassDescription| validateFrom:in:fields:methods:. Answer 
  33097.     a copy of the receiver without the subclasses."
  33098.  
  33099.     ^super copy! !
  33100.  
  33101. !Metaclass methodsFor: 'instance creation'!
  33102. new
  33103.     "The receiver can only have one instance. Create it or complain that
  33104.     one already exists."
  33105.  
  33106.     thisClass == nil
  33107.         ifTrue: [^thisClass _ super new]
  33108.         ifFalse: [self error: 'A Metaclass should only have one instance!!']! !
  33109.  
  33110. !Metaclass methodsFor: 'instance variables'!
  33111. addInstVarName: aString 
  33112.     "Add the argument, aString, as one of the receiver's instance variables."
  33113.  
  33114.     | fullString |
  33115.     fullString _ aString.
  33116.     self instVarNames do: [:aString2 | fullString _ aString2 , ' ' , fullString].
  33117.     self instanceVariableNames: fullString!
  33118. removeInstVarName: aString 
  33119.     "Remove the argument, aString, as one of the receiver's instance variables."
  33120.  
  33121.     | newArray newString |
  33122.     (self instVarNames includes: aString)
  33123.         ifFalse: [self error: aString , ' is not one of my instance variables'].
  33124.     newArray _ self instVarNames copyWithout: aString.
  33125.     newString _ ''.
  33126.     newArray do: [:aString2 | newString _ aString2 , ' ' , newString].
  33127.     self instanceVariableNames: newString! !
  33128.  
  33129. !Metaclass methodsFor: 'pool variables'!
  33130. classPool
  33131.     "Answer the dictionary of class variables."
  33132.  
  33133.     ^thisClass classPool! !
  33134.  
  33135. !Metaclass methodsFor: 'class hierarchy'!
  33136. name: newName inEnvironment: environ subclassOf: sup instanceVariableNames: instVarString variable: v words: w pointers: p classVariableNames: classVarString poolDictionaries: poolString category: categoryName comment: commentString changed: changed 
  33137.     "This is the standard initialization message for creating a new Metaclass. 
  33138.     Answer an instance of me from the information provided in the 
  33139.     arguments. Create an error notification if the name does not begin with 
  33140.     an uppercase letter or if a class of the same name already exists.
  33141.     1/22/96 sw: don't ever do addClass, always do changeClass"
  33142.  
  33143.     | wasPresent oldClass newClass invalidFields invalidMethods |
  33144.     newName first isUppercase
  33145.         ifFalse: 
  33146.             [self error: 'Class names must be capitalized'.
  33147.             ^false].
  33148.     (wasPresent _ environ includesKey: newName)
  33149.         ifTrue: 
  33150.             [oldClass _ environ at: newName.
  33151.             (oldClass isKindOf: Behavior)
  33152.                 ifFalse: 
  33153.                     [self error: newName , ' already exists!!  Proceed will store over it'.
  33154.                     wasPresent _ false.
  33155.                     oldClass _ self newNamed: newName]]
  33156.         ifFalse: [oldClass _ self newNamed: newName].
  33157.     newClass _ oldClass copy.
  33158.     invalidFields _ 
  33159.         changed | (newClass
  33160.                     subclassOf: sup
  33161.                     oldClass: oldClass
  33162.                     instanceVariableNames: instVarString
  33163.                     variable: v
  33164.                     words: w
  33165.                     pointers: p
  33166.                     ifBad: [^false]).
  33167.     invalidFields not & (oldClass instSize = newClass instSize)
  33168.         ifTrue: [newClass _ oldClass].
  33169.     invalidMethods _ invalidFields | (newClass declare: classVarString) | (newClass sharing: poolString).
  33170.     commentString == nil ifFalse: [newClass comment: commentString].
  33171.     (environ includesKey: newName)
  33172.         ifFalse: [environ declare: newName from: Undeclared].
  33173.     environ at: newName put: newClass.
  33174.     SystemOrganization classify: newClass name under: categoryName asSymbol.
  33175.     newClass
  33176.         validateFrom: oldClass
  33177.         in: environ
  33178.         instanceVariableNames: invalidFields
  33179.         methods: invalidMethods.
  33180.     "update subclass lists"
  33181.     newClass superclass removeSubclass: oldClass.
  33182.     newClass superclass addSubclass: newClass.
  33183.     "Update Changes"
  33184.     wasPresent | true
  33185.         ifTrue: [Smalltalk changes changeClass: newClass]
  33186.         ifFalse: [Smalltalk changes addClass: newClass].
  33187.     ^ newClass!
  33188. subclasses
  33189.     "Answer the receiver's subclasses."
  33190.  
  33191.     | temp |
  33192.     self == Class class 
  33193.         ifTrue: ["Meta-Object is exceptional subclass of Class"
  33194.                 temp _ thisClass subclasses copy.
  33195.                 temp remove: Object class.
  33196.                 ^temp collect: [:aSubClass | aSubClass class]].
  33197.     thisClass == nil
  33198.         ifTrue: [^Set new]
  33199.         ifFalse: [^thisClass subclasses collect: [:aSubClass | aSubClass class]]
  33200.  
  33201.     "Metaclass allInstancesDo:
  33202.         [:m | Compiler evaluate: 'subclasses_nil' for: m logged: false]"!
  33203. subclassesDo: aBlock
  33204.     "Evaluate aBlock for each of the receiver's immediate subclasses."
  33205.     self == Class class
  33206.         ifTrue: ["Don't include Object class class in Class class's subclasses (heh heh)"
  33207.                 thisClass subclassesDo: [:aSubclass | aSubclass == Object class
  33208.                                             ifFalse: [aBlock value: aSubclass class]]]
  33209.         ifFalse: [thisClass == nil
  33210.                 ifFalse: [thisClass subclassesDo: [:aSubclass | aBlock value: aSubclass class]]]! !
  33211.  
  33212. !Metaclass methodsFor: 'compiling'!
  33213. acceptsLoggingOfCompilation
  33214.     "Answer whether the receiver's method submisions and class defintions should be logged to the changes file and to the current change set.  The metaclass follows the rule of the class itself.  6/18/96 sw"
  33215.  
  33216.     ^ thisClass acceptsLoggingOfCompilation!
  33217. compile: code classified: heading notifying: requestor 
  33218.     "Make sure there is an organization before compiling."
  33219.  
  33220.     organization _ self organization.
  33221.     ^super
  33222.         compile: code
  33223.         classified: heading
  33224.         notifying: requestor!
  33225. possibleVariablesFor: misspelled continuedFrom: oldResults
  33226.  
  33227.     ^ thisClass possibleVariablesFor: misspelled continuedFrom: oldResults
  33228. !
  33229. scopeHas: name ifTrue: assocBlock 
  33230.  
  33231.     ^thisClass scopeHas: name ifTrue: assocBlock!
  33232. wantsChangeSetLogging
  33233.     "Answer whether code submitted for the receiver should be remembered by the changeSet mechanism.The metaclass follows the rule of the class itself.  7/12/96 sw"
  33234.  
  33235.     ^ thisClass wantsChangeSetLogging! !
  33236.  
  33237. !Metaclass methodsFor: 'fileIn/Out'!
  33238. definition 
  33239.     "Refer to the comment in ClassDescription|definition."
  33240.  
  33241.     | aStream names |
  33242.     aStream _ WriteStream on: (String new: 300).
  33243.     self printOn: aStream.
  33244.     aStream nextPutAll: '
  33245.     instanceVariableNames: '''.
  33246.     names _ self instVarNames.
  33247.     1 to: names size do: [:i | aStream nextPutAll: (names at: i); space].
  33248.     aStream nextPut: $'.
  33249.     ^aStream contents!
  33250. fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex
  33251.     super fileOutOn: aFileStream
  33252.         moveSource: moveSource
  33253.         toFile: fileIndex.
  33254.     (methodDict includesKey: #initialize) ifTrue: 
  33255.         [aFileStream cr.
  33256.         aFileStream cr.
  33257.         aFileStream nextChunkPut: thisClass name , ' initialize'.
  33258.         aFileStream cr]!
  33259. nonTrivial 
  33260.     "Answer whether the receiver has any methods or instance variables."
  33261.  
  33262.     ^self instVarNames size > 0 or: [methodDict size > 0 or: [self comment size > 0]]! !
  33263. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  33264.  
  33265. Metaclass class
  33266.     instanceVariableNames: ''!
  33267.  
  33268. !Metaclass class methodsFor: 'instance creation'!
  33269. subclassOf: superMeta 
  33270.     "Answer an instance of me that is a subclass of the metaclass, superMeta."
  33271.  
  33272.     ^self new subclassOf: superMeta! !ContextPart variableSubclass: #MethodContext
  33273.     instanceVariableNames: 'method receiverMap receiver '
  33274.     classVariableNames: ''
  33275.     poolDictionaries: ''
  33276.     category: 'Kernel-Methods'!
  33277. MethodContext comment:
  33278. 'My instances hold all the dynamic state associated with the execution of a CompiledMethod. In addition to their inherited state, this includes the receiver, a method, and temporary space in the variable part of the context.
  33279.     
  33280. MethodContexts, though normal in their variable size, are actually only used in two sizes, small and large, which are determined by the temporary space required by the method being executed.'!
  33281.  
  33282. !MethodContext methodsFor: 'initialize-release'!
  33283. restart
  33284.     "Reinitialize the receiver so that it is in the state it was at its creation."
  33285.  
  33286.     pc _ method initialPC.
  33287.     stackp _ method numArgs + method numTemps!
  33288. restartWith: aCompiledMethod 
  33289.     "Reinitialize the receiver as though it had been for a different method. 
  33290.     Used by a Debugger when one of the methods to which it refers is 
  33291.     recompiled."
  33292.  
  33293.     method _ aCompiledMethod.
  33294.     ^self restart! !
  33295.  
  33296. !MethodContext methodsFor: 'accessing'!
  33297. home 
  33298.     "Refer to the comment in ContextPart|home."
  33299.  
  33300.     ^self!
  33301. method
  33302.  
  33303.     ^method!
  33304. receiver 
  33305.     "Refer to the comment in ContextPart|receiver."
  33306.  
  33307.     ^receiver!
  33308. removeSelf
  33309.     "Nil the receiver pointer and answer its former value."
  33310.  
  33311.     | tempSelf |
  33312.     tempSelf _ receiver.
  33313.     receiver _ nil.
  33314.     ^tempSelf!
  33315. tempAt: index 
  33316.     "Refer to the comment in ContextPart|tempAt:."
  33317.  
  33318.     ^self at: index!
  33319. tempAt: index put: value 
  33320.     "Refer to the comment in ContextPart|tempAt:put:."
  33321.  
  33322.     ^self at: index put: value! !
  33323.  
  33324. !MethodContext methodsFor: 'private'!
  33325. setSender: s receiver: r method: m arguments: args 
  33326.     "Create the receiver's initial state."
  33327.  
  33328.     sender _ s.
  33329.     receiver _ r.
  33330.     method _ m.
  33331.     pc _ method initialPC.
  33332.     stackp _ method numTemps.
  33333.     1 to: args size do: [:i | self at: i put: (args at: i)]! !
  33334. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  33335.  
  33336. MethodContext class
  33337.     instanceVariableNames: ''!
  33338.  
  33339. !MethodContext class methodsFor: 'instance creation'!
  33340. sender: s receiver: r method: m arguments: args 
  33341.     "Answer an instance of me with attributes set to the arguments."
  33342.  
  33343.     ^(self new: m frameSize) setSender: s receiver: r method: m arguments: args! !Dictionary variableSubclass: #MethodDictionary
  33344.     instanceVariableNames: ''
  33345.     classVariableNames: ''
  33346.     poolDictionaries: ''
  33347.     category: 'Kernel-Support'!
  33348.  
  33349. !MethodDictionary methodsFor: 'accessing'!
  33350. add: anAssociation
  33351.     ^ self at: anAssociation key put: anAssociation value!
  33352. at: key ifAbsent: aBlock
  33353.  
  33354.     | index |
  33355.     index _ self findElementOrNil: key.
  33356.     (self basicAt: index) == nil ifTrue: [ ^ aBlock value ].
  33357.     ^ array at: index!
  33358. at: key put: value
  33359.     "Set the value at key to be value."
  33360.     | index |
  33361.     index _ self findElementOrNil: key.
  33362.     (self basicAt: index) == nil
  33363.         ifTrue: 
  33364.             [tally _ tally + 1.
  33365.             self basicAt: index put: key].
  33366.     array at: index put: value.
  33367.     self fullCheck.
  33368.     ^ value!
  33369. includesKey: aSymbol
  33370.     "This override assumes that pointsTo is a fast primitive"
  33371.     ^ super pointsTo: aSymbol!
  33372. keyAtValue: value ifAbsent: exceptionBlock
  33373.     "Answer the key whose value equals the argument, value. If there is
  33374.     none, answer the result of evaluating exceptionBlock."
  33375.     | theKey |
  33376.     1 to: self basicSize do:
  33377.         [:index |
  33378.         value == (array at: index)
  33379.             ifTrue:
  33380.                 [(theKey _ self basicAt: index) == nil
  33381.                     ifFalse: [^ theKey]]].
  33382.     ^ exceptionBlock value! !
  33383.  
  33384. !MethodDictionary methodsFor: 'removing'!
  33385. removeKey: key ifAbsent: errorBlock 
  33386.     "The interpreter might be using this MethodDict while
  33387.     this method is running!!  Therefore we perform the removal
  33388.     in a copy, and then atomically become that copy"
  33389.     | copy |
  33390.     copy _ self copy.
  33391.     copy removeDangerouslyKey: key ifAbsent: [^ errorBlock value].
  33392.     self become: copy! !
  33393.  
  33394. !MethodDictionary methodsFor: 'enumeration'!
  33395. associationsDo: aBlock 
  33396.     | key |
  33397.     tally = 0 ifTrue: [^ self].
  33398.     1 to: self basicSize do:
  33399.         [:i | (key _ self basicAt: i) == nil ifFalse:
  33400.             [aBlock value: (Association key: key
  33401.                                     value: (array at: i))]]!
  33402. keysDo: aBlock 
  33403.     | key |
  33404.     tally = 0 ifTrue: [^ self].
  33405.     1 to: self basicSize do:
  33406.         [:i | (key _ self basicAt: i) == nil
  33407.             ifFalse: [aBlock value: key]]! !
  33408.  
  33409. !MethodDictionary methodsFor: 'private'!
  33410. grow 
  33411.     | newSelf key |
  33412.     newSelf _ self species new: self basicSize + self growSize.
  33413.     1 to: self basicSize do:
  33414.         [:i | key _ self basicAt: i.
  33415.         key == nil ifFalse: [newSelf at: key put: (array at: i)]].
  33416.     self become: newSelf!
  33417. keyAt: index
  33418.  
  33419.     ^ self basicAt: index!
  33420. methodArray
  33421.     ^ array!
  33422. removeDangerouslyKey: key ifAbsent: aBlock
  33423.     "This is not really dangerous.  But if normal removal
  33424.     were done WHILE a MethodDict were being used, the
  33425.     system might crash.  So instead we make a copy, then do
  33426.     this operation (which is NOT dangerous in a copy that is
  33427.     not being used), and then use the copy after the removal."
  33428.  
  33429.     | index element |
  33430.     index _ self findElementOrNil: key.
  33431.     (self basicAt: index) == nil ifTrue: [ ^ aBlock value ].
  33432.     element _ array at: index.
  33433.     array at: index put: nil.
  33434.     self basicAt: index put: nil.
  33435.     tally _ tally - 1.
  33436.     self fixCollisionsFrom: index.
  33437.     ^ element!
  33438. scanFor: key from: start to: finish
  33439.     "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches the key. Answer the index of that slot or zero if no slot is found within the given range of indices."
  33440.  
  33441.     | element |
  33442.     "this speeds up a common case: key is in the first slot"
  33443.     ((element _ self basicAt: start) == nil or: [element == key])
  33444.         ifTrue: [ ^ start ].
  33445.  
  33446.     start + 1 to: finish do: [ :index |
  33447.         ((element _ self basicAt: index) == nil or: [element == key])
  33448.             ifTrue: [ ^ index ].
  33449.     ].
  33450.     ^ 0
  33451. !
  33452. swap: oneIndex with: otherIndex
  33453.     | element |
  33454.     element _ self basicAt: oneIndex.
  33455.     self basicAt: oneIndex put: (self basicAt: otherIndex).
  33456.     self basicAt: otherIndex put: element.
  33457.     super swap: oneIndex with: otherIndex.
  33458. ! !
  33459. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  33460.  
  33461. MethodDictionary class
  33462.     instanceVariableNames: ''!
  33463.  
  33464. !MethodDictionary class methodsFor: 'instance creation'!
  33465. new: nElements
  33466.     "Create a Dictionary large enough to hold nElements without growing.
  33467.     Note that the basic size must be a power of 2."
  33468.     | size |
  33469.     size _ (self sizeFor: nElements).
  33470.     size isPowerOfTwo ifFalse:
  33471.         ["Size must be a power of 2..."
  33472.         size _ 1 bitShift: size highBit].
  33473.     size >= 1 ifFalse: [self error: 'size must be >= 1'].
  33474.     ^ (self basicNew: size) init: size! !ParseNode subclass: #MethodNode
  33475.     instanceVariableNames: 'selectorOrFalse precedence arguments block literals primitive encoder temporaries '
  33476.     classVariableNames: ''
  33477.     poolDictionaries: ''
  33478.     category: 'System-Compiler'!
  33479. MethodNode comment: 'I am the root of the parse tree.'!
  33480.  
  33481. !MethodNode methodsFor: 'initialize-release'!
  33482. selector: selOrFalse arguments: args precedence: p temporaries: temps block: blk encoder: anEncoder primitive: prim 
  33483.     "Initialize the receiver with respect to the arguments given."
  33484.  
  33485.     encoder _ anEncoder.
  33486.     selectorOrFalse _ selOrFalse.
  33487.     precedence _ p.
  33488.     arguments _ args.
  33489.     temporaries _ temps.
  33490.     block _ blk.
  33491.     primitive _ prim! !
  33492.  
  33493. !MethodNode methodsFor: 'code generation'!
  33494. encoder
  33495.     ^ encoder!
  33496. generate: trailer
  33497.     "The receiver is the root of a parse tree. Answer a CompiledMethod. The 
  33498.     argument, trailer, is the references to the source code that is stored with 
  33499.     every CompiledMethod."
  33500.     | blkSize method nLits lit stack strm nArgs i |
  33501.     self generateIfQuick: 
  33502.         [:method | 
  33503.         1 to: 3 do: [:i | method at: method size - 3 + i put: (trailer at: i)].
  33504.         method cacheTempNames: self tempNames.
  33505.         ^method].
  33506.     nArgs _ arguments size.
  33507.     blkSize _ block sizeForEvaluatedValue: encoder.
  33508.     encoder maxTemp > 31
  33509.         ifTrue: [^self error: 'Too many temporary variables'].    
  33510.     literals _ encoder allLiterals.
  33511.     (nLits _ literals size) > 63
  33512.         ifTrue: [^self error: 'Too many literals referenced'].
  33513.     method _ CompiledMethod    "Dummy to allocate right size"
  33514.                 newBytes: blkSize
  33515.                 nArgs: nArgs
  33516.                 nTemps: encoder maxTemp
  33517.                 nStack: 0
  33518.                 nLits: nLits
  33519.                 primitive: primitive.
  33520.     strm _ ReadWriteStream with: method.
  33521.     strm position: method initialPC - 1.
  33522.     stack _ ParseStack new init.
  33523.     block emitForEvaluatedValue: stack on: strm.
  33524.     stack position ~= 1 ifTrue: [^self error: 'Compiler stack discrepancy'].
  33525.     strm position ~= (method size - 3) 
  33526.         ifTrue: [^self error: 'Compiler code size discrepancy'].
  33527.     method needsFrameSize: stack size.
  33528.     1 to: nLits do: [:lit | method literalAt: lit put: (literals at: lit)].
  33529.     1 to: 3 do: [:i | method at: method size - 3 + i put: (trailer at: i)].
  33530.     method cacheTempNames: self tempNames.
  33531.     ^method!
  33532. generateIfQuick: methodBlock
  33533.     | v |
  33534.     (primitive = 0 and: [arguments size = 0 and: [block isQuick]])
  33535.         ifFalse: [^ self].
  33536.     v _ block code.
  33537.     v < 0
  33538.         ifTrue: [^ self].
  33539.     v = LdSelf
  33540.         ifTrue: [^ methodBlock value: CompiledMethod toReturnSelf].
  33541.     (v between: LdTrue and: LdMinus1 + 3)
  33542.         ifTrue: [^ methodBlock value: (CompiledMethod toReturnConstant: v - LdSelf)].
  33543.     v < ((CodeBases at: LdInstType) + (CodeLimits at: LdInstType))
  33544.         ifTrue: [^ methodBlock value: (CompiledMethod toReturnField: v)].
  33545.     v // 256 = 1
  33546.         ifTrue: [^ methodBlock value: (CompiledMethod toReturnField: v \\ 256)]!
  33547. selector 
  33548.     "Answer the message selector for the method represented by the receiver."
  33549.  
  33550.     (selectorOrFalse isMemberOf: Symbol)
  33551.         ifTrue: [^selectorOrFalse].
  33552.     ^selectorOrFalse key!
  33553. sourceMap
  33554.     "Answer a SortedCollection of associations of the form: pc (byte offset in 
  33555.     me) -> sourceRange (an Interval) in source text."
  33556.  
  33557.     self generate: #(0 0 0 ).
  33558.     ^encoder sourceMap! !
  33559.  
  33560. !MethodNode methodsFor: 'converting'!
  33561. decompileString
  33562.     "Answer a string description of the parse tree whose root is the receiver."
  33563.  
  33564.     | aStream |
  33565.     aStream _ WriteStream on: (String new: 1000).
  33566.     self printOn: aStream.
  33567.     ^aStream contents! !
  33568.  
  33569. !MethodNode methodsFor: 'printing'!
  33570. printOn: aStream
  33571.     | s args |
  33572.     precedence = 1
  33573.         ifTrue: 
  33574.             [aStream nextPutAll: self selector]
  33575.         ifFalse: 
  33576.             [args _ ReadStream on: arguments.
  33577.             self selector keywords with: arguments do: 
  33578.                 [:s :arg | 
  33579.                 aStream nextPutAll: s; space; nextPutAll: arg key; space]].
  33580.     aStream cr.
  33581.     comment == nil ifFalse: 
  33582.             [self printCommentOn: aStream indent: 0.
  33583.             aStream cr].
  33584.     temporaries isEmpty 
  33585.         ifTrue: [comment == nil ifFalse: [aStream cr]]
  33586.         ifFalse: [aStream tab; nextPutAll: '| '.
  33587.                 temporaries do: 
  33588.                     [:temp | aStream nextPutAll: temp key; space].
  33589.                 aStream nextPut: $|; cr].
  33590.     (primitive between: 1 and: 255) ifTrue:
  33591.             [self printPrimitiveOn: aStream.
  33592.             aStream cr].
  33593.     ^ block printStatementsOn: aStream indent: 0!
  33594. printPrimitiveOn: aStream
  33595.     aStream nextPutAll: '<primitive: '; print: primitive.
  33596.     aStream nextPutAll: '>'!
  33597. tempNames
  33598.     ^ encoder tempNames! !
  33599.  
  33600. !MethodNode methodsFor: 'equation translation'!
  33601. block
  33602.     ^block!
  33603. collectVariables
  33604.     ^block collectVariables!
  33605. copyReplacingVariables: varDict 
  33606.     | t1 t2 t3 |
  33607.     t1 _ selectorOrFalse copyReplacingVariables: varDict.
  33608.     t2 _ block copyReplacingVariables: varDict.
  33609.     t3 _ arguments collect: [:a | a copyReplacingVariables: varDict].
  33610.     ^self class new
  33611.         selector: t1
  33612.         arguments: t3
  33613.         precedence: precedence
  33614.         temporaries: temporaries copy
  33615.         block: t2
  33616.         encoder: encoder
  33617.         primitive: primitive!
  33618. specificMatch: aTree using: matchDict 
  33619.     ^self selector = aTree selector
  33620.         and: [arguments = aTree arguments
  33621.         and: [block match: aTree block using: matchDict]]! !
  33622.  
  33623. !MethodNode methodsFor: 'C translation'! !AbstractSound subclass: #MixedSound
  33624.     instanceVariableNames: 'sounds panSettings soundDone '
  33625.     classVariableNames: ''
  33626.     poolDictionaries: ''
  33627.     category: 'Sound'!
  33628.  
  33629. !MixedSound methodsFor: 'initialization'!
  33630. initialize
  33631.  
  33632.     sounds _ Array new.
  33633.     panSettings _ Array new.
  33634. ! !
  33635.  
  33636. !MixedSound methodsFor: 'sound generation'!
  33637. doControl
  33638.  
  33639.     1 to: sounds size do: [ :i |
  33640.         (sounds at: i) doControl.
  33641.     ].
  33642. !
  33643. mixSampleCount: n into: aByteArray startingAt: startIndex pan: pan
  33644.     "Play a number of sounds concurrently. Each sound can be panned independently between the left and right channels."
  33645.     "(AbstractSound bachFugueTwoVoices) play"
  33646.  
  33647.     | snd sndPan |
  33648.     1 to: sounds size do: [ :i |
  33649.         (soundDone at: i) ifFalse: [
  33650.             snd _ sounds at: i.
  33651.             pan = 1000
  33652.                 ifTrue: [ sndPan _ 1000 ]  "pan argument of 1000 means mono; pass that on"
  33653.                 ifFalse: [ sndPan _ panSettings at: i ].  "otherwise, use the pan for this voice"
  33654.             snd samplesRemaining > 0 ifTrue: [
  33655.                 snd mixSampleCount: n into: aByteArray startingAt: startIndex pan: sndPan.
  33656.             ] ifFalse: [
  33657.                 soundDone at: i put: true.
  33658.             ].
  33659.         ].
  33660.     ].
  33661. !
  33662. reset
  33663.  
  33664.     super reset.
  33665.     sounds do: [ :snd | snd reset ].
  33666.     soundDone _ (Array new: sounds size) atAllPut: false.
  33667. !
  33668. samplesRemaining
  33669.  
  33670.     | remaining r |
  33671.     remaining _ 0.
  33672.     sounds do: [ :snd |
  33673.         r _ snd samplesRemaining.
  33674.         r > remaining ifTrue: [ remaining _ r ].
  33675.     ].
  33676.     ^ remaining! !
  33677.  
  33678. !MixedSound methodsFor: 'composition'!
  33679. + aSound
  33680.     "Return the mix of the receiver and the argument sound."
  33681.  
  33682.     ^ self add: aSound
  33683. !
  33684. add: aSound
  33685.  
  33686.     sounds _ sounds copyWith: aSound.
  33687.     panSettings _ panSettings copyWith: 500.  "pan settings defaults to centered"!
  33688. add: aSound pan: pan
  33689.  
  33690.     sounds _ sounds copyWith: aSound.
  33691.     panSettings _ panSettings copyWith: pan.! !Controller subclass: #ModalController
  33692.     instanceVariableNames: 'modeActive '
  33693.     classVariableNames: ''
  33694.     poolDictionaries: ''
  33695.     category: 'Interface-Framework'!
  33696. ModalController comment:
  33697. 'I am a class of controllers that put the poor user into a mode.  They do so by always wanting control and never giving it up.  However, they do pass control onto their underlings if any.  The underlings are the only ones who can break the mode by sending controlTerminate.  But beware, if restarted they continue the mode.  Watch out Larry Tesler, the mode lives on...'!
  33698.  
  33699. !ModalController methodsFor: 'mode access'!
  33700. close
  33701.     "Enter the mode, the controller will hold controll forever..." 
  33702.  
  33703.     modeActive _ false.!
  33704. enterMode
  33705.     "Enter the mode, the controller will hold controll forever..." 
  33706.  
  33707.     modeActive _ true.!
  33708. exitMode
  33709.     "Enter the mode, the controller will hold controll forever..." 
  33710.  
  33711.     modeActive _ false.!
  33712. isModeActive
  33713.     ^ modeActive! !
  33714.  
  33715. !ModalController methodsFor: 'control defaults'!
  33716. controlInitialize
  33717.     self enterMode.
  33718.     ^ super controlInitialize!
  33719. controlTerminate
  33720.     self exitMode.
  33721.     ^ super controlTerminate!
  33722. isControlActive
  33723.     ^ modeActive!
  33724. isControlWanted
  33725.     ^ modeActive! !Object subclass: #Model
  33726.     instanceVariableNames: 'dependents '
  33727.     classVariableNames: ''
  33728.     poolDictionaries: ''
  33729.     category: 'Interface-Framework'!
  33730. Model comment:
  33731. 'Provides a superclass for classes that function as models.  The only behavior provided is fast dependents maintentance, which bypasses the generic DependentsFields mechanism.  1/23/96 sw'!
  33732.  
  33733. !Model methodsFor: 'dependents'!
  33734. addDependent: anObject 
  33735.     "Add anObject as one of the receiver's dependents.  Uniform with generic #addDependent:, returns the newly-object dependent, though this feature is not used anywhere in the base system.  1/23/96 sw"
  33736.  
  33737.     dependents == nil
  33738.         ifTrue: 
  33739.             [dependents _ OrderedCollection with: anObject]
  33740.         ifFalse:
  33741.             [dependents add: anObject].
  33742.     ^ anObject!
  33743. breakDependents
  33744.     "Reset the user's dependents list.  1/23/96 sw"
  33745.  
  33746.     dependents _ nil!
  33747. dependents
  33748.     "Answer an OrderedCollection of the objects that are dependent on the receiver, that is, the objects that should be notified if the receiver changes.  Always returns a collection, even if empty. 1/23/96 sw"
  33749.  
  33750.     dependents == nil ifTrue: [dependents _ OrderedCollection new].
  33751.     ^ dependents! !Controller subclass: #MouseMenuController
  33752.     instanceVariableNames: 'redButtonMenu redButtonMessages yellowButtonMenu yellowButtonMessages blueButtonMenu blueButtonMessages '
  33753.     classVariableNames: ''
  33754.     poolDictionaries: ''
  33755.     category: 'Interface-Support'!
  33756. MouseMenuController comment:
  33757. 'I am a Controller that modifies the scheduling of user activities so that the three mouse buttons can be used to make selections or display menus. The menu items are unary messages to the value of sending my instance the message menuMessageReceiver.'!
  33758.  
  33759. !MouseMenuController methodsFor: 'initialize-release'!
  33760. release
  33761.  
  33762.     super release.
  33763.     redButtonMenu release.
  33764.     yellowButtonMenu release.
  33765.     blueButtonMenu release!
  33766. reset
  33767.     "Eliminate references to all mouse button menus."
  33768.  
  33769.     redButtonMenu _ nil.
  33770.     redButtonMessages _ nil.
  33771.     yellowButtonMenu _ nil.
  33772.     yellowButtonMessages _ nil.
  33773.     blueButtonMenu _ nil.
  33774.     blueButtonMessages _ nil! !
  33775.  
  33776. !MouseMenuController methodsFor: 'control defaults'!
  33777. cmdKeyActivity
  33778.     "Check for relevant command keys.  If so, perform them and return true.  Subclasses should override for appropriate cmd keys.  See example code below."
  33779.  
  33780. "    | cmd |
  33781.     (cmd _ sensor ctrlChar) notNil
  33782.     ifTrue: [cmd _ cmd asLowercase.
  33783.             cmd = $x ifTrue: [view cmdX. ^ true].
  33784.             cmd = $c ifTrue: [view cmdC. ^ true].
  33785.             cmd = $v ifTrue: [view cmdV. ^ true].
  33786.             cmd = $d ifTrue: [view cmdD. ^ true]]."
  33787.     ^ false!
  33788. controlActivity 
  33789.     "Refer to the comment in Controller|controlActivity."
  33790.  
  33791.     | cursorPoint |
  33792.     cursorPoint _ Sensor cursorPoint.
  33793.     super controlActivity.
  33794.     cursorPoint = Sensor cursorPoint
  33795.     ifTrue: [ sensor redButtonPressed & self viewHasCursor 
  33796.                 ifTrue: [^self redButtonActivity].
  33797.             sensor yellowButtonPressed & self viewHasCursor 
  33798.                 ifTrue: [^self yellowButtonActivity].
  33799.             sensor blueButtonPressed & self viewHasCursor 
  33800.                 ifTrue: [^self blueButtonActivity]]!
  33801. isControlActive 
  33802.     "Refer to the comment in Controller|isControlActive."
  33803.  
  33804.     Sensor blueButtonPressed ifTrue: [^ false].
  33805.     ^ view containsPoint: sensor cursorPoint! !
  33806.  
  33807. !MouseMenuController methodsFor: 'menu setup'!
  33808. blueButtonMenu: aSystemMenu blueButtonMessages: anArray 
  33809.     "Initialize the pop-up menu that should appear when the user presses the 
  33810.     blue mouse button to be aSystemMenu. The corresponding messages that 
  33811.     should be sent are listed in the array, anArray."
  33812.  
  33813.     blueButtonMenu release.
  33814.     blueButtonMenu _ aSystemMenu.
  33815.     blueButtonMessages _ anArray!
  33816. redButtonMenu: aSystemMenu redButtonMessages: anArray 
  33817.     "Initialize the pop-up menu that should appear when the user presses the 
  33818.     red mouse button to be aSystemMenu. The corresponding messages that 
  33819.     should be sent are listed in the array, anArray."
  33820.  
  33821.     redButtonMenu release.
  33822.     redButtonMenu _ aSystemMenu.
  33823.     redButtonMessages _ anArray!
  33824. shiftedYellowButtonMenu
  33825.     "Serves as a nonsense default backstop; every situation where a shifted menu is anticipated should reimplement this.  2/5/96 sw"
  33826.  
  33827.     ^ PopUpMenu labels: 'eat
  33828. drink
  33829. be merry
  33830. die tomorrow' lines: #()!
  33831. shiftedYellowButtonMessages
  33832.     "Refer to comment under shiftedYellowButtonMenu.  2/5/96 sw"
  33833.  
  33834.     ^ #(notYetImplemented notYetImplemented notYetImplemented notYetImplemented)!
  33835. yellowButtonMenu: aSystemMenu yellowButtonMessages: anArray 
  33836.     "Initialize the pop-up menu that should appear when the user presses the 
  33837.     yellow mouse button to be aSystemMenu. The corresponding messages 
  33838.     that should be sent are listed in the array, anArray."
  33839.  
  33840.     yellowButtonMenu release.
  33841.     yellowButtonMenu _ aSystemMenu.
  33842.     yellowButtonMessages _ anArray! !
  33843.  
  33844. !MouseMenuController methodsFor: 'menu messages'!
  33845. blueButtonActivity
  33846.     "Determine which item in the blue button pop-up menu is selected. If 
  33847.     one is selected, then send the corresponding message to the object 
  33848.     designated as the menu message receiver."
  33849.  
  33850.     | index |
  33851.     blueButtonMenu ~~ nil
  33852.         ifTrue: 
  33853.             [index _ blueButtonMenu startUp.
  33854.             index ~= 0 
  33855.                 ifTrue: [self menuMessageReceiver perform:
  33856.                             (blueButtonMessages at: index)]]
  33857.         ifFalse: [super controlActivity]!
  33858. menuMessageReceiver
  33859.     "Answer the object that should be sent a message when a menu item is 
  33860.     selected."
  33861.  
  33862.     ^self!
  33863. performMenuMessage: aSelector
  33864.     "Perform a menu command by sending self the message aSelector.
  33865.      Default does nothing special."
  33866.  
  33867.     ^self perform: aSelector!
  33868. redButtonActivity
  33869.     "Determine which item in the red button pop-up menu is selected. If one 
  33870.     is selected, then send the corresponding message to the object designated 
  33871.     as the menu message receiver."
  33872.  
  33873.     | index |
  33874.     redButtonMenu ~~ nil
  33875.         ifTrue: 
  33876.             [index _ redButtonMenu startUpRedButton.
  33877.             index ~= 0 
  33878.                 ifTrue: [self menuMessageReceiver perform:
  33879.                             (redButtonMessages at: index)]]
  33880.         ifFalse: [super controlActivity]!
  33881. shiftedYellowButtonActivity
  33882.     "Present the alternate (shifted) menu and take action accordingly.  1/17/96 sw.
  33883.     1/25/96 sw: let #shiftedYellowButtonActivity: do the work"
  33884.  
  33885.     | index shiftMenu |
  33886.  
  33887.     (shiftMenu _ self shiftedYellowButtonMenu) == nil ifTrue:
  33888.         [^ super controlActivity].
  33889.     self shiftedYellowButtonActivity: shiftMenu!
  33890. shiftedYellowButtonActivity: shiftMenu
  33891.     "Present the alternate (shifted) menu and take action accordingly.  If we get here, shiftMenu is known to be non-nil.  1/26/96 sw"
  33892.  
  33893.     | index  |
  33894.  
  33895.     (index _ shiftMenu startUpYellowButton) ~= 0
  33896.         ifTrue:
  33897.             [self menuMessageReceiver performMenuMessage: (self shiftedYellowButtonMessages at: index)]
  33898.         ifFalse:
  33899.             [super controlActivity]!
  33900. unshiftedYellowButtonActivity
  33901.     "Put up the regular yellow-button menu and take action as appropriate.  1/24/96 sw"
  33902.  
  33903.     | index  |
  33904.  
  33905.     yellowButtonMenu ~~ nil
  33906.         ifTrue: 
  33907.             [index _ yellowButtonMenu startUpYellowButton.
  33908.             index ~= 0 
  33909.                 ifTrue: [self menuMessageReceiver performMenuMessage:
  33910.                             (yellowButtonMessages at: index)]]
  33911.         ifFalse:
  33912.             [super controlActivity]!
  33913. yellowButtonActivity
  33914.     "Determine which item in the yellow button pop-up menu is selected. If 
  33915.     one is selected, then send the corresponding message to the object 
  33916.     designated as the menu message receiver.
  33917.     1/18/96 sw: added the escape to shifted variant
  33918.     1/24/96 sw: separate methods for shifted and unshifted variant.
  33919.     1/25/96 sw: speeded up by passing shifted menu along"
  33920.  
  33921.     | shiftMenu |
  33922.     ^ (Sensor leftShiftDown and: [(shiftMenu _ self shiftedYellowButtonMenu) notNil])
  33923.         ifTrue: [self shiftedYellowButtonActivity: shiftMenu]
  33924.         ifFalse:    [self unshiftedYellowButtonActivity]! !Controller subclass: #NoController
  33925.     instanceVariableNames: ''
  33926.     classVariableNames: ''
  33927.     poolDictionaries: ''
  33928.     category: 'Interface-Framework'!
  33929. NoController comment:
  33930. 'I represent a controller that never wants control. I am the controller for views that are non-interactive.'!
  33931.  
  33932. !NoController methodsFor: 'basic control sequence'!
  33933. startUp
  33934.     "I do nothing."
  33935.  
  33936.     ^self! !
  33937.  
  33938. !NoController methodsFor: 'control defaults'!
  33939. isControlActive 
  33940.     "Refer to the comment in Controller|isControlActive."
  33941.  
  33942.     ^false!
  33943. isControlWanted 
  33944.     "Refer to the comment in Controller|isControlWanted."
  33945.  
  33946.     ^false! !StringHolderController subclass: #NotifyStringHolderController
  33947.     instanceVariableNames: 'debugger '
  33948.     classVariableNames: 'YellowButtonMenu YellowButtonMessages '
  33949.     poolDictionaries: ''
  33950.     category: 'Interface-Debugger'!
  33951. NotifyStringHolderController comment:
  33952. 'This class furnishes a controller for Notifiers with a limited menu.
  33953. Red button activity (editing) is prevented'!
  33954.  
  33955. !NotifyStringHolderController methodsFor: 'initialization'!
  33956. initialize
  33957.  
  33958.     super initialize.
  33959.     self yellowButtonMenu: YellowButtonMenu 
  33960.         yellowButtonMessages: YellowButtonMessages! !
  33961.  
  33962. !NotifyStringHolderController methodsFor: 'menu messages'!
  33963. debug
  33964.     "Open a full DebuggerView."
  33965.     | debuggerTemp topView |
  33966.     topView _ view superView.
  33967.     debuggerTemp _ debugger.  debugger _ nil.  "So close wont terminate"
  33968.     self controlTerminate.
  33969.     topView erase.
  33970.     DebuggerView openNoSuspendDebugger: debuggerTemp label: topView label.
  33971.     topView controller closeAndUnscheduleNoErase.
  33972.     Processor terminateActive!
  33973. proceed
  33974.     "Proceed execution of the suspended process."
  33975.     | debuggerTemp |
  33976.     debuggerTemp _ debugger.  debugger _ nil.  "So close wont terminate"
  33977.     self controlTerminate.
  33978.     debuggerTemp proceed: view superView controller.
  33979.     self controlInitialize!
  33980. release
  33981.     | debuggerTemp |
  33982.     debugger == nil
  33983.         ifTrue: [super release]
  33984.         ifFalse:
  33985.             [debuggerTemp _ debugger.  debugger _ nil.
  33986.             view release.  "This will finish view release without termination"
  33987.             debuggerTemp release  "This will cause termination"]! !
  33988.  
  33989. !NotifyStringHolderController methodsFor: 'editing'!
  33990. processRedButton
  33991.     "no editing"! !
  33992.  
  33993. !NotifyStringHolderController methodsFor: 'private'!
  33994. setDebugger: aDebugger
  33995.     debugger _ aDebugger! !
  33996.  
  33997. !NotifyStringHolderController methodsFor: 'selection'!
  33998. initializeSelection
  33999.  
  34000.     ^self! !
  34001. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  34002.  
  34003. NotifyStringHolderController class
  34004.     instanceVariableNames: ''!
  34005.  
  34006. !NotifyStringHolderController class methodsFor: 'class initialization'!
  34007. debugger: aDebugger
  34008.     ^ self new setDebugger: aDebugger! !
  34009.  
  34010. !NotifyStringHolderController class methodsFor: 'instance creation'!
  34011. initialize
  34012.  
  34013.     YellowButtonMenu _ 
  34014.         PopUpMenu labels: 
  34015. 'proceed
  34016. debug'.
  34017.     YellowButtonMessages _ #(proceed debug )
  34018.  
  34019.     "NotifyStringHolderController initialize"! !
  34020.  
  34021. NotifyStringHolderController initialize!
  34022. Magnitude subclass: #Number
  34023.     instanceVariableNames: ''
  34024.     classVariableNames: ''
  34025.     poolDictionaries: ''
  34026.     category: 'Numeric-Numbers'!
  34027. Number comment:
  34028. 'I am an abstract representation of a number. My subclasses--Float, Fraction, and Integer, or their subclasses--provide concrete representations of a numeric quantity.'!
  34029.  
  34030. !Number methodsFor: 'arithmetic'!
  34031. * aNumber 
  34032.     "Answer the result of multiplying the receiver by aNumber."
  34033.  
  34034.     self subclassResponsibility!
  34035. + aNumber 
  34036.     "Answer the sum of the receiver and aNumber."
  34037.  
  34038.     self subclassResponsibility!
  34039. - aNumber 
  34040.     "Answer the difference between the receiver and aNumber."
  34041.  
  34042.     self subclassResponsibility!
  34043. / aNumber 
  34044.     "Answer the result of dividing receiver by aNumber."
  34045.  
  34046.     self subclassResponsibility!
  34047. // aNumber 
  34048.     "Integer quotient defined by division with truncation toward negative 
  34049.     infinity. 9//4 = 2, -9//4 = -3. -0.9//0.4 = -3. \\ answers the remainder 
  34050.     from this division."
  34051.  
  34052.     ^(self / aNumber) floor!
  34053. abs
  34054.     "Answer a Number that is the absolute value (positive magnitude) of the 
  34055.     receiver."
  34056.  
  34057.     self < 0
  34058.         ifTrue: [^self negated]
  34059.         ifFalse: [^self]!
  34060. negated
  34061.     "Answer a Number that is the negation of the receiver."
  34062.  
  34063.     ^0 - self!
  34064. quo: aNumber 
  34065.     "Integer quotient defined by division with truncation toward zero. -9 quo: 
  34066.     4 = -2, -0.9 quo: 0.4 = -2. rem: answers the remainder from this division."
  34067.  
  34068.     ^(self / aNumber) truncated!
  34069. reciprocal
  34070.     "Answer 1 divided by the receiver. Create an error notification if the 
  34071.     receiver is 0."
  34072.  
  34073.     self = 0
  34074.         ifTrue: [^self error: 'zero has no reciprocal']
  34075.         ifFalse: [^1 / self]!
  34076. rem: aNumber 
  34077.     "Remainder defined in terms of quo:. Answer a Number with the same 
  34078.     sign as self. e.g. 9 rem: 4 = 1, -9 rem: 4 = -1. 0.9 rem: 0.4 = 0.1."
  34079.  
  34080.     ^self - ((self quo: aNumber) * aNumber)!
  34081. \\ aNumber 
  34082.     "modulo. Remainder defined in terms of //. Answer a Number with the 
  34083.     same sign as aNumber. e.g. 9\\4 = 1, -9\\4 = 3, 9\\-4 = -3, 0.9\\0.4 = 0.1."
  34084.  
  34085.     ^self - (self // aNumber * aNumber)! !
  34086.  
  34087. !Number methodsFor: 'mathematical functions'!
  34088. arcCos 
  34089.     "The receiver is the cosine of an angle. Answer the angle measured in 
  34090.     radians."
  34091.  
  34092.     ^self asFloat arcCos!
  34093. arcSin
  34094.     "The receiver is the sine of an angle. Answer the angle measured in 
  34095.     radians."
  34096.  
  34097.     ^self asFloat arcSin!
  34098. arcTan
  34099.     "The receiver is the tangent of an angle. Answer the angle measured in 
  34100.     radians."
  34101.  
  34102.     ^self asFloat arcTan!
  34103. cos
  34104.     "The receiver represents an angle measured in radians. Answer its cosine."
  34105.  
  34106.     ^self asFloat cos!
  34107. exp
  34108.     "Answer the exponential of the receiver as a floating point number."
  34109.  
  34110.     ^self asFloat exp!
  34111. floorLog: radix 
  34112.     "Answer the floor of the log base radix of the receiver."
  34113.  
  34114.     ^self asFloat floorLog: radix!
  34115. ln
  34116.     "Answer the natural log of the receiver."
  34117.  
  34118.     ^self asFloat ln!
  34119. log: aNumber 
  34120.     "Answer the log base aNumber of the receiver."
  34121.  
  34122.     ^self ln / aNumber ln!
  34123. raisedTo: aNumber 
  34124.     "Answer the receiver raised to aNumber."
  34125.     (aNumber isInteger)
  34126.         ifTrue: ["Do the special case of integer power"
  34127.                 ^self raisedToInteger: aNumber].
  34128.     aNumber = 0 ifTrue: [^1].        "Special case of exponent=0"
  34129.     aNumber = 1 ifTrue: [^self].        "Special case of exponent=1"
  34130.     ^(aNumber * self ln) exp        "Otherwise raise it to the power using logarithms"!
  34131. raisedToInteger: anInteger 
  34132.     "Answer the receiver raised to the power anInteger where the argument 
  34133.     must be a kind of Integer. This is a special case of raisedTo:."
  34134.     (anInteger isInteger)
  34135.         ifFalse: [^self error: 'raisedToInteger: only works for integral arguments'].
  34136.     anInteger = 0 ifTrue: [^1].
  34137.     anInteger = 1 ifTrue: [^self].
  34138.     anInteger > 1 
  34139.         ifTrue: [^(self * self raisedToInteger: anInteger // 2)
  34140.                     * (self raisedToInteger: anInteger \\ 2)].
  34141.     ^(self raisedToInteger: anInteger negated) reciprocal!
  34142. sin
  34143.     "The receiver represents an angle measured in radians. Answer its sine."
  34144.  
  34145.     ^self asFloat sin!
  34146. sqrt
  34147.     "Answer the square root of the receiver."
  34148.  
  34149.     ^self asFloat sqrt!
  34150. squared
  34151.     "Answer the receiver multipled by itself."
  34152.  
  34153.     ^self * self!
  34154. tan
  34155.     "The receiver represents an angle measured in radians. Answer its 
  34156.     tangent."
  34157.  
  34158.     ^self asFloat tan! !
  34159.  
  34160. !Number methodsFor: 'truncation and round off'!
  34161. ceiling
  34162.     "Answer the integer nearest the receiver toward positive infinity."
  34163.  
  34164.     self <= 0.0
  34165.         ifTrue: [^self truncated]
  34166.         ifFalse: [^self negated floor negated]!
  34167. floor
  34168.     "Answer the integer nearest the receiver toward negative infinity."
  34169.  
  34170.     | truncation |
  34171.     truncation _ self truncated.
  34172.     self >= 0 ifTrue: [^truncation].
  34173.     self = truncation
  34174.         ifTrue: [^truncation]
  34175.         ifFalse: [^truncation - 1]!
  34176. rounded
  34177.     "Answer the integer nearest the receiver."
  34178.  
  34179.     ^(self + (self sign / 2)) truncated!
  34180. roundTo: aNumber 
  34181.     "Answer the integer that is a multiple of aNumber that is nearest the 
  34182.     receiver."
  34183.  
  34184.     ^(self / aNumber) rounded * aNumber!
  34185. roundUpTo: aNumber 
  34186.     "Answer the next multiple of aNumber toward infinity that is nearest the 
  34187.     receiver."
  34188.  
  34189.     ^(self/aNumber) ceiling * aNumber!
  34190. truncated
  34191.     "Answer an integer nearest the receiver toward zero."
  34192.  
  34193.     ^self quo: 1!
  34194. truncateTo: aNumber 
  34195.     "Answer the next multiple of aNumber toward zero that is nearest the 
  34196.     receiver."
  34197.  
  34198.     ^(self quo: aNumber)
  34199.         * aNumber! !
  34200.  
  34201. !Number methodsFor: 'testing'!
  34202. even
  34203.     "Answer whether the receiver is an even number."
  34204.  
  34205.     ^self \\ 2 = 0!
  34206. isInteger
  34207.     ^ false!
  34208. isNumber
  34209.     ^ true!
  34210. negative
  34211.     "Answer whether the receiver is less than 0."
  34212.  
  34213.     ^self < 0!
  34214. odd
  34215.     "Answer whether the receiver is an odd number."
  34216.  
  34217.     ^self even == false!
  34218. positive
  34219.     "Answer whether the receiver is greater than or equal to 0."
  34220.  
  34221.     ^self >= 0!
  34222. sign
  34223.     "Answer 1 if the receiver is greater than 0, -1 if less than 0, else 0."
  34224.  
  34225.     self > 0 ifTrue: [^1].
  34226.     self < 0 ifTrue: [^-1].
  34227.     ^0!
  34228. strictlyPositive
  34229.     "Answer whether the receiver is greater than 0."
  34230.  
  34231.     ^self > 0! !
  34232.  
  34233. !Number methodsFor: 'coercing'!
  34234. coerce: aNumber 
  34235.     "Answer a number representing the argument, aNumber, that is 
  34236.     represented by the same kind of Number as is the receiver. Must be 
  34237.     defined by all Number classes."
  34238.  
  34239.     self subclassResponsibility!
  34240. generality
  34241.     "Answer the number representing the ordering of the receiver in the 
  34242.     generality hierarchy. A number in this hierarchy coerces to numbers 
  34243.     higher in hierarchy (i.e., with larger generality numbers)."
  34244.  
  34245.     self subclassResponsibility!
  34246. retry: arith coercing: argument 
  34247.     "Arithmetic represented by the message, arith, could not be performed 
  34248.     between the receiver and the argument because of differences in
  34249.     representation. Coerce either the receiver or the argument to a more
  34250.     general representation, and try again."
  34251.  
  34252.     (argument isKindOf: Number)
  34253.         ifTrue:
  34254.             [self generality < argument generality
  34255.                 ifTrue: [^ (argument coerce: self) perform: arith with: argument]
  34256.                 ifFalse: [^ self perform: arith with: (self coerce: argument)]]
  34257.         ifFalse: [^ argument perform: arith with: self]! !
  34258.  
  34259. !Number methodsFor: 'converting'!
  34260. @ y 
  34261.     "Primitive. Answer a Point whose x value is the receiver and whose y 
  34262.     value is the argument. Optional. No Lookup. See Object documentation 
  34263.     whatIsAPrimitive."
  34264.  
  34265.     <primitive: 18>
  34266.     ^Point x: self y: y!
  34267. asInteger
  34268.     "Answer an Integer nearest the receiver toward zero."
  34269.  
  34270.     ^self truncated!
  34271. asPoint
  34272.     "Answer a Point with the receiver as both coordinates; often used to 
  34273.     supply the same value in two dimensions, as with symmetrical gridding 
  34274.     or scaling."
  34275.  
  34276.     ^self @ self!
  34277. degreesToRadians
  34278.     "The receiver is assumed to represent degrees. Answer the conversion to 
  34279.     radians."
  34280.  
  34281.     ^self asFloat degreesToRadians!
  34282. radiansToDegrees
  34283.     "The receiver is assumed to represent radians. Answer the conversion to 
  34284.     degrees."
  34285.  
  34286.     ^self asFloat radiansToDegrees! !
  34287.  
  34288. !Number methodsFor: 'intervals'!
  34289. to: stop
  34290.     "Answer an Interval from the receiver up to the argument, stop, 
  34291.     incrementing by 1."
  34292.  
  34293.     ^Interval from: self to: stop by: 1!
  34294. to: stop by: step
  34295.     "Answer an Interval from the receiver up to the argument, stop, 
  34296.     incrementing by step."
  34297.  
  34298.     ^Interval from: self to: stop by: step!
  34299. to: stop by: step do: aBlock 
  34300.     "Normally compiled in-line, and therefore not overridable.
  34301.     Evaluate aBlock for each element of the interval (self to: stop by: step)."
  34302.     | nextValue |
  34303.     nextValue _ self.
  34304.     step < 0
  34305.         ifTrue: [[stop <= nextValue]
  34306.                 whileTrue: 
  34307.                     [aBlock value: nextValue.
  34308.                     nextValue _ nextValue + step]]
  34309.         ifFalse: [[stop >= nextValue]
  34310.                 whileTrue: 
  34311.                     [aBlock value: nextValue.
  34312.                     nextValue _ nextValue + step]]!
  34313. to: stop do: aBlock 
  34314.     "Normally compiled in-line, and therefore not overridable.
  34315.     Evaluate aBlock for each element of the interval (self to: stop by: 1)."
  34316.     | nextValue |
  34317.     nextValue _ self.
  34318.     [nextValue <= stop]
  34319.         whileTrue: 
  34320.             [aBlock value: nextValue.
  34321.             nextValue _ nextValue + 1]! !
  34322.  
  34323. !Number methodsFor: 'printing'!
  34324. printOn: aStream
  34325.     "Default print radix is 10"
  34326.     self printOn: aStream base: 10!
  34327. printStringBase: base
  34328.     ^ String streamContents:
  34329.         [:strm | self printOn: strm base: base]!
  34330. storeOn: aStream 
  34331.     "Normal printing is OK for storing"
  34332.     self printOn: aStream!
  34333. storeOn: aStream base: base
  34334.     "Append my printed representation to aStream, incuding the base."
  34335.  
  34336.     self printOn: aStream base: base!
  34337. storeStringBase: base
  34338.     ^ String streamContents: [:strm | self storeOn: strm base: base]! !
  34339. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  34340.  
  34341. Number class
  34342.     instanceVariableNames: ''!
  34343.  
  34344. !Number class methodsFor: 'instance creation'!
  34345. newFrom: aSimilarObject
  34346.     "Create an object that has similar contents to aSimilarObject."
  34347.  
  34348.     ^self new coerce: aSimilarObject
  34349.  
  34350. "    4 as: Float   4.0
  34351.     4 as: Fraction   (4/1)
  34352.     4 as: Integer   4
  34353.     (4 as: Integer) class   SmallInteger
  34354.     (4 as: LargePositiveInteger) class   SmallInteger
  34355.     4 as: SmallInteger   (error)
  34356. "!
  34357. readFrom: stringOrStream 
  34358.     "Answer a number as described on aStream.  The number may
  34359.     include a leading radix specification, as in 16rFADE"
  34360.     | value base aStream |
  34361.     aStream _ (stringOrStream isMemberOf: String)
  34362.         ifTrue: [ReadStream on: stringOrStream]
  34363.         ifFalse: [stringOrStream].
  34364.     base _ 10.
  34365.     value _ Integer readFrom: aStream base: 10.
  34366.     (aStream peekFor: $r)
  34367.         ifTrue: 
  34368.             ["<base>r<integer>"
  34369.             (base _ value) < 2 ifTrue: [^self error: 'Invalid radix'].
  34370.             value _ Integer readFrom: aStream base: base].
  34371.     ^ self readRemainderOf: value from: aStream base: base!
  34372. readFrom: stringOrStream base: base
  34373.     "Answer a number as described on aStream in the given number base."
  34374.     | aStream |
  34375.     aStream _ (stringOrStream isMemberOf: String)
  34376.         ifTrue: [ReadStream on: stringOrStream]
  34377.         ifFalse: [stringOrStream].
  34378.     ^ self readRemainderOf: (Integer readFrom: aStream base: base)
  34379.             from: aStream base: base!
  34380. readRemainderOf: integerPart from: aStream base: base
  34381.     "Read optional fractional part and exponent, and return the final result"
  34382.     | value fraction fracpos |
  34383.     value _ integerPart.
  34384.     (aStream peekFor: $.)
  34385.         ifTrue: 
  34386.             ["<integer>.<fraction>"
  34387.             (aStream atEnd not and: [aStream peek digitValue between: 0 and: base - 1])
  34388.                 ifTrue: 
  34389.                     [fracpos _ aStream position.
  34390.                     fraction _ Integer readFrom: aStream base: base.
  34391.                     fraction _ 
  34392.                         fraction asFloat / (base raisedTo: aStream position - fracpos).
  34393.                     value _ value asFloat + (value < 0
  34394.                                     ifTrue: [fraction negated]
  34395.                                     ifFalse: [fraction])]
  34396.                 ifFalse: 
  34397.                     ["oops - just <integer>."
  34398.                     aStream skip: -1.        "un-gobble the period"
  34399.                     ^ value
  34400.                     "Number readFrom: '3r-22.2'"]].
  34401.     (aStream peekFor: $e)
  34402.         ifTrue: 
  34403.             ["<integer>e<exponent>"
  34404.             ^ value * (base raisedTo: (Integer readFrom: aStream))].
  34405.     ^ value! !nil subclass: #Object
  34406.     instanceVariableNames: ''
  34407.     classVariableNames: 'ErrorRecursion ConfirmMenu DependentsFields '
  34408.     poolDictionaries: ''
  34409.     category: 'Kernel-Objects'!
  34410. Object comment:
  34411. 'I am the superclass of all classes. I provide default behavior common to all objects, such as class access, copying and printing.'!
  34412.  
  34413. !Object methodsFor: 'accessing'!
  34414. at: index 
  34415.     "Primitive. Assumes receiver is indexable. Answer the value of an 
  34416.     indexable element in the receiver. Fail if the argument index is not an 
  34417.     Integer or is out of bounds. Essential. See Object documentation 
  34418.     whatIsAPrimitive."
  34419.  
  34420.     <primitive: 60>
  34421.     index isInteger
  34422.         ifTrue: [self errorSubscriptBounds: index].
  34423.     index isNumber
  34424.         ifTrue: [^self at: index asInteger]
  34425.         ifFalse: [self errorNonIntegerIndex]!
  34426. at: index add: amount
  34427.     "Add a number to an element of a collection"
  34428.     self at: index put: (self at: index) + amount!
  34429. at: index modify: aBlock
  34430.     "Replace the element of the collection with itself transformed by the block"
  34431.     ^ self at: index put: (aBlock value: (self at: index))!
  34432. at: index put: value 
  34433.     "Primitive. Assumes receiver is indexable. Store the argument value in 
  34434.     the indexable element of the receiver indicated by index. Fail if the 
  34435.     index is not an Integer or is out of bounds. Or fail if the value is not of 
  34436.     the right type for this kind of collection. Answer the value that was 
  34437.     stored. Essential. See Object documentation whatIsAPrimitive."
  34438.  
  34439.     <primitive: 61>
  34440.     index isInteger
  34441.         ifTrue: [(index >= 1 and: [index <= self size])
  34442.                     ifTrue: [self errorImproperStore]
  34443.                     ifFalse: [self errorSubscriptBounds: index]].
  34444.     index isNumber
  34445.         ifTrue: [^self at: index asInteger put: value]
  34446.         ifFalse: [self errorNonIntegerIndex]!
  34447. atPin: index 
  34448.     "Return this element of an indexable object.  Return the first or last element if index is out of bounds.  See Object at:. 6/18/96 tk"
  34449.  
  34450.     <primitive: 60>
  34451.     self emptyCheck.
  34452.     index isInteger ifTrue: [
  34453.         ^ index < 1 ifTrue: [self first] ifFalse: [self last]].
  34454.     index isNumber
  34455.         ifTrue: [^self atPin: index asInteger]
  34456.         ifFalse: [self errorNonIntegerIndex]!
  34457. atWrap: index 
  34458.     "Return this element of an indexable object.  If index is out of bounds, let it wrap around from the end to the beginning until it is in bounds.  See Object at:. 6/18/96 tk"
  34459.     <primitive: 60>
  34460.     self size = 0 ifTrue: [self halt].
  34461.     index isInteger ifTrue: [
  34462.         ^ self at: (index - 1 \\ self size + 1)].
  34463.     index isNumber
  34464.         ifTrue: [^self atWrap: index asInteger]
  34465.         ifFalse: [self errorNonIntegerIndex]!
  34466. basicAt: index 
  34467.     "Primitive. Assumes receiver is indexable. Answer the value of an 
  34468.     indexable element in the receiver. Fail if the argument index is not an 
  34469.     Integer or is out of bounds. Essential. Do not override in a subclass. See 
  34470.     Object documentation whatIsAPrimitive."
  34471.  
  34472.     <primitive: 60>
  34473.     index isInteger ifTrue: [self errorSubscriptBounds: index].
  34474.     index isNumber
  34475.         ifTrue: [^self basicAt: index asInteger]
  34476.         ifFalse: [self errorNonIntegerIndex]!
  34477. basicAt: index put: value 
  34478.     "Primitive. Assumes receiver is indexable. Store the second argument 
  34479.     value in the indexable element of the receiver indicated by index. Fail 
  34480.     if the index is not an Integer or is out of bounds. Or fail if the value is 
  34481.     not of the right type for this kind of collection. Answer the value that 
  34482.     was stored. Essential. Do not override in a subclass. See Object 
  34483.     documentation whatIsAPrimitive."
  34484.  
  34485.     <primitive: 61>
  34486.     index isInteger
  34487.         ifTrue: [(index >= 1 and: [index <= self size])
  34488.                     ifTrue: [self errorImproperStore]
  34489.                     ifFalse: [self errorSubscriptBounds: index]].
  34490.     index isNumber
  34491.         ifTrue: [^self basicAt: index asInteger put: value]
  34492.         ifFalse: [self errorNonIntegerIndex]!
  34493. basicSize
  34494.     "Primitive. Answer the number of indexable variables in the receiver. 
  34495.     This value is the same as the largest legal subscript. Essential. Do not 
  34496.     override in any subclass. See Object documentation whatIsAPrimitive."
  34497.  
  34498.     <primitive: 62>
  34499.     "The number of indexable fields of fixed-length objects is 0"
  34500.     ^0    !
  34501. bindWithTemp: aBlock
  34502.     ^ aBlock value: self value: nil!
  34503. do: aBlock
  34504.     "Singleton objects just upply themselves to the block"
  34505.     "This is a convenient way to bind a simple variable
  34506.     to the result of some expression"
  34507.     ^ aBlock value: self!
  34508. readFromString: aString
  34509.     "Create an object based on the contents of aString."
  34510.  
  34511.     ^self readFrom: (ReadStream on: aString)!
  34512. size
  34513.     "Primitive. Answer the number of indexable variables in the receiver. 
  34514.     This value is the same as the largest legal subscript. Essential. See Object 
  34515.     documentation whatIsAPrimitive."
  34516.  
  34517.     <primitive: 62>
  34518.     "The number of indexable fields of fixed-length objects is 0"
  34519.     ^0!
  34520. yourself
  34521.     "Answer self."! !
  34522.  
  34523. !Object methodsFor: 'testing'!
  34524. hasUnacceptedInput
  34525.     "Answer if the receiver bears unaccepted input.  3/13/96 sw"
  34526.  
  34527.     ^ (self respondsTo: #isUnlocked) and: [self isUnlocked not]!
  34528. isColor
  34529.     "Overridden to return true in Color, natch"
  34530.     ^ false!
  34531. isExtant
  34532.     ^ true!
  34533. isInteger
  34534.     "Overridden to return true in Integer."
  34535.  
  34536.     ^ false!
  34537. isNil
  34538.     "Coerces nil to true and everything else to false."
  34539.  
  34540.     ^false!
  34541. isNumber
  34542.     "Overridden to return true in Number, natch"
  34543.     ^ false!
  34544. notNil
  34545.     "Coerces nil to false and everything else to true."
  34546.  
  34547.     ^true!
  34548. pointsTo: anObject
  34549.     "This method returns true if self contains a pointer to anObject,
  34550.         and returns false otherwise"
  34551.     <primitive: 132>
  34552.     1 to: self class instSize do:
  34553.         [:i | (self instVarAt: i) == anObject ifTrue: [^ true]].
  34554.     1 to: self basicSize do:
  34555.         [:i | (self basicAt: i) == anObject ifTrue: [^ true]].
  34556.     ^ false! !
  34557.  
  34558. !Object methodsFor: 'comparing'!
  34559. = anObject 
  34560.     "Answer whether the receiver and the argument represent the same 
  34561.     object. If = is redefined in any subclass, consider also redefining the 
  34562.     message hash."
  34563.  
  34564.     ^self == anObject!
  34565. == anObject 
  34566.     "Primitive. Answer whether the receiver and the argument are the same 
  34567.     object (have the same object pointer). Do not redefine the message == in 
  34568.     any other class!! Essential. No Lookup. Do not override in any subclass. 
  34569.     See Object documentation whatIsAPrimitive."
  34570.  
  34571.     <primitive: 110>
  34572.     self primitiveFailed!
  34573. hash
  34574.     "Primitive. Answer a SmallInteger whose value is half of the receiver's 
  34575.     object pointer (interpreting object pointers as 16-bit signed quantities). 
  34576.     Fails if the receiver is a SmallInteger. Essential. See Object 
  34577.     documentation whatIsAPrimitive."
  34578.  
  34579.     <primitive: 75>
  34580.     self primitiveFailed!
  34581. hashMappedBy: map
  34582.     "Answer what my hash would be if oops changed according to map."
  34583.  
  34584.     ^map newHashFor: self hash!
  34585. ~= anObject 
  34586.     "Answer whether the receiver and the argument do not represent the 
  34587.     same object."
  34588.  
  34589.     ^self = anObject == false!
  34590. ~~ anObject
  34591.     "Answer whether the receiver and the argument are not the same object 
  34592.     (do not have the same object pointer)."
  34593.  
  34594.     self == anObject
  34595.         ifTrue: [^ false]
  34596.         ifFalse: [^ true]! !
  34597.  
  34598. !Object methodsFor: 'copying'!
  34599. contentsCopy
  34600.     "Squeak: the receiver, serving as the contents of a Squeak object, wishes to have a suitable copy returned.  For most possible contents, the shallow is right; for a collection, i.e. for Folder contents, it is handled in a special-case way.  For alias-valued objects, we come to the crux: the receiver, rather than a copy thereof, must be returned.  6/6/96 sw"
  34601.  
  34602.     ^ self shallowCopy release!
  34603. copy
  34604.     "Answer another instance just like the receiver. Subclasses typically 
  34605.     override this method; they typically do not override shallowCopy."
  34606.  
  34607.     ^self shallowCopy!
  34608. deepCopy
  34609.     "Answer a copy of the receiver with its own copy of each instance 
  34610.     variable."
  34611.  
  34612.     | newObject class index |
  34613.     class _ self class.
  34614.     (class == Object) ifTrue: [^self].
  34615.     class isVariable
  34616.         ifTrue: 
  34617.             [index _ self basicSize.
  34618.             newObject _ class basicNew: index.
  34619.             [index > 0]
  34620.                 whileTrue: 
  34621.                     [newObject basicAt: index put: (self basicAt: index) deepCopy.
  34622.                     index _ index - 1]]
  34623.         ifFalse: [newObject _ class basicNew].
  34624.     index _ class instSize.
  34625.     [index > 0]
  34626.         whileTrue: 
  34627.             [newObject instVarAt: index put: (self instVarAt: index) deepCopy.
  34628.             index _ index - 1].
  34629.     ^newObject!
  34630. kitCopy
  34631.     ^ self shallowCopy!
  34632. shallowCopy
  34633.     "Answer a copy of the receiver which shares the receiver's instance 
  34634.     variables."
  34635.  
  34636.     | class newObject index |
  34637.     class _ self class.
  34638.     "I don't understand why the following check is here.  Object is not 
  34639.     supposed to have any instances at all."
  34640.     class == Object ifTrue: [^self].
  34641.     class isVariable
  34642.         ifTrue: 
  34643.             [index _ self basicSize.
  34644.             newObject _ class basicNew: index.
  34645.             [index > 0]
  34646.                 whileTrue: 
  34647.                     [newObject basicAt: index put: (self basicAt: index).
  34648.                     index _ index - 1]]
  34649.         ifFalse: [newObject _ class basicNew].
  34650.     index _ class instSize.
  34651.     [index > 0]
  34652.         whileTrue: 
  34653.             [newObject instVarAt: index put: (self instVarAt: index).
  34654.             index _ index - 1].
  34655.     ^newObject! !
  34656.  
  34657. !Object methodsFor: 'dependents access'!
  34658. addDependent: anObject 
  34659.     "Add anObject as one of the receiver's dependents."
  34660.  
  34661.     self dependents isEmpty ifTrue: [self setDependents].
  34662.     self dependents add: anObject.
  34663.     ^anObject!
  34664. dependents
  34665.     "Answer an OrderedCollection of the objects that are dependent on the 
  34666.     receiver, that is, the objects that should be notified if the receiver 
  34667.     changes."
  34668.  
  34669.     (DependentsFields includesKey: self)
  34670.         ifTrue: [^DependentsFields at: self]
  34671.         ifFalse: [^OrderedCollection new]!
  34672. release
  34673.     "Remove references to objects that may refer to the receiver. This message 
  34674.     should be overridden by subclasses with any cycles, in which case the 
  34675.     subclass should also include the expression super release."
  34676.  
  34677.     self breakDependents!
  34678. removeDependent: anObject 
  34679.     "Remove the argument, anObject, as one of the receiver's dependents."
  34680.  
  34681.     self dependents remove: anObject ifAbsent: [].
  34682.     self dependents isEmpty ifTrue: [self breakDependents].
  34683.     ^anObject! !
  34684.  
  34685. !Object methodsFor: 'updating'!
  34686. broadcast: aSymbol 
  34687.     "Send the argument, aSymbol, as a unary message to all of the receiver's 
  34688.     dependents."
  34689.  
  34690.     self dependents ~~ nil
  34691.         ifTrue: [self dependents do: 
  34692.                     [:aDependent | aDependent perform: aSymbol]]!
  34693. broadcast: aSymbol with: anObject 
  34694.     "Send the argument, aSymbol, as a keyword message with argument, 
  34695.     anObject, to all of the receiver's dependents."
  34696.  
  34697.     self dependents ~~ nil
  34698.         ifTrue: [self dependents do:
  34699.                     [:aDependent | aDependent perform: aSymbol with: anObject]]!
  34700. changed
  34701.     "Receiver changed in a general way; inform all the dependents by 
  34702.     sending each dependent an update: message."
  34703.  
  34704.     self changed: self!
  34705. changed: aParameter 
  34706.     "Receiver changed. The change is denoted by the argument aParameter. 
  34707.     Usually the argument is a Symbol that is part of the dependent's change 
  34708.     protocol. Inform all of the dependents."
  34709.  
  34710.     self dependents do: [:aDependent | aDependent update: aParameter]!
  34711. hasBeenChanged
  34712.     "Allows a controller to ask this of any model.  1/12/96 sw"
  34713.     ^ false!
  34714. okToChange
  34715.     "Allows a controller to ask this of any model"
  34716.     ^ true!
  34717. update: aParameter 
  34718.     "Receive a change notice from an object of whom the receiver is a 
  34719.     dependent. The default behavior is to do nothing; a subclass might want 
  34720.     to change itself in some way."
  34721.  
  34722.     ^self! !
  34723.  
  34724. !Object methodsFor: 'printing'!
  34725. isLiteral
  34726.     "Answer whether the receiver has a literal text form recognized by the 
  34727.     compiler."
  34728.  
  34729.     ^false!
  34730. longPrintOn: aStream 
  34731.     "Append to the argument, aStream, the names and values of all its instance variables."
  34732.  
  34733.     self class allInstVarNames
  34734.         doWithIndex: [:title :index |
  34735.             aStream nextPutAll: title; nextPut: $:; space; tab.
  34736.             (self instVarAt: index) printOn: aStream.
  34737.             aStream cr].!
  34738. longPrintString
  34739.     "Answer a String whose characters are a description of the receiver."
  34740.  
  34741.     | aStream |
  34742.     aStream _ WriteStream on: (String new: 100).
  34743.     self longPrintOn: aStream.
  34744.     ^aStream contents!
  34745. printOn: aStream 
  34746.     "Append to the argument, aStream, a sequence of characters that 
  34747.     identifies the receiver."
  34748.  
  34749.     | title |
  34750.     title _ self class name.
  34751.     aStream nextPutAll: ((title at: 1) isVowel
  34752.                             ifTrue: ['an ']
  34753.                             ifFalse: ['a '])
  34754.                         , title!
  34755. printString
  34756.     "Answer a String whose characters are a description of the receiver."
  34757.  
  34758.     | aStream |
  34759.     aStream _ WriteStream on: (String new: 100).
  34760.     self printOn: aStream.
  34761.     ^aStream contents!
  34762. storeOn: aStream 
  34763.     "Append to the argument aStream a sequence of characters that is an 
  34764.     expression whose evaluation creates an object similar to the receiver."
  34765.  
  34766.     aStream nextPut: $(.
  34767.     self class isVariable
  34768.         ifTrue: [aStream nextPutAll: '(', self class name, ' basicNew: ';
  34769.                     store: self basicSize;
  34770.                     nextPutAll: ') ']
  34771.         ifFalse: [aStream nextPutAll: self class name, ' basicNew'].
  34772.     1 to: self class instSize do:
  34773.         [:i |
  34774.         aStream nextPutAll: ' instVarAt: ';
  34775.             store: i;
  34776.             nextPutAll: ' put: ';
  34777.             store: (self instVarAt: i);
  34778.             nextPut: $;].
  34779.     1 to: self basicSize do:
  34780.         [:i |
  34781.         aStream nextPutAll: ' basicAt: ';
  34782.             store: i;
  34783.             nextPutAll: ' put: ';
  34784.             store: (self basicAt: i);
  34785.             nextPut: $;].
  34786.     aStream nextPutAll: ' yourself)'
  34787. !
  34788. storeString
  34789.     "Answer a String representation of the receiver from which the receiver 
  34790.     can be reconstructed."
  34791.  
  34792.     | aStream |
  34793.     aStream _ WriteStream on: (String new: 16).
  34794.     self storeOn: aStream.
  34795.     ^aStream contents!
  34796. stringRepresentation
  34797.     "Answer a string that represents the receiver.  For most objects this is simply its printString, but for strings themselves, it's themselves.  6/12/96 sw"
  34798.  
  34799.     ^ self printString ! !
  34800.  
  34801. !Object methodsFor: 'class membership'!
  34802. class
  34803.     "Primitive. Answer the object which is the receiver's class. Essential. See 
  34804.     Object documentation whatIsAPrimitive."
  34805.  
  34806.     <primitive: 111>
  34807.     self primitiveFailed!
  34808. isKindOf: aClass 
  34809.     "Answer whether the class, aClass, is a superclass or class of the receiver."
  34810.  
  34811.     self class == aClass
  34812.         ifTrue: [^true]
  34813.         ifFalse: [^self class inheritsFrom: aClass]!
  34814. isMemberOf: aClass 
  34815.     "Answer whether the receiver is an instance of the class, aClass."
  34816.  
  34817.     ^self class == aClass!
  34818. respondsTo: aSymbol 
  34819.     "Answer whether the method dictionary of the receiver's class contains 
  34820.     aSymbol as a message selector."
  34821.  
  34822.     ^self class canUnderstand: aSymbol! !
  34823.  
  34824. !Object methodsFor: 'message handling'!
  34825. perform: aSymbol 
  34826.     "Primitive. Send the receiver the unary message indicated by the 
  34827.     argument. The argument is the selector of the message. Invoke 
  34828.     messageNotUnderstood: if the number of arguments expected by the 
  34829.     selector is not zero. Optional. See Object documentation whatIsAPrimitive."
  34830.  
  34831.     <primitive: 83>
  34832.     ^self perform: aSymbol withArguments: (Array new: 0)!
  34833. perform: aSymbol with: anObject 
  34834.     "Primitive. Send the receiver the keyword message indicated by the 
  34835.     arguments. The first argument is the selector of the message. The other 
  34836.     argument is the argument of the message to be sent. Invoke 
  34837.     messageNotUnderstood: if the number of arguments expected by the 
  34838.     selector is not one. Optional. See Object documentation whatIsAPrimitive."
  34839.  
  34840.     <primitive: 83>
  34841.     ^self perform: aSymbol withArguments: (Array with: anObject)!
  34842. perform: aSymbol with: firstObject with: secondObject 
  34843.     "Primitive. Send the receiver the keyword message indicated by the 
  34844.     arguments. The first argument is the selector of the message. The other 
  34845.     arguments are the arguments of the message to be sent. Invoke 
  34846.     messageNotUnderstood: if the number of arguments expected by the 
  34847.     selector is not two. Optional. See Object documentation whatIsAPrimitive."
  34848.  
  34849.     <primitive: 83>
  34850.     ^self perform: aSymbol withArguments: (Array with: firstObject with: secondObject)!
  34851. perform: aSymbol with: firstObject with: secondObject with: thirdObject 
  34852.     "Primitive. Send the receiver the keyword message indicated by the 
  34853.     arguments. The first argument is the selector of the message. The other 
  34854.     arguments are the arguments of the message to be sent. Invoke 
  34855.     messageNotUnderstood: if the number of arguments expected by the 
  34856.     selector is not three. Optional. See Object documentation 
  34857.     whatIsAPrimitive."
  34858.  
  34859.     <primitive: 83>
  34860.     ^self perform: aSymbol withArguments: (Array
  34861.             with: firstObject
  34862.             with: secondObject
  34863.             with: thirdObject)!
  34864. perform: selector withArguments: anArray 
  34865.     "Primitive. Send the receiver the keyword message indicated by the 
  34866.     arguments. The argument, selector, is the selector of the message. The 
  34867.     arguments of the message are the elements of anArray. Invoke 
  34868.     messageNotUnderstood: if the number of arguments expected by the 
  34869.     selector is not the same as the length of anArray. Essential. See Object 
  34870.     documentation whatIsAPrimitive."
  34871.  
  34872.     <primitive: 84>
  34873.     self primitiveFailed! !
  34874.  
  34875. !Object methodsFor: 'error handling'!
  34876. break: aMessage 
  34877.     "Call break: instead of self halt, you can browse all your breakpoints by browsing senders of #break:  The halt is bypassed if the shift key is down.  1/18/96 sw"
  34878.  
  34879.     Sensor leftShiftDown ifFalse:
  34880.         [self halt: aMessage]!
  34881. caseError
  34882.     "Report an error from an in-line or explicit case statement."
  34883.  
  34884.     self error: 'Case not found, and no otherwise clause'!
  34885. confirm: aString 
  34886.     "Put up a yes/no menu with caption aString.
  34887.     Answer true if the response is yes, false if no."
  34888.     | choice |
  34889.     [true] whileTrue:
  34890.     [choice _ ConfirmMenu startUpWithCaption: aString.
  34891.     choice = 1 ifTrue: [^ true].
  34892.     choice = 2 ifTrue: [^ false]]!
  34893. confirm: aString orCancel: cancelBlock
  34894.     "Put up a yes/no/cancel menu with caption aString.
  34895.     Answer true if the response is yes, false if no.
  34896.     If cancel is chosen, evaluate cancelBlock."
  34897.  
  34898.     | choice |
  34899.     [true] whileTrue:
  34900.     [choice _ (PopUpMenu labels:
  34901. 'yes
  34902. no
  34903. cancel') startUpWithCaption: aString.
  34904.     choice = 1 ifTrue: [^ true].
  34905.     choice = 2 ifTrue: [^ false].
  34906.     choice = 3 ifTrue: [^ cancelBlock value]]!
  34907. debug
  34908.     "Create and schedule a Debugger on the receiver in the current context."
  34909.  
  34910.     DebuggerView openContext: thisContext sender label: 'debugger'
  34911.  
  34912.     "nil debug."!
  34913. doesNotUnderstand: aMessage 
  34914.     "Report to the user that the receiver does not understand the argument, aMessage, as a message."
  34915.     | currentProcesss currentProcess aString |
  34916.     (self tryToDefineVariableAccess: aMessage)
  34917.         ifFalse: 
  34918.             [aString _ 'Message not understood:', aMessage selector.
  34919.         (currentProcess _ ScheduledControllers activeControllerProcess) isErrorHandled
  34920.                 ifTrue:
  34921.                     [currentProcess errorHandler value: aString value: self]
  34922.                 ifFalse:
  34923.                     [DebuggerView
  34924.                     openContext: thisContext
  34925.                     label: aString
  34926.                     contents: thisContext shortStack]].
  34927.     ^ aMessage sentTo: self!
  34928. error: aString 
  34929.     "The default behavior for error: is the same as halt:. The code is 
  34930.     replicated in order to avoid showing an extra level of message sending 
  34931.     in the Debugger. This additional message is the one a subclass should 
  34932.     override in order to change the error handling behavior."
  34933.     | currentProcesss currentProcess |
  34934.     (currentProcess _ ScheduledControllers activeControllerProcess) isErrorHandled
  34935.         ifTrue:
  34936.             [currentProcess errorHandler value: aString value: self]
  34937.         ifFalse:
  34938.             [DebuggerView
  34939.             openContext: thisContext
  34940.             label: aString
  34941.             contents: thisContext shortStack]
  34942.  
  34943.     "nil error: 'error message'."!
  34944. error: labelString with: contentsString
  34945.     DebuggerView
  34946.         openContext: thisContext
  34947.         label: labelString
  34948.         contents: contentsString!
  34949. halt
  34950.     "This is the typical message to use for inserting breakpoints during 
  34951.     debugging. It behaves like halt:, but does not call on halt: in order to 
  34952.     avoid putting this message on the stack. Halt is especially useful when 
  34953.     the breakpoint message is an arbitrary one."
  34954.  
  34955.     DebuggerView
  34956.         openContext: thisContext
  34957.         label: 'Halt encountered.'
  34958.         contents: thisContext shortStack
  34959.  
  34960.     "nil halt."!
  34961. halt: aString 
  34962.     "This is the typical message to use for inserting breakpoints during 
  34963.     debugging. It creates and schedules a Notifier with the argument, 
  34964.     aString, as the label."
  34965.  
  34966.     DebuggerView
  34967.         openContext: thisContext
  34968.         label: aString
  34969.         contents: thisContext shortStack
  34970.  
  34971.     "nil halt: 'Test of halt:.'."!
  34972. notify: aString 
  34973.     "Create and schedule a Notifier with the argument as the message in 
  34974.     order to request confirmation before a process can proceed."
  34975.  
  34976.     DebuggerView
  34977.         openContext: thisContext
  34978.         label: 'Notifier'
  34979.         contents: aString
  34980.  
  34981.     "nil notify: 'confirmation message'"!
  34982. notify: aString at: location
  34983.     "Create and schedule a Notifier with the argument as the message in 
  34984.     order to request confirmation before a process can proceed. Subclasses can
  34985.     override this and insert an error message at location within aString."
  34986.  
  34987.     self notify: aString
  34988.  
  34989.     "nil notify: 'confirmation message' at: 12"!
  34990. primitiveFailed
  34991.     "Announce that a primitive has failed and there is no appropriate 
  34992.     Smalltalk code to run."
  34993.  
  34994.     self error: 'a primitive has failed'!
  34995. shouldNotImplement
  34996.     "Announce that, although the receiver inherits this message, it should 
  34997.     not implement it."
  34998.  
  34999.     self error: 'This message is not appropriate for this object'!
  35000. subclassResponsibility
  35001.     "This message sets up a framework for the behavior of the class' 
  35002.     subclasses. Announce that the subclass should have implemented this 
  35003.     message."
  35004.  
  35005.     self error: 'My subclass should have overridden one of my messages.'!
  35006. transcriptErrorReportingBlock
  35007.     ^ [:aString :aReceiver |
  35008.         Transcript cr; show: 'Error!! ', aString, '  Receiver: ', aReceiver printString]!
  35009. tryToDefineVariableAccess: aMessage
  35010.     "See if the message just wants to get at an instance variable of this class.  Ask the user if its OK.  If so, define the message to read or write that instance or class variable and retry."
  35011.     | ask newMessage sel |
  35012.     aMessage arguments size > 1 ifTrue: [^ false].
  35013.     sel _ aMessage selector asString.    "works for 0 args"
  35014.     aMessage arguments size = 1 ifTrue: [
  35015.         sel last = $: ifFalse: [^ false].
  35016.         sel _ sel copyWithout: $:].
  35017.     (self class instVarNames includes: sel) ifFalse: [
  35018.         (self class classVarNames includes: sel asSymbol) ifFalse: [
  35019.             ^ false]].
  35020.     ask _ self confirm: 'A ', thisContext sender sender receiver 
  35021.         class printString, ' wants to ', 
  35022.         (aMessage arguments size = 1 ifTrue: ['write into'] ifFalse: ['read from']), '
  35023. ', sel ,' in class ', self class printString, '.
  35024. Define a this access message?'.
  35025.     ask ifTrue: [
  35026.         aMessage arguments size = 1 
  35027.             ifTrue: [newMessage _ aMessage selector, ' anObject
  35028.     ', sel, ' _ anObject']
  35029.             ifFalse: [newMessage _ aMessage selector, '
  35030.     ^', aMessage selector].
  35031.         self class compile: newMessage classified: 'accessing' notifying: nil].
  35032.     ^ ask! !
  35033.  
  35034. !Object methodsFor: 'user interface'!
  35035. basicInspect
  35036.     "Create and schedule an Inspector in which the user can examine the 
  35037.     receiver's variables. This method should not be overriden."
  35038.  
  35039.     InspectorView open: (InspectorView inspectorWithTrash: (Inspector inspect: self))!
  35040. beep
  35041.     "Make a beep sound.  Every object would like to be able to speak.  6/10/96 sw"
  35042.  
  35043.     Smalltalk beep!
  35044. defaultBackgroundColor
  35045.     "Answer the symbol representing the default background color to use if the receiver is used as the model for a StandardSystemView.  4/30/96 sw"
  35046.  
  35047.     ^ #white!
  35048. inform: aString
  35049.     "Display a message for the user to read and then dismiss.  6/9/96 sw"
  35050.  
  35051.     aString size > 0 ifTrue: [(PopUpMenu labels: 'OK') startUpWithCaption: aString]!
  35052. initialExtent
  35053.     "Answer the desired extent for the receiver when a view on it is first opened on the screen. 
  35054.     5/22/96 sw: in the absence of any override, obtain from RealEstateAgent"
  35055.  
  35056.     ^ RealEstateAgent standardWindowExtent!
  35057. inspect
  35058.     "Create and schedule an Inspector in which the user can examine the 
  35059.     receiver's variables."
  35060.     InspectorView open: (InspectorView inspectorWithTrash: (Inspector inspect: self))
  35061. !
  35062. inspectWithLabel: aLabel
  35063.     InspectorView open: (InspectorView inspectorWithTrash: (Inspector inspect: self)) withLabel: aLabel!
  35064. notYetImplemented
  35065.     self inform: 'Not yet implemented'! !
  35066.  
  35067. !Object methodsFor: 'system primitives'!
  35068. asOop
  35069.     "Primitive. Answer a SmallInteger whose value is half of the receiver's 
  35070.     object pointer (interpreting object pointers as 16-bit signed quantities). 
  35071.     Fail if the receiver is a SmallInteger. Essential. See Object documentation 
  35072.     whatIsAPrimitive."
  35073.  
  35074.     <primitive: 75>
  35075.     self primitiveFailed!
  35076. become: otherObject 
  35077.     "Primitive. Swap the object pointers of the receiver and the argument.
  35078.     All variables in the entire system that used to point to the 
  35079.     receiver now point to the argument, and vice-versa.
  35080.     Fails if either object is a SmallInteger"
  35081.  
  35082.     (Array with: self)
  35083.         elementsExchangeIdentityWith:
  35084.             (Array with: otherObject)!
  35085. instVarAt: index 
  35086.     "Primitive. Answer a fixed variable in an object. The numbering of the 
  35087.     variables corresponds to the named instance variables. Fail if the index 
  35088.     is not an Integer or is not the index of a fixed variable. Essential. See 
  35089.     Object documentation whatIsAPrimitive."
  35090.  
  35091.     <primitive: 73>
  35092.     "Access beyond fixed variables."
  35093.     ^self basicAt: index - self class instSize        !
  35094. instVarAt: anInteger put: anObject 
  35095.     "Primitive. Store a value into a fixed variable in the receiver. The 
  35096.     numbering of the variables corresponds to the named instance variables. 
  35097.     Fail if the index is not an Integer or is not the index of a fixed variable. 
  35098.     Answer the value stored as the result. Using this message violates the 
  35099.     principle that each object has sovereign control over the storing of 
  35100.     values into its instance variables. Essential. See Object documentation 
  35101.     whatIsAPrimitive."
  35102.  
  35103.     <primitive: 74>
  35104.     "Access beyond fixed fields"
  35105.     ^self basicAt: anInteger - self class instSize put: anObject!
  35106. nextInstance
  35107.     "Primitive. Answer the next instance after the receiver in the 
  35108.     enumeration of all instances of this class. Fails if all instances have been 
  35109.     enumerated. Essential. See Object documentation whatIsAPrimitive."
  35110.  
  35111.     <primitive: 78>
  35112.     ^nil!
  35113. nextObject
  35114.     "Primitive. Answer the next object after the receiver in the 
  35115.     enumeration of all objects. Return 0 when all objects have been 
  35116.     enumerated."
  35117.  
  35118.     <primitive: 139>
  35119.     self primitiveFailed.!
  35120. someObject
  35121.     "Primitive. Answer the first object in the enumeration of all
  35122.      objects."
  35123.  
  35124.     <primitive: 138>
  35125.     self primitiveFailed.! !
  35126.  
  35127. !Object methodsFor: 'system simulation'!
  35128. tryPrimitive
  35129.     "This method is a template that the Smalltalk simulator uses to 
  35130.     execute primitives. See Object documentation whatIsAPrimitive."
  35131.  
  35132.     <primitive: 007>
  35133.     ^ #simulatorFail!
  35134. tryPrimitiveWith: arg1 
  35135.     "This method is a template that the Smalltalk simulator uses to 
  35136.     execute primitives. See Object documentation whatIsAPrimitive."
  35137.  
  35138.     <primitive: 007>
  35139.     ^ #simulatorFail!
  35140. tryPrimitiveWith: arg1 with: arg2 
  35141.     "This method is a template that the Smalltalk simulator uses to 
  35142.     execute primitives. See Object documentation whatIsAPrimitive."
  35143.  
  35144.     <primitive: 007>
  35145.     ^ #simulatorFail!
  35146. tryPrimitiveWith: arg1 with: arg2 with: arg3 
  35147.     "This method is a template that the Smalltalk simulator uses to 
  35148.     execute primitives. See Object documentation whatIsAPrimitive."
  35149.  
  35150.     <primitive: 007>
  35151.     ^ #simulatorFail!
  35152. tryPrimitiveWith: arg1 with: arg2 with: arg3 with: arg4 
  35153.     "This method is a template that the Smalltalk simulator uses to 
  35154.     execute primitives. See Object documentation whatIsAPrimitive."
  35155.  
  35156.     <primitive: 007>
  35157.     ^ #simulatorFail!
  35158. tryPrimitiveWith: arg1 with: arg2 with: arg3 with: arg4 with: arg5
  35159.     "This method is a template that the Smalltalk simulator uses to 
  35160.     execute primitives. See Object documentation whatIsAPrimitive."
  35161.  
  35162.     <primitive: 007>
  35163.     ^ #simulatorFail!
  35164. tryPrimitiveWith: arg1 with: arg2 with: arg3 with: arg4 with: arg5 with: arg6
  35165.     "This method is a template that the Smalltalk simulator uses to 
  35166.     execute primitives. See Object documentation whatIsAPrimitive."
  35167.  
  35168.     <primitive: 007>
  35169.     ^ #simulatorFail! !
  35170.  
  35171. !Object methodsFor: 'private'!
  35172. breakDependents
  35173.     "Deallocate the soft field for the receiver's dependents."
  35174.  
  35175.     DependentsFields removeKey: self ifAbsent: []!
  35176. errorImproperStore
  35177.     "Create an error notification that an improper store was attempted."
  35178.  
  35179.     self error: 'Improper store into indexable object'!
  35180. errorNonIntegerIndex
  35181.     "Create an error notification that an improper object was used as an index."
  35182.  
  35183.     self error: 'only integers should be used as indices'!
  35184. errorSubscriptBounds: index 
  35185.     "Create an error notification that an improper integer was used as an index."
  35186.  
  35187.     self error: 'subscript is out of bounds: ' , index printString!
  35188. mustBeBoolean
  35189.     "Catches attempts to test truth of non-Booleans.  This message is sent from the
  35190.     interpreter."
  35191.  
  35192.     self error: 'NonBoolean receiver--proceed for truth.'.
  35193.     ^true!
  35194. primitiveError: aString 
  35195.     "This method is called when the error handling results in a recursion in calling
  35196.     on error: or halt or halt:."
  35197.  
  35198.     | context key |
  35199.     Transcript cr.
  35200.     Transcript show: '**System Error Handling Failed** '.
  35201.     Transcript show: aString.
  35202.     Transcript cr.
  35203.     context _ thisContext sender sender.
  35204.     3 timesRepeat: 
  35205.         [context == nil ifFalse: [Transcript print: (context _ context sender); cr]].
  35206.  
  35207.     [Transcript show: '**type <s> for more stack; anything else restarts scheduler**'.
  35208.     Transcript cr.
  35209.     key _ Sensor keyboard.
  35210.     key = $s | (key = $S)] 
  35211.         whileTrue: 
  35212.             [5 timesRepeat: 
  35213.                 [context == nil 
  35214.                     ifFalse: [Transcript print: (context _ context sender); cr]]].
  35215.     ScheduledControllers searchForActiveController!
  35216. setDependents
  35217.     "Allocate the soft field for the receiver's dependents."
  35218.  
  35219.     DependentsFields add: (Association key: self value: OrderedCollection new)!
  35220. species
  35221.     "Answer the preferred class for reconstructing the receiver.  For example, 
  35222.     collections create new collections whenever enumeration messages such as 
  35223.     collect: or select: are invoked.  The new kind of collection is determined by 
  35224.     the species of the original collection.  Species and class are not always the 
  35225.     same.  For example, the species of Interval is Array."
  35226.  
  35227.     ^self class!
  35228. storeAt: offset inTempFrame: aContext
  35229.     "This message had to get sent to an expression already on the stack
  35230.     as a Block argument being accessed by the debugger.
  35231.     Just re-route it to the temp frame."
  35232.     ^ aContext tempAt: offset put: self! !
  35233.  
  35234. !Object methodsFor: 'associating'!
  35235. -> anObject
  35236.     "Answer an Association between self and anObject"
  35237.  
  35238.     ^Association new key: self value: anObject! !
  35239.  
  35240. !Object methodsFor: 'converting'!
  35241. as: aSimilarClass
  35242.     "Create an object of class aSimilarClass that has similar contents to the receiver."
  35243.  
  35244.     ^ aSimilarClass newFrom: self! !
  35245.  
  35246. !Object methodsFor: 'casing'!
  35247. caseOf: aBlockAssociationCollection
  35248.     "The elements of aBlockAssociationCollection are associations between blocks.
  35249.      Answer the evaluated value of the first association in aBlockAssociationCollection
  35250.      whose evaluated key equals the receiver.  If no match is found, report an error."
  35251.  
  35252.     ^ self caseOf: aBlockAssociationCollection otherwise: [self caseError]
  35253.  
  35254. "| z | z _ {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z"
  35255. "| z | z _ {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z"
  35256. "The following are compiled in-line:"
  35257. "#b caseOf: {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}"
  35258. "#b caseOf: {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}"!
  35259. caseOf: aBlockAssociationCollection otherwise: aBlock
  35260.     "The elements of aBlockAssociationCollection are associations between blocks.
  35261.      Answer the evaluated value of the first association in aBlockAssociationCollection
  35262.      whose evaluated key equals the receiver.  If no match is found, answer the result
  35263.      of evaluating aBlock."
  35264.  
  35265.     aBlockAssociationCollection associationsDo:
  35266.         [:assoc | (assoc key value = self) ifTrue: [^assoc value value]].
  35267.     ^ aBlock value
  35268.  
  35269. "| z | z _ {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z otherwise: [0]"
  35270. "| z | z _ {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z otherwise: [0]"
  35271. "The following are compiled in-line:"
  35272. "#b caseOf: {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]} otherwise: [0]"
  35273. "#b caseOf: {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]} otherwise: [0]"! !
  35274.  
  35275. !Object methodsFor: 'binding'!
  35276. bindingOf: aString
  35277.     ^nil! !
  35278.  
  35279. !Object methodsFor: 'macpal'!
  35280. showInTranscript: aString
  35281.     "Call this instead of addressing Transcript directly in order to ease identification of all New-Kernel-related Transcript calls obtained (i.e. by browsing senders).  1/18/96 sw"
  35282.  
  35283.     Transcript cr; show: aString! !
  35284.  
  35285. !Object methodsFor: 'flagging'!
  35286. flag: aSymbol
  35287.     "Send this message, with a relevant symbol as argument, to flag a message for subsequent retrieval.  For example, you might put the following line in a number of messages:
  35288.     self flag: #returnHereUrgently
  35289.     Then, to retrieve all such messages, browse all senders of #returnHereUrgently."
  35290.  
  35291.     "flags in use currently:
  35292.         hot (used by sw to flag methods he must revisit; things hotter than hot are flagged #hottest)
  35293.         developmentNote
  35294.         scottPrivate
  35295.         toBeRemoved
  35296.         noteToDan
  35297.         noteToJohn
  35298.         noteToTed"!
  35299. isThisEverCalled: msg
  35300.     "Send this message, with some useful printable argument, from methods or branches of methods which you believe are never reached.  2/5/96 sw"
  35301.  
  35302.     self halt: 'This is indeed called: ', msg printString! !
  35303.  
  35304. !Object methodsFor: 'imported from V'!
  35305. comeFullyUpOnReload
  35306.     "Normally this read-in object is exactly what we want to store. 7/26/96 tk"
  35307.  
  35308.     ^ self!
  35309. objectToStoreOnDataStream
  35310.     "Return an object to store on a data stream (externalize myself)."
  35311.  
  35312.     ^ self!
  35313. saveOnFile
  35314.     "Ask the user for a filename and save myself on a ReferenceStream file.
  35315.      11/13/92 jhm: Set the file type so it won't appear to be TEXT.
  35316.      12/2/92 sw:  Stash ReferenceStream versionCode at start of file.
  35317.     Is this ever used???  7/26/96 tk"
  35318.  
  35319.     | aFileStream |
  35320.  
  35321.     aFileStream _ FileStream fromUser.
  35322.     aFileStream isNil ifTrue: [^ false].
  35323.     aFileStream binary.
  35324.  
  35325.     self aboutToWriteToDisk.
  35326.  
  35327.     (ReferenceStream on: aFileStream)
  35328.         nextPut: ReferenceStream versionCode;
  35329.         nextPut: self;
  35330.         setType;
  35331.         close.
  35332.  
  35333.     self doneWritingToDisk!
  35334. storeDataOn: aDataStream
  35335.     "Store myself on a DataStream. Answer self.  This is a low-level DataStream/ReferenceStream method. See also objectToStoreOnDataStream.
  35336.      NOTE: This method must send 'aDataStream beginInstance:size:'
  35337.         and then put a number of objects (via aDataStream nextPut:/nextPutWeak:).
  35338.      Cf. readDataFrom:size:, which must read back what this puts
  35339.     when given the size that it gave to beginInstance:size:. -- 11/15/92 jhm"
  35340.     | cntInstVars cntIndexedVars |
  35341.  
  35342.     cntInstVars _ self class instSize.
  35343.     cntIndexedVars _ self basicSize.
  35344.     aDataStream
  35345.         beginInstance: self class
  35346.         size: cntInstVars + cntIndexedVars.
  35347.     1 to: cntInstVars do:
  35348.         [:i | aDataStream nextPut: (self instVarAt: i)].
  35349.     1 to: cntIndexedVars do:
  35350.         [:i | aDataStream nextPut: (self basicAt: i)]! !
  35351.  
  35352. !Object methodsFor: 'hyperSqueak I/O'!
  35353. ioType
  35354.     "Return which of several categories this object is.  Effects how a HyperSqueak object is written on the disk.  7/29/96 tk"
  35355.     
  35356.     ^ #System    "non-HyperSqueak object"!
  35357. saveOnFile2
  35358.     "Ask the user for a filename and save myself on a ReferenceStream file.
  35359.      Put out structure of non-HyperSqueak object.  8/19/96 tk
  35360.      9/19/96 sw: adjustments for case where HyperSqueak is not present, though this code
  35361.         at present is not reached except from HyperSqueak code"
  35362.  
  35363.     | aFileName manager model aStream bytes sqSupport |
  35364.  
  35365.     aFileName _ self class name asFileName.    "do better?"
  35366.     aFileName _ FillInTheBlank request: 'File name?' initialAnswer: aFileName.
  35367.     aFileName size == 0 ifTrue: [^ self beep].
  35368.  
  35369.     sqSupport _ self hyperSqueakSupportClass.
  35370.     sqSupport == nil ifFalse:
  35371.         [sqSupport preReleaseFileOut: true].    "Force writing of sys objects"
  35372.     manager _ DataStream incomingObjectsClass new.
  35373.     manager install: model.
  35374.     aStream _ ReferenceStream newFileNamed: aFileName.
  35375.     aStream nextPut: ReferenceStream versionCode;
  35376.         nextPut: manager instVarInfo;
  35377.         nextPut: self.
  35378.     bytes _ aStream close.
  35379.     sqSupport == nil ifFalse:
  35380.         [sqSupport preReleaseFileOut: false].    "normal"
  35381.  
  35382.     Transcript cr; show: 'Successfully saved to ', aFileName, ' with length ', bytes printString.! !
  35383. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  35384.  
  35385. Object class
  35386.     instanceVariableNames: ''!
  35387.  
  35388. !Object class methodsFor: 'class initialization'!
  35389. initializeOnceOnly 
  35390.     "Refer to the comment in Class|initialize.  This is the initilaize message for Object class, but
  35391.     if called initialize, then all classes would inherit it as a class message, and clearly this is not
  35392.     the default desired."
  35393.  
  35394.     self initializeDependentsFields.  "Note this will disconnect views!!"
  35395.     self initializeErrorRecursion.
  35396.     self initializeConfirmMenu.
  35397.  
  35398.     "Object initializeOnceOnly"! !
  35399.  
  35400. !Object class methodsFor: 'instance creation'!
  35401. newFrom: aSimilarObject
  35402.     "Create an object that has similar contents to aSimilarObject.  If the classes have any instance varaibles with the same names, copy them across.  If this is bad for a class, override this method."
  35403.     | myInstVars similarInstVars any inst good |
  35404.     myInstVars _ self allInstVarNames.
  35405.     similarInstVars _ aSimilarObject class allInstVarNames.
  35406.     inst _ self new.
  35407.     myInstVars doWithIndex: [:each :index |
  35408.         good _ similarInstVars indexOf: each.
  35409.         good > 0 ifTrue: [
  35410.             inst instVarAt: index put: 
  35411.                 (aSimilarObject instVarAt: good).
  35412.             any _ true]].
  35413.     any == nil ifTrue: ["not related at all"
  35414.         self subclassResponsibility].
  35415.     ^ inst!
  35416. readFrom: aStream
  35417.     "Create an object based on the contents of aStream."
  35418.  
  35419.     | object |
  35420.     object _ Compiler evaluate: aStream.
  35421.     (object isKindOf: self) ifFalse: [self error: self name, ' expected'].
  35422.     ^object! !
  35423.  
  35424. !Object class methodsFor: 'documentation'!
  35425. howToModifyPrimitives
  35426.     "You are allowed to write methods which specify primitives, but please use 
  35427.     caution.  If you make a subclass of a class which contains a primitive method, 
  35428.     the subclass inherits the primitive.  The message which is implemented 
  35429.     primitively may be overridden in the subclass (E.g., see at:put: in String's 
  35430.     subclass Symbol).  The primitive behavior can be invoked using super (see 
  35431.     Symbol string:). 
  35432.      
  35433.     A class which attempts to mimic the behavior of another class without being 
  35434.     its subclass may or may not be able to use the primitives of the original class.  
  35435.     In general, if the instance variables read or written by a primitive have the 
  35436.     same meanings and are in the same fields in both classes, the primitive will 
  35437.     work.  
  35438.  
  35439.     For certain frequently used 'special selectors', the compiler emits a 
  35440.     send-special-selector bytecode instead of a send-message bytecode.  
  35441.     Special selectors were created because they offer two advantages.  Code 
  35442.     which sends special selectors compiles into fewer bytes than normal.  For 
  35443.     some pairs of receiver classes and special selectors, the interpreter jumps 
  35444.     directly to a primitive routine without looking up the method in the class.  
  35445.     This is much faster than a normal message lookup. 
  35446.      
  35447.     A selector which is a special selector solely in order to save space has a 
  35448.     normal behavior.  Methods whose selectors are special in order to 
  35449.     gain speed contain the comment, 'No Lookup'.  When the interpreter 
  35450.     encounters a send-special-selector bytecode, it checks the class of the 
  35451.     receiver and the selector.  If the class-selector pair is a no-lookup pair, 
  35452.     then the interpreter swiftly jumps to the routine which implements the 
  35453.     corresponding primitive.  (A special selector whose receiver is not of the 
  35454.     right class to make a no-lookup pair, is looked up normally).  The pairs are 
  35455.     listed below.  No-lookup methods contain a primitive number specification, 
  35456.     <primitive: xx>, which is redundant.  Since the method is not normally looked 
  35457.     up, deleting the primitive number specification cannot prevent this 
  35458.     primitive from running.  If a no-lookup primitive fails, the method is looked 
  35459.     up normally, and the expressions in it are executed. 
  35460.      
  35461.     No Lookup pairs of (class, selector) 
  35462.      
  35463.     SmallInteger with any of        + - * /  \\  bitOr: bitShift: bitAnd:  // 
  35464.     SmallInteger with any of        =  ~=  >  <  >=  <= 
  35465.     Any class with                    == 
  35466.     Any class with                     @ 
  35467.     Point with either of                x y 
  35468.     ContextPart with                    blockCopy: 
  35469.     BlockContext with either of         value value:
  35470.     "
  35471.  
  35472.     self error: 'comment only'!
  35473. whatIsAPrimitive
  35474.     "Some messages in the system are responded to primitively. A primitive   
  35475.     response is performed directly by the interpreter rather than by evaluating   
  35476.     expressions in a method. The methods for these messages indicate the   
  35477.     presence of a primitive response by including <primitive: xx> before the   
  35478.     first expression in the method.   
  35479.       
  35480.     Primitives exist for several reasons. Certain basic or 'primitive' 
  35481.     operations cannot be performed in any other way. Smalltalk without 
  35482.     primitives can move values from one variable to another, but cannot add two 
  35483.     SmallIntegers together. Many methods for arithmetic and comparison 
  35484.     between numbers are primitives. Some primitives allow Smalltalk to 
  35485.     communicate with I/O devices such as the disk, the display, and the keyboard. 
  35486.     Some primitives exist only to make the system run faster; each does the same 
  35487.     thing as a certain Smalltalk method, and its implementation as a primitive is 
  35488.     optional.  
  35489.       
  35490.     When the Smalltalk interpreter begins to execute a method which specifies a 
  35491.     primitive response, it tries to perform the primitive action and to return a 
  35492.     result. If the routine in the interpreter for this primitive is successful, 
  35493.     it will return a value and the expressions in the method will not be evaluated. 
  35494.     If the primitive routine is not successful, the primitive 'fails', and the 
  35495.     Smalltalk expressions in the method are executed instead. These 
  35496.     expressions are evaluated as though the primitive routine had not been 
  35497.     called.  
  35498.       
  35499.     The Smalltalk code that is evaluated when a primitive fails usually 
  35500.     anticipates why that primitive might fail. If the primitive is optional, the 
  35501.     expressions in the method do exactly what the primitive would have done (See 
  35502.     Number @). If the primitive only works on certain classes of arguments, the 
  35503.     Smalltalk code tries to coerce the argument or appeals to a superclass to find 
  35504.     a more general way of doing the operation (see SmallInteger +). If the 
  35505.     primitive is never supposed to fail, the expressions signal an error (see 
  35506.     SmallInteger asFloat).  
  35507.       
  35508.     Each method that specifies a primitive has a comment in it. If the primitive is 
  35509.     optional, the comment will say 'Optional'. An optional primitive that is not 
  35510.     implemented always fails, and the Smalltalk expressions do the work 
  35511.     instead.  
  35512.      
  35513.     If a primitive is not optional, the comment will say, 'Essential'. Some 
  35514.     methods will have the comment, 'No Lookup'. See Object 
  35515.     howToModifyPrimitives for an explanation of special selectors which are 
  35516.     not looked up.  
  35517.       
  35518.     For the primitives for +, -, *, and bitShift: in SmallInteger, and truncated 
  35519.     in Float, the primitive constructs and returns a 16-bit 
  35520.     LargePositiveInteger when the result warrants it. Returning 16-bit 
  35521.     LargePositiveIntegers from these primitives instead of failing is 
  35522.     optional in the same sense that the LargePositiveInteger arithmetic 
  35523.     primitives are optional. The comments in the SmallInteger primitives say, 
  35524.     'Fails if result is not a SmallInteger', even though the implementor has the 
  35525.     option to construct a LargePositiveInteger. For further information on 
  35526.     primitives, see the 'Primitive Methods' part of the chapter on the formal 
  35527.     specification of the interpreter in the Smalltalk book."
  35528.  
  35529.     self error: 'comment only'! !
  35530.  
  35531. !Object class methodsFor: 'private'!
  35532. initializeConfirmMenu
  35533.     ConfirmMenu _ PopUpMenu labels:
  35534. 'yes
  35535. no'.
  35536.     "Object initializeConfirmMenu"!
  35537. initializeDependentsFields
  35538.     DependentsFields _ IdentityDictionary new: 4
  35539.  
  35540.     "Object initializeDependentsFields"
  35541. !
  35542. initializeErrorRecursion
  35543.     ErrorRecursion _ false
  35544.  
  35545.     "Object initializeErrorRecursion"! !
  35546.  
  35547. !Object class methodsFor: 'imported from V'!
  35548. readDataFrom: aDataStream size: anInteger
  35549.     "Create an object based on the contents of aDataStream, which was
  35550.        generated by the object╒s storeDataOn: method. Answer it.
  35551.      This implementation reads back the instance-variables written by
  35552.        Object>>storeDataOn:.
  35553.      NOTE: This method must match its corresponding storeDataOn:
  35554.        method. Also, it must send beginReference: after instantiating
  35555.        the new object but before reading any objects from aDataStream
  35556.        that might reference it.
  35557.      11/23/92 jhm: Changed to basicNew & basicNew: to match basicSize and because
  35558.         we then overwrite all instance & indexed vars."
  35559.     | anObject cntInstVars cntIndexedVars |
  35560.  
  35561.     cntInstVars _ self instSize.
  35562.     anObject _ self isVariable
  35563.         ifTrue:  [cntIndexedVars _ anInteger - cntInstVars.
  35564.                  self basicNew: cntIndexedVars]
  35565.         ifFalse: [cntIndexedVars _ 0.
  35566.                  self basicNew].
  35567.  
  35568.     aDataStream beginReference: anObject.
  35569.     1 to: cntInstVars do:
  35570.         [:i | anObject instVarAt: i put: aDataStream next].
  35571.     1 to: cntIndexedVars do:
  35572.         [:i | anObject basicAt: i put: aDataStream next].
  35573. "self == Association ifTrue: [
  35574.     anObject value == Obj homeObject ifTrue: [self halt]]."
  35575.  
  35576.     ^ anObject! !Switch subclass: #OneOnSwitch
  35577.     instanceVariableNames: 'connection '
  35578.     classVariableNames: ''
  35579.     poolDictionaries: ''
  35580.     category: 'Interface-Menus'!
  35581. OneOnSwitch comment:
  35582. 'I am a kind of Switch that can be connected to some related object, typically to a collection of my instances. When my instance is created, its connection is set to a particular object. When the object changes because an Switch it refers to is turned on, an update message is broadcasted. All the connected OneOnSwitches, except the changed one, turn off. This allows OneOnSwitches to maintain the constraint that at most one of them will be on at any time. OneOnSwitches can thus be made to act like "car radio" switches.'!
  35583.  
  35584. !OneOnSwitch methodsFor: 'initialize-release'!
  35585. release
  35586.  
  35587.     super release.
  35588.     self isConnectionSet ifTrue: [connection removeDependent: self]! !
  35589.  
  35590. !OneOnSwitch methodsFor: 'state'!
  35591. turnOn
  35592.     "Does nothing if it is already on. If it is not, it is set to 'on', its
  35593.     dependents are     notified of the change, its connection is notified, and
  35594.     its action is executed."
  35595.  
  35596.     self isOff
  35597.         ifTrue: 
  35598.             [on _ true.
  35599.             self changed.
  35600.             self notifyConnection.
  35601.             self doAction: onAction]! !
  35602.  
  35603. !OneOnSwitch methodsFor: 'connection'!
  35604. connection
  35605.     "Answer the object that connects the receiver to other Switches."
  35606.  
  35607.     ^connection!
  35608. connection: anObject 
  35609.     "Set anObject to be the connection among two or more Switches. Make the 
  35610.     receiver a dependent of the argument, anObject."
  35611.  
  35612.     connection _ anObject.
  35613.     connection addDependent: self!
  35614. isConnectionSet
  35615.     "Answer whether the receiver is connected to an object that coordinates 
  35616.     updates among switches."
  35617.  
  35618.     connection == nil
  35619.         ifTrue: [^false]
  35620.         ifFalse: [^true]!
  35621. notifyConnection
  35622.     "Send the receiver's connection (if it exists) the message 'changed: self' in 
  35623.     order for the connection to broadcast the change to other objects 
  35624.     connected by the connection."
  35625.     
  35626.     self isConnectionSet ifTrue: [self connection changed: self]! !
  35627.  
  35628. !OneOnSwitch methodsFor: 'updating'!
  35629. update: aOneOnSwitch 
  35630.     "Does nothing if aOneOnSwitch is identical to this object. If it is not, this 
  35631.     object is turned off. This message is sent by the connection (an Object)
  35632.     when some related OneOnSwitch (possibly this one) has changed. This
  35633.     allows a group of related OneOnSwitches to maintain the constraint that
  35634.     at most one will be on at any time."
  35635.  
  35636.     self ~~ aOneOnSwitch ifTrue: [self turnOff]! !SequenceableCollection subclass: #OrderedCollection
  35637.     instanceVariableNames: 'array firstIndex lastIndex '
  35638.     classVariableNames: ''
  35639.     poolDictionaries: ''
  35640.     category: 'Collections-Sequenceable'!
  35641. OrderedCollection comment:
  35642. 'I represent a collection of objects ordered by the collector.'!
  35643.  
  35644. !OrderedCollection methodsFor: 'accessing'!
  35645. after: oldObject 
  35646.     "Answer the element after oldObject. If the receiver does not contain 
  35647.     oldObject or if the receiver contains no elements after oldObject, create 
  35648.     an error notification."
  35649.     | index |
  35650.     index _ self find: oldObject.
  35651.     index = lastIndex
  35652.         ifTrue: [^self errorLastObject]
  35653.         ifFalse: [^array at: index + 1]!
  35654. at: anInteger 
  35655.     "Answer my element at index anInteger. at: is used by a knowledgeable
  35656.     client to access an existing element"
  35657.  
  35658.     (anInteger < 1 or: [anInteger + firstIndex - 1 > lastIndex])
  35659.         ifTrue: [self errorNoSuchElement]
  35660.         ifFalse: [^ array at: anInteger + firstIndex - 1]!
  35661. at: anInteger put: anObject 
  35662.     "Put anObject at element index anInteger. at:put: cannot be used to
  35663.     append, front or back, to an ordered collection; it is used by a
  35664.     knowledgeable client to replace an element."
  35665.  
  35666.     | index |
  35667.     index _ anInteger asInteger.
  35668.     (index < 1 or: [index + firstIndex - 1 > lastIndex])
  35669.         ifTrue: [self errorNoSuchElement]
  35670.         ifFalse: [^array at: index + firstIndex - 1 put: anObject]!
  35671. atPin: anInteger 
  35672.     "Answer my element at index anInteger. at: is used by a knowledgeable client to access an existing element.   Return the first or last element if index is out of bounds.  6/18/96 tk"
  35673.  
  35674. anInteger < 1
  35675.     ifTrue: [^ self first]
  35676.     ifFalse: [anInteger + firstIndex - 1 > lastIndex
  35677.         ifTrue: [^ self last]
  35678.         ifFalse: [^ array at: anInteger + firstIndex - 1]]!
  35679. atWrap: anInteger 
  35680.     "Answer my element at index anInteger. at: is used by a knowledgeable client to access an existing element.   If index is out of bounds, let it wrap around from the end to the beginning until it is in bounds.  6/18/96 tk"
  35681.  
  35682. ^ self at: (anInteger - 1 \\ self size + 1)
  35683. !
  35684. before: oldObject 
  35685.     "Answer the element before oldObject. If the receiver does not contain 
  35686.     oldObject or if the receiver contains no elements before oldObject, create     an error notification."
  35687.     | index |
  35688.     index _ self find: oldObject.
  35689.     index = firstIndex
  35690.         ifTrue: [^ self errorFirstObject]
  35691.         ifFalse: [^ array at: index - 1]!
  35692. first
  35693.     "Answer the first element. If the receiver is empty, create an errror
  35694.     message. This is a little faster than the implementation in the superclass."
  35695.  
  35696.     self emptyCheck.
  35697.     ^ array at: firstIndex!
  35698. inspect
  35699.     "Open an OrderedCollectionInspector on the receiver.
  35700.     Use basicInspect to get a normal type of inspector."
  35701.  
  35702.     InspectorView open: (InspectorView inspectorWithTrash:
  35703.         (OrderedCollectionInspector inspect: self))!
  35704. last
  35705.     "Answer the last element. If the receiver is empty, create an errror
  35706.     message. This is a little faster than the implementation in the superclass."
  35707.  
  35708.     self emptyCheck.
  35709.     ^ array at: lastIndex!
  35710. size
  35711.  
  35712.     ^lastIndex - firstIndex + 1! !
  35713.  
  35714. !OrderedCollection methodsFor: 'copying'!
  35715. copyEmpty
  35716.     "Answer a copy of the receiver that contains no elements."
  35717.  
  35718.     ^self species new!
  35719. copyFrom: startIndex to: endIndex 
  35720.     "Answer a copy of the receiver that contains elements from position
  35721.     startIndex to endIndex."
  35722.  
  35723.     | targetCollection index |
  35724.     endIndex < startIndex ifTrue: [^self species new: 0].
  35725.     targetCollection _ self species new: endIndex + 1 - startIndex.
  35726.     startIndex to: endIndex do: [:index | targetCollection add: (self at: index)].
  35727.     ^ targetCollection!
  35728. copyReplaceFrom: start to: stop with: replacementCollection 
  35729.     "Answer a copy of the receiver with replacementCollection's elements in
  35730.     place of the receiver's start'th to stop'th elements. This does not expect
  35731.     a 1-1 map from replacementCollection to the start to stop elements, so it
  35732.     will do an insert or append."
  35733.  
  35734.     | newOrderedCollection delta newIndex index mySize startIndex stopIndex |
  35735.     "if start is less than 1, ignore stop and assume this is inserting at the front. 
  35736.     if start greater than self size, ignore stop and assume this is appending. 
  35737.     otherwise, it is replacing part of me and start and stop have to be within my 
  35738.     bounds. "
  35739.     delta _ 0.
  35740.     startIndex _ start.
  35741.     stopIndex _ stop.
  35742.     start < 1
  35743.         ifTrue: [startIndex _ stopIndex _ 0]
  35744.         ifFalse: [startIndex > self size
  35745.                 ifTrue: [startIndex _ stopIndex _ self size + 1]
  35746.                 ifFalse: 
  35747.                     [(stopIndex < (startIndex - 1) or: [stopIndex > self size])
  35748.                         ifTrue: [self errorOutOfBounds].
  35749.                     delta _ stopIndex - startIndex + 1]].
  35750.     newOrderedCollection _ 
  35751.         self species new: self size + replacementCollection size - delta.
  35752.     1 to: startIndex - 1 do: [:index | newOrderedCollection add: (self at: index)].
  35753.     1 to: replacementCollection size do: 
  35754.         [:index | newOrderedCollection add: (replacementCollection at: index)].
  35755.     stopIndex + 1 to: self size do: [:index | newOrderedCollection add: (self at: index)].
  35756.     ^newOrderedCollection!
  35757. copyWith: newElement 
  35758.     "Answer a copy of the receiver that is 1 bigger than the receiver and 
  35759.     includes the argument, newElement, at the end."
  35760.  
  35761.     | newCollection |
  35762.     newCollection _ self copy.
  35763.     newCollection add: newElement.
  35764.     ^newCollection!
  35765. copyWithout: oldElement 
  35766.     "Answer a copy of the receiver that does not contain any elements equal
  35767.     to oldElement."
  35768.  
  35769.     | newCollection each |
  35770.     newCollection _ self species new: self size.
  35771.     self do: [:each | oldElement = each ifFalse: [newCollection add: each]].
  35772.     ^newCollection! !
  35773.  
  35774. !OrderedCollection methodsFor: 'adding'!
  35775. add: newObject
  35776.  
  35777.     ^self addLast: newObject!
  35778. add: newObject after: oldObject 
  35779.     "Add the argument, newObject, as an element of the receiver. Put it in 
  35780.     the sequence just succeeding oldObject. Answer newObject."
  35781.     
  35782.     | index |
  35783.     index _ self find: oldObject.
  35784.     self insert: newObject before: index + 1.
  35785.     ^newObject!
  35786. add: newObject before: oldObject 
  35787.     "Add the argument, newObject, as an element of the receiver. Put it in 
  35788.     the sequence just preceding oldObject. Answer newObject."
  35789.     
  35790.     | index |
  35791.     index _ self find: oldObject.
  35792.     self insert: newObject before: index.
  35793.     ^newObject!
  35794. addAll: anOrderedCollection 
  35795.     "Add each element of anOrderedCollection at my end. Answer
  35796.     anOrderedCollection."
  35797.  
  35798.     ^self addAllLast: anOrderedCollection!
  35799. addAllFirst: anOrderedCollection 
  35800.     "Add each element of anOrderedCollection at the beginning of the 
  35801.     receiver. Answer anOrderedCollection."
  35802.  
  35803.     anOrderedCollection reverseDo: [:each | self addFirst: each].
  35804.     ^anOrderedCollection!
  35805. addAllLast: anOrderedCollection 
  35806.     "Add each element of anOrderedCollection at the end of the receiver. 
  35807.     Answer anOrderedCollection."
  35808.  
  35809.     anOrderedCollection do: [:each | self addLast: each].
  35810.     ^anOrderedCollection!
  35811. addFirst: newObject 
  35812.     "Add newObject to the beginning of the receiver. Answer newObject."
  35813.  
  35814.     firstIndex = 1 ifTrue: [self makeRoomAtFirst].
  35815.     firstIndex _ firstIndex - 1.
  35816.     array at: firstIndex put: newObject.
  35817.     ^ newObject!
  35818. addLast: newObject 
  35819.     "Add newObject to the end of the receiver. Answer newObject."
  35820.  
  35821.     lastIndex = array size ifTrue: [self makeRoomAtLast].
  35822.     lastIndex _ lastIndex + 1.
  35823.     array at: lastIndex put: newObject.
  35824.     ^ newObject!
  35825. grow
  35826.     "Become larger. Typically, a subclass has to override this if the subclass
  35827.     adds instance variables."
  35828.     | newArray |
  35829.     newArray _ Array new: self size + self growSize.
  35830.     newArray replaceFrom: 1 to: array size with: array startingAt: 1.
  35831.     array _ newArray!
  35832. growSize
  35833.     ^ array size max: 2! !
  35834.  
  35835. !OrderedCollection methodsFor: 'removing'!
  35836. remove: oldObject ifAbsent: absentBlock
  35837.  
  35838.     | index |
  35839.     index _ firstIndex.
  35840.     [index <= lastIndex]
  35841.         whileTrue: 
  35842.             [oldObject = (array at: index)
  35843.                 ifTrue: 
  35844.                     [self removeIndex: index.
  35845.                     ^ oldObject]
  35846.                 ifFalse: [index _ index + 1]].
  35847.     ^ absentBlock value!
  35848. removeAllSuchThat: aBlock 
  35849.     "Evaluate aBlock for each element of the receiver. Remove each element     for which aBlock evaluates to true. Answer an OrderedCollection of the 
  35850.     removed elements."
  35851.     | index element newCollection |
  35852.     newCollection _ self species new.
  35853.     index _ firstIndex.
  35854.     [index <= lastIndex]
  35855.         whileTrue: 
  35856.             [element _ array at: index.
  35857.             (aBlock value: element)
  35858.                 ifTrue: 
  35859.                     [newCollection add: element.
  35860.                     self removeIndex: index]
  35861.                 ifFalse: [index _ index + 1]].
  35862.     ^newCollection!
  35863. removeAt: index
  35864.  
  35865.     ^self removeIndex: index + firstIndex - 1!
  35866. removeFirst
  35867.     "Remove the first element of the receiver and answer it. If the receiver is 
  35868.     empty, create an error notification."
  35869.     | firstObject |
  35870.     self emptyCheck.
  35871.     firstObject _ array at: firstIndex.
  35872.     array at: firstIndex put: nil.
  35873.     firstIndex _ firstIndex + 1.
  35874.     ^ firstObject!
  35875. removeLast
  35876.     "Remove the last element of the receiver and answer it. If the receiver is 
  35877.     empty, create an error notification."
  35878.     | lastObject |
  35879.     self emptyCheck.
  35880.     lastObject _ array at: lastIndex.
  35881.     array at: lastIndex put: nil.
  35882.     lastIndex _ lastIndex - 1.
  35883.     ^ lastObject! !
  35884.  
  35885. !OrderedCollection methodsFor: 'enumerating'!
  35886. collect: aBlock 
  35887.     "Evaluate aBlock with each of my elements as the argument. Collect the 
  35888.     resulting values into a collection that is like me. Answer the new 
  35889.     collection. Override superclass in order to use add:, not at:put:."
  35890.  
  35891.     | newCollection |
  35892.     newCollection _ self species new.
  35893.     self do: [:each | newCollection add: (aBlock value: each)].
  35894.     ^newCollection!
  35895. do: aBlock 
  35896.     "Override the superclass for performance reasons."
  35897.     | index |
  35898.     index _ firstIndex.
  35899.     [index <= lastIndex]
  35900.         whileTrue: 
  35901.             [aBlock value: (array at: index).
  35902.             index _ index + 1]!
  35903. reverseDo: aBlock 
  35904.     "Override the superclass for performance reasons."
  35905.     | index |
  35906.     index _ lastIndex.
  35907.     [index >= firstIndex]
  35908.         whileTrue: 
  35909.             [aBlock value: (array at: index).
  35910.             index _ index - 1]!
  35911. select: aBlock 
  35912.     "Evaluate aBlock with each of my elements as the argument. Collect into
  35913.     a new collection like the receiver, only those elements for which aBlock
  35914.     evaluates to true. Override the superclass in order to use add:, not at:put:."
  35915.     | newCollection |
  35916.     newCollection _ self copyEmpty.
  35917.     self do: [:each | (aBlock value: each) ifTrue: [newCollection add: each]].
  35918.     ^ newCollection! !
  35919.  
  35920. !OrderedCollection methodsFor: 'private'!
  35921. collector  "Private"
  35922.     ^ array!
  35923. errorConditionNotSatisfied
  35924.  
  35925.     self error: 'no element satisfies condition'!
  35926. errorFirstObject
  35927.  
  35928.     self error: 'specified object is first object'!
  35929. errorLastObject
  35930.  
  35931.     self error: 'specified object is last object'!
  35932. errorNoSuchElement
  35933.  
  35934.     self error: 'attempt to index non-existent element in an ordered collection'!
  35935. errorNotFound
  35936.  
  35937.     self error: 'element not found'!
  35938. find: oldObject
  35939.     | index |
  35940.     index _ firstIndex.
  35941.     [index <= lastIndex and: [oldObject ~= (array at: index)]]
  35942.         whileTrue: [index _ index + 1].
  35943.     index <= lastIndex
  35944.         ifTrue: [^ index]
  35945.         ifFalse: [self errorNotFound]!
  35946. insert: anObject before: spot
  35947.     | index delta spotIndex|
  35948.     spotIndex _ spot.
  35949.     delta _ spotIndex - firstIndex.
  35950.     firstIndex = 1
  35951.         ifTrue: 
  35952.             [self makeRoomAtFirst.
  35953.             spotIndex _ firstIndex + delta].
  35954.     index _ firstIndex _ firstIndex - 1.
  35955.     [index < (spotIndex - 1)]
  35956.         whileTrue: 
  35957.             [array at: index put: (array at: index + 1).
  35958.             index _ index + 1].
  35959.     array at: index put: anObject.
  35960.     ^ anObject!
  35961. makeRoomAtFirst
  35962.     | delta index |
  35963.     delta _ array size - self size.
  35964.     delta = 0 ifTrue: 
  35965.             [self grow.
  35966.             delta _ array size - self size].
  35967.     lastIndex = array size ifTrue: [^ self]. "just in case we got lucky"
  35968.     index _ array size.
  35969.     [index > delta]
  35970.         whileTrue: 
  35971.             [array at: index put: (array at: index - delta + firstIndex - 1).
  35972.             array at: index - delta + firstIndex - 1 put: nil.
  35973.             index _ index - 1].
  35974.     firstIndex _ delta + 1.
  35975.     lastIndex _ array size!
  35976. makeRoomAtLast
  35977.     | index newLast delta |
  35978.     newLast _ self size.
  35979.     array size - self size = 0 ifTrue: [self grow].
  35980.     (delta _ firstIndex - 1) = 0 ifTrue: [^ self].
  35981.     "we might be here under false premises or grow did the job for us"
  35982.     1 to: newLast do:
  35983.         [:index |
  35984.         array at: index put: (array at: index + delta).
  35985.         array at: index + delta put: nil].
  35986.     firstIndex _ 1.
  35987.     lastIndex _ newLast!
  35988. removeIndex: removedIndex
  35989.     | index |
  35990.     index _ removedIndex.
  35991.     [index < lastIndex]
  35992.         whileTrue: 
  35993.             [array at: index put: (array at: index + 1).
  35994.             index _ index + 1].
  35995.     array at: lastIndex put: nil.
  35996.     lastIndex _ lastIndex - 1!
  35997. setCollection: anArray
  35998.     array _ anArray.
  35999.     firstIndex _ array size // 3 max: 1.
  36000.     lastIndex _ firstIndex - 1 max: 0! !
  36001. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  36002.  
  36003. OrderedCollection class
  36004.     instanceVariableNames: ''!
  36005.  
  36006. !OrderedCollection class methodsFor: 'instance creation'!
  36007. new
  36008.  
  36009.     ^self new: 10!
  36010. new: anInteger 
  36011.     "If a subclass adds fields, then it is necessary for that subclass to
  36012.     reimplement new:."
  36013.  
  36014.     ^ super new setCollection: (Array new: anInteger)!
  36015. newFrom: aCollection 
  36016.     "Answer an instance of me containing the same elements as aCollection."
  36017.  
  36018.     | newCollection |
  36019.     newCollection _ self new: aCollection size.
  36020.     newCollection addAll: aCollection.
  36021.     ^newCollection
  36022.  
  36023. "    OrderedCollection newFrom: {1. 2. 3}
  36024.     {1. 2. 3} as: OrderedCollection
  36025.     {4. 2. 7} as: SortedCollection
  36026. "! !Inspector subclass: #OrderedCollectionInspector
  36027.     instanceVariableNames: ''
  36028.     classVariableNames: ''
  36029.     poolDictionaries: ''
  36030.     category: 'Interface-Inspector'!
  36031.  
  36032. !OrderedCollectionInspector methodsFor: 'as yet unclassified'!
  36033. fieldList
  36034.     ^ self baseFieldList ,
  36035.         (object size <= (self i1 + self i2)
  36036.             ifTrue: [(1 to: object size)
  36037.                         collect: [:i | i printString]]
  36038.             ifFalse: [(1 to: self i1) , (object size-(self i2-1) to: object size)
  36039.                         collect: [:i | i printString]])"
  36040. OrderedCollection new inspect
  36041. (OrderedCollection newFrom: #(3 5 7 123)) inspect
  36042. (OrderedCollection newFrom: (1 to: 1000)) inspect
  36043. "!
  36044. replaceSelectionValue: anObject 
  36045.     "The receiver has a list of variables of its inspected object. One of these 
  36046.     is selected. The value of the selected variable is set to the value, 
  36047.     anObject."
  36048.     | basicIndex |
  36049.     (selectionIndex - 2) <= object class instSize
  36050.         ifTrue: [^ super replaceSelectionValue: anObject].
  36051.     basicIndex _ selectionIndex - 2 - object class instSize.
  36052.     (object size <= (self i1 + self i2)  or: [basicIndex <= self i1])
  36053.         ifTrue: [^object at: basicIndex put: anObject]
  36054.         ifFalse: [^object at: object size - (self i1 + self i2) + basicIndex
  36055.                     put: anObject]!
  36056. selection
  36057.     "The receiver has a list of variables of its inspected object.
  36058.     One of these is selected. Answer the value of the selected variable."
  36059.     | basicIndex |
  36060.     (selectionIndex - 2) <= object class instSize
  36061.         ifTrue: [^ super selection].
  36062.     basicIndex _ selectionIndex - 2 - object class instSize.
  36063.     (object size <= (self i1 + self i2)  or: [basicIndex <= self i1])
  36064.         ifTrue: [^ object at: basicIndex]
  36065.         ifFalse: [^ object at: object size - (self i1 + self i2) + basicIndex]! !DisplayText subclass: #Paragraph
  36066.     instanceVariableNames: 'clippingRectangle compositionRectangle destinationForm rule mask marginTabsLevel lines lastLine '
  36067.     classVariableNames: ''
  36068.     poolDictionaries: 'TextConstants '
  36069.     category: 'Graphics-Display Objects'!
  36070. Paragraph comment:
  36071. 'I represent displayable text that has been decoraged with margin alignment, line leading, and tab settings.'!
  36072.  
  36073. !Paragraph methodsFor: 'accessing'!
  36074. clippingRectangle 
  36075.     "Answer the rectangle, defined in absolute coordinates, whose 
  36076.     intersection with the destinationForm is the area in which the characters 
  36077.     are constrained to display."
  36078.  
  36079.     ^clippingRectangle!
  36080. compositionRectangle
  36081.     "Answer the rectangle whose width is the dimension, modified by 
  36082.     indents and tabsLevels, against which line wraparound is measured. The 
  36083.     height of the compositionRectangle is reset each time recomposition is 
  36084.     required."
  36085.  
  36086.     ^compositionRectangle!
  36087. compositionRectangle: compRectangle 
  36088.     "Set the rectangle whose width is the dimension, modified by indents and 
  36089.     tabsLevels, against which line wraparound is measured."
  36090.  
  36091.     compositionRectangle _ compRectangle.
  36092.     self composeAll!
  36093. destinationForm 
  36094.      "Answer the Form into which the characters are scanned."
  36095.  
  36096.     ^destinationForm!
  36097. fillColor 
  36098.     "Answer the Form with which each character is combined by the scanner 
  36099.     before applying the rule for display."
  36100.  
  36101.     ^mask!
  36102. fillColor: maskForm 
  36103.     "Set the argument, maskForm, to be the form with which each character 
  36104.     is combined by the scanner before applying the rule for display."
  36105.  
  36106.     mask _ maskForm!
  36107. height 
  36108.     "Answer the height of the composition rectangle."
  36109.  
  36110.     ^compositionRectangle height!
  36111. indentationOfLineIndex: lineIndex ifBlank: aBlock
  36112.     "Answer the number of leading tabs in the line at lineIndex.  If there are
  36113.      no visible characters, pass the number of tabs to aBlock and return its value.
  36114.      If the line is word-wrap overflow, back up a line and recur."
  36115.  
  36116.     | arrayIndex first last reader leadingTabs lastSeparator cr tab ch |
  36117.     cr _ Character cr.
  36118.     tab _ Character tab.
  36119.     arrayIndex _ lineIndex.
  36120.     [first _ (lines at: arrayIndex) first.
  36121.      first > 1 and: [(text string at: first - 1) ~~ cr]] whileTrue: "word wrap"
  36122.         [arrayIndex _ arrayIndex - 1].
  36123.     last _ (lines at: lastLine) last.
  36124.     reader _ ReadStream on: text string from: first to: last.
  36125.     leadingTabs _ 0.
  36126.     [reader atEnd not and: [(ch _ reader next) == tab]]
  36127.         whileTrue: [leadingTabs _ leadingTabs + 1].
  36128.     lastSeparator _ first - 1 + leadingTabs.
  36129.     [reader atEnd not and: [ch isSeparator and: [ch ~~ cr]]]
  36130.         whileTrue: [lastSeparator _ lastSeparator + 1. ch _ reader next].
  36131.     lastSeparator = last | (ch == cr)
  36132.         ifTrue: [^aBlock value: leadingTabs].
  36133.     ^leadingTabs!
  36134. mask 
  36135.     "Answer the Form with which each character is combined by the scanner 
  36136.     before applying the rule for display."
  36137.  
  36138.     ^mask!
  36139. numberOfLines 
  36140.     "Answer the number of lines of text in the receiver."
  36141.  
  36142.     ^lastLine!
  36143. replaceFrom: start to: stop with: aText displaying: displayBoolean
  36144.     "Replace the receiver's text starting at position start, stopping at stop, by 
  36145.     the characters in aText. It is expected that most requirements for 
  36146.     modifications to the receiver will call this code. Certainly all cut's or 
  36147.     paste's." 
  36148.  
  36149.     | compositionScanner obsoleteLines obsoleteLastLine firstLineIndex lastLineIndex
  36150.     startLine stopLine replacementRange visibleRectangle startIndex newLine done
  36151.     newStop obsoleteY newY upOrDown moveRectangle |
  36152.  
  36153.     text            "Update the text."
  36154.       replaceFrom: start to: stop with: aText.
  36155.     lastLine = 0
  36156.       ifTrue:     ["if lines have never been set up, measure them and display
  36157.                     all the lines falling in the visibleRectangle"
  36158.                 self composeAll.
  36159.                 displayBoolean
  36160.                     ifTrue:    [^ self displayLines: (1 to: lastLine)]].
  36161.  
  36162.     "save -- things get pretty mashed as we go along"
  36163.     obsoleteLines _ lines copy.
  36164.     obsoleteLastLine _ lastLine.
  36165.  
  36166.         "find the starting and stopping lines"
  36167.     firstLineIndex _ startLine _ self lineIndexOfCharacterIndex: start.
  36168.     stopLine _ self lineIndexOfCharacterIndex: stop.
  36169.         "how many characters being inserted or deleted -- negative if
  36170.             aText size is < characterInterval size."
  36171.     replacementRange _ aText size - (stop - start + 1).
  36172.         "Give ourselves plenty of elbow room."
  36173.     compositionRectangle height: textStyle lineGrid * 8196.    "max Vector length"
  36174.         "build a boundingBox of the actual screen space in question -- we'll need it later"
  36175.     visibleRectangle _ (clippingRectangle intersect: compositionRectangle)
  36176.                             intersect: destinationForm boundingBox.
  36177.         "Initialize a scanner."
  36178.     compositionScanner _ CompositionScanner new in: self.
  36179.  
  36180.         "If the starting line is not also the first line, then measuring must commence from line preceding the one in which characterInterval start appears.  For example, deleting a line with only a carriage return may move characters following the deleted portion of text into the line preceding the deleted line."
  36181.     startIndex _ (lines at: firstLineIndex) first.
  36182.     startLine > 1
  36183.         ifTrue:     [newLine _
  36184.                     compositionScanner
  36185.                         composeLine: startLine - 1
  36186.                         fromCharacterIndex: (lines at: startLine - 1) first
  36187.                         inParagraph: self.
  36188.                 (lines at: startLine - 1) = newLine
  36189.                     ifFalse:    ["start in line preceding the one with the starting character"
  36190.                             startLine _ startLine - 1.
  36191.                             self lineAt: startLine put: newLine.
  36192.                             startIndex _ newLine last + 1]].
  36193.     startIndex > text size
  36194.         ifTrue:     ["nil lines after a deletion -- remeasure last line below"
  36195.                 self trimLinesTo: (firstLineIndex - 1 max: 0).
  36196.                 text size = 0
  36197.                     ifTrue:    ["entire text deleted -- clear visibleRectangle and return."
  36198.                             destinationForm
  36199.                                  fill: visibleRectangle rule: rule fillColor: self backgroundColor.
  36200.                             self updateCompositionHeight.
  36201.                             ^self]].
  36202.  
  36203.     "Now we really get to it."
  36204.     done _ false.
  36205.     lastLineIndex _ stopLine.
  36206.     [done or: [startIndex > text size]]
  36207.         whileFalse: 
  36208.         [self lineAt: firstLineIndex put:
  36209.             (newLine _ compositionScanner composeLine: firstLineIndex
  36210.                             fromCharacterIndex: startIndex inParagraph: self).
  36211.         [(lastLineIndex > obsoleteLastLine
  36212.             or: ["no more old lines to compare with?"
  36213.                 newLine last <
  36214.                     (newStop _ (obsoleteLines at: lastLineIndex) last + replacementRange)])
  36215.                   or: [done]]
  36216.             whileFalse: 
  36217.             [newStop = newLine last
  36218.                 ifTrue:    ["got the match"
  36219.                         upOrDown _ replacementRange < 0
  36220.                             ifTrue: [0] ifFalse: [1].
  36221.                             "get source and dest y's for moving the unchanged lines"
  36222.                         obsoleteY _ self topAtLineIndex: lastLineIndex + upOrDown.
  36223.                         newY _ self topAtLineIndex: firstLineIndex + upOrDown.
  36224.                         stopLine _ firstLineIndex.
  36225.                         done _ true.
  36226.                             "Fill in the new line vector with the old unchanged lines.
  36227.                             Update their starting and stopping indices on the way."
  36228.                         ((lastLineIndex _ lastLineIndex + 1) to: obsoleteLastLine) do:
  36229.                             [:upDatedIndex | 
  36230.                             self lineAt: (firstLineIndex _ firstLineIndex + 1) 
  36231.                                 put: ((obsoleteLines at: upDatedIndex)
  36232.                                       slide: replacementRange)].
  36233.                             "trim off obsolete lines, if any"
  36234.                         self trimLinesTo: firstLineIndex]
  36235.                 ifFalse:    [lastLineIndex _ lastLineIndex + 1]].
  36236.         startIndex _ newLine last + 1.
  36237.         firstLineIndex _ firstLineIndex + 1].
  36238.  
  36239.     "Now the lines are up to date -- Whew!!.  What remains is to move
  36240.     the 'unchanged' lines and display those which have changed."
  36241.     displayBoolean   "Not much to do if not displaying"
  36242.         ifFalse: [^ self updateCompositionHeight].
  36243.  
  36244.     startIndex > text size
  36245.         ifTrue:
  36246.         ["If at the end of previous lines simply display lines from the line in
  36247.         which the first character of the replacement occured through the
  36248.         end of the paragraph."
  36249.         self updateCompositionHeight.
  36250.         self displayLines:
  36251.             (startLine to: (stopLine _ firstLineIndex min: lastLine)).
  36252.         destinationForm  "Clear out area at the bottom"
  36253.             fill: ((visibleRectangle left @ (self topAtLineIndex: lastLine + 1)
  36254.                         extent: visibleRectangle extent)
  36255.                     intersect: visibleRectangle)
  36256.             rule: rule fillColor: self backgroundColor]
  36257.         ifFalse:
  36258.         [newY ~= obsoleteY ifTrue:
  36259.             ["Otherwise first move the unchanged lines within
  36260.             the visibleRectangle with a good old bitblt."
  36261.             moveRectangle _
  36262.                 visibleRectangle left @ (obsoleteY max: visibleRectangle top)
  36263.                     corner: visibleRectangle corner.
  36264.             destinationForm copyBits: moveRectangle from: destinationForm
  36265.                 at: moveRectangle origin + (0 @ (newY-obsoleteY))
  36266.                 clippingBox: visibleRectangle
  36267.                 rule: Form over fillColor: nil].
  36268.  
  36269.         "Then display the altered lines."
  36270.         self displayLines: (startLine to: stopLine).
  36271.  
  36272.         newY < obsoleteY
  36273.             ifTrue:
  36274.             [(self topAtLineIndex: obsoleteLastLine + 1) > visibleRectangle bottom
  36275.                 ifTrue:
  36276.                 ["A deletion may have 'pulled' previously undisplayed lines
  36277.                 into the visibleRectangle.  If so, display them."
  36278.                 self displayLines:
  36279.                     ((self lineIndexOfTop: visibleRectangle bottom - (obsoleteY - newY))
  36280.                         to: (self lineIndexOfTop: visibleRectangle bottom))].
  36281.             "Clear out obsolete material at the bottom of the visibleRectangle."
  36282.             destinationForm
  36283.                 fill: ((visibleRectangle left @ (self topAtLineIndex: lastLine + 1)
  36284.                         extent: visibleRectangle extent)
  36285.                     intersect: visibleRectangle)
  36286.                 rule: rule fillColor: self backgroundColor].
  36287.  
  36288.         (newY > obsoleteY and: [obsoleteY < visibleRectangle top])
  36289.             ifTrue:
  36290.                 ["An insertion may have 'pushed' previously undisplayed lines
  36291.                 into the visibleRectangle.  If so, display them."
  36292.                 self displayLines:
  36293.                     ((self lineIndexOfTop: obsoleteY)
  36294.                         to: (self lineIndexOfTop: visibleRectangle top))].
  36295.  
  36296.         self updateCompositionHeight]!
  36297. rule 
  36298.     "Answer the rule according to which character display behaves. For 
  36299.     example, rule may equal over, under, reverse."
  36300.  
  36301.     ^rule!
  36302. rule: ruleInteger 
  36303.     "Set the rule according to which character display behaves."
  36304.  
  36305.     rule _ ruleInteger!
  36306. text: aText 
  36307.     "Set the argument, aText, to be the text for the receiver."
  36308.  
  36309.     text _ aText.
  36310.     self composeAll! !
  36311.  
  36312. !Paragraph methodsFor: 'displaying'!
  36313. displayOn: aDisplayMedium
  36314.     "Because Paragraphs cache so much information, computation is avoided
  36315.     and displayAt: 0@0 is not appropriate here."
  36316.  
  36317.     self displayOn: aDisplayMedium
  36318.         at: compositionRectangle topLeft
  36319.         clippingBox: clippingRectangle
  36320.         rule: rule
  36321.         fillColor: mask!
  36322. displayOn: aDisplayMedium at: aPoint
  36323.     "Use internal clippingRect; destination cliping is done during actual display."
  36324.  
  36325.     self displayOn: aDisplayMedium at: aPoint
  36326.         clippingBox: (clippingRectangle translateBy: aPoint - compositionRectangle topLeft)
  36327.         rule: rule fillColor: mask!
  36328. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
  36329.     "Default display message when aDisplayPoint is in absolute screen
  36330.     coordinates."
  36331.  
  36332.     rule _ ruleInteger.
  36333.     mask _ aForm.
  36334.     clippingRectangle _ clipRectangle.
  36335.     compositionRectangle moveTo: aDisplayPoint.
  36336.     (lastLine == nil or: [lastLine < 1]) ifTrue: [self composeAll].
  36337.     self displayOn: aDisplayMedium lines: (1 to: lastLine)!
  36338. displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle align: alignmentPoint with: relativePoint rule: ruleInteger fillColor: aForm 
  36339.  
  36340.     self                "Assumes offset has been set!!!!!!!!!!"
  36341.       displayOn: aDisplayMedium
  36342.       at: (offset 
  36343.             + (displayTransformation applyTo: relativePoint) 
  36344.             - alignmentPoint) rounded
  36345.       clippingBox: clipRectangle
  36346.       rule: ruleInteger
  36347.       fillColor: aForm.
  36348.     ! !
  36349.  
  36350. !Paragraph methodsFor: 'display box access'!
  36351. boundingBox
  36352.  
  36353.     ^offset extent: compositionRectangle extent!
  36354. computeBoundingBox
  36355.  
  36356.     ^offset extent: compositionRectangle extent! !
  36357.  
  36358. !Paragraph methodsFor: 'composition'!
  36359. composeAll
  36360.     "Compose a collection of characters into a collection of lines."
  36361.  
  36362.     | startIndex stopIndex lineIndex maximumRightX compositionScanner |
  36363.     lines _ Array new: 32.
  36364.     lastLine _ 0.
  36365.     maximumRightX _ 0.
  36366.     text size = 0
  36367.         ifTrue:
  36368.             [compositionRectangle height: 0.
  36369.             ^maximumRightX].
  36370.     startIndex _ lineIndex _ 1.
  36371.     stopIndex _ text size.
  36372.     compositionScanner _ CompositionScanner new in: self.
  36373.     [startIndex > stopIndex] whileFalse: 
  36374.         [self lineAt: lineIndex 
  36375.                 put: (compositionScanner composeLine: lineIndex 
  36376.                                         fromCharacterIndex: startIndex 
  36377.                                         inParagraph: self).
  36378.          maximumRightX _ compositionScanner rightX max: maximumRightX.
  36379.          startIndex _ (lines at: lineIndex) last + 1.
  36380.          lineIndex _ lineIndex + 1].
  36381.     self updateCompositionHeight.
  36382.     self trimLinesTo: lineIndex - 1.
  36383.     ^maximumRightX!
  36384. wrappingBox: compositionRect clippingBox: clippingRect 
  36385.     "Set the composition rectangle for the receiver so that the lines wrap 
  36386.     within the rectangle, compositionRect, and the display of the text is 
  36387.     clipped by the rectangle, clippingRect."
  36388.  
  36389.     self compositionRectangle: compositionRect copy
  36390.                 text: text
  36391.                 style: textStyle
  36392.                 offset: offset.
  36393.     clippingRectangle _ clippingRect copy! !
  36394.  
  36395. !Paragraph methodsFor: 'character location'!
  36396. characterBlockAtPoint: aPoint 
  36397.     "Answer a CharacterBlock for characters in the text at point aPoint. It is 
  36398.     assumed that aPoint has been transformed into coordinates appropriate to 
  36399.     the receiver's destinationForm rectangle and the compositionRectangle."
  36400.  
  36401.     ^CharacterBlockScanner new characterBlockAtPoint: aPoint in: self!
  36402. characterBlockForIndex: targetIndex 
  36403.     "Answer a CharacterBlock for character in the text at targetIndex. The 
  36404.     coordinates in the CharacterBlock will be appropriate to the intersection 
  36405.     of the destinationForm rectangle and the compositionRectangle."
  36406.  
  36407.     ^CharacterBlockScanner new characterBlockForIndex: targetIndex in: self! !
  36408.  
  36409. !Paragraph methodsFor: 'selecting'!
  36410. extendSelectionAt: beginBlock endBlock: endBlock 
  36411.     "Answer with an Array of two CharacterBlocks that represent the text 
  36412.     selection that the user makes."
  36413.     
  36414.     (self characterBlockAtPoint: Sensor cursorPoint) <= beginBlock
  36415.         ifTrue: [^self mouseMovedFrom: beginBlock 
  36416.                     pivotBlock: endBlock
  36417.                     showingCaret: (beginBlock = endBlock)]
  36418.         ifFalse: [^self mouseMovedFrom: endBlock 
  36419.                     pivotBlock: beginBlock
  36420.                     showingCaret: (beginBlock = endBlock)]
  36421. !
  36422. hiliteRect: rect
  36423.     (rect ~~ nil) ifTrue:
  36424.         [ destinationForm
  36425.             fill: rect
  36426.             rule: Form reverse
  36427.             fillColor: destinationForm highLight.
  36428.         "destinationForm
  36429.             fill: (rect translateBy: 1@1)
  36430.             rule: Form reverse
  36431.             fillColor: destinationForm highLight" ].
  36432. !
  36433. mouseMovedFrom: beginBlock pivotBlock: pivotBlock showingCaret: caretOn 
  36434.     | startBlock stopBlock showingCaret |
  36435.     stopBlock _ startBlock _ beginBlock.
  36436.     showingCaret _ caretOn.
  36437.     [Sensor redButtonPressed]
  36438.         whileTrue: 
  36439.             [stopBlock _ self characterBlockAtPoint: Sensor cursorPoint.
  36440.             stopBlock = startBlock
  36441.                 ifFalse: 
  36442.                     [showingCaret
  36443.                         ifTrue: 
  36444.                             [showingCaret _ false.
  36445.                             self reverseFrom: pivotBlock to: pivotBlock].
  36446.             ((startBlock >= pivotBlock and: [stopBlock >= pivotBlock])
  36447.                 or: [startBlock <= pivotBlock and: [stopBlock <= pivotBlock]])
  36448.                 ifTrue: 
  36449.                     [self reverseFrom: startBlock to: stopBlock.
  36450.                     startBlock _ stopBlock]
  36451.                 ifFalse: 
  36452.                     [self reverseFrom: startBlock to: pivotBlock.
  36453.                     self reverseFrom: pivotBlock to: stopBlock.
  36454.                     startBlock _ stopBlock].
  36455.             (clippingRectangle contains: stopBlock) ifFalse:
  36456.                 [stopBlock top < clippingRectangle top
  36457.                 ifTrue: [self scrollBy: stopBlock top - clippingRectangle top
  36458.                         withSelectionFrom: pivotBlock to: stopBlock]
  36459.                 ifFalse: [self scrollBy: stopBlock bottom + textStyle lineGrid - clippingRectangle bottom
  36460.                         withSelectionFrom: pivotBlock to: stopBlock]]]].
  36461.     pivotBlock = stopBlock ifTrue:
  36462.         [showingCaret ifFalse:  "restore caret"
  36463.             [self reverseFrom: pivotBlock to: pivotBlock]].
  36464.     ^ Array with: pivotBlock with: stopBlock!
  36465. mouseSelect
  36466.     "Answer with an Array of two CharacterBlocks that represent the text 
  36467.     selection that the user makes.  Return quickly if the button is noticed up
  36468.     to make double-click more responsive."
  36469.  
  36470.     | pivotBlock startBlock stopBlock origPoint stillDown |
  36471.     stillDown _ Sensor redButtonPressed.
  36472.     pivotBlock _ startBlock _ stopBlock _
  36473.         self characterBlockAtPoint: (origPoint _ Sensor cursorPoint).
  36474.     stillDown _ stillDown and: [Sensor redButtonPressed].
  36475.     self reverseFrom: startBlock to: startBlock.
  36476.     [stillDown and: [Sensor cursorPoint = origPoint]] whileTrue:
  36477.         [stillDown _ Sensor redButtonPressed].
  36478.     (stillDown and: [clippingRectangle containsPoint: Sensor cursorPoint])
  36479.         ifFalse: [^Array with: pivotBlock with: stopBlock].
  36480.     ^ self mouseMovedFrom: startBlock 
  36481.         pivotBlock: pivotBlock
  36482.         showingCaret: true!
  36483. mouseSelect: clickPoint 
  36484.     "Track text selection and answer with an Array of two CharacterBlocks."
  36485.     | startBlock |
  36486.     startBlock _ self characterBlockAtPoint: clickPoint.
  36487.     self reverseFrom: startBlock to: startBlock.
  36488.     ^ self mouseMovedFrom: startBlock 
  36489.         pivotBlock: startBlock
  36490.         showingCaret: true!
  36491. reverseFrom: characterBlock1 to: characterBlock2 
  36492.     "Reverse area between the two character blocks given as arguments."
  36493.     | visibleRectangle initialRectangle interiorRectangle finalRectangle |
  36494.     characterBlock1 = characterBlock2
  36495.         ifTrue: [^ CaretForm  "Use a caret to indicate null selection"
  36496.                     displayOn: destinationForm
  36497.                     at: characterBlock1 topLeft + (0 @ textStyle baseline)
  36498.                     clippingBox: clippingRectangle
  36499.                     rule: (Display depth>8
  36500.                             ifTrue: [9 "not-reverse"]
  36501.                             ifFalse: [Form reverse])
  36502.                     fillColor: nil].
  36503.     visibleRectangle _ 
  36504.         (clippingRectangle intersect: compositionRectangle)
  36505.             "intersect: destinationForm boundingBox" "not necessary".
  36506.     characterBlock1 top = characterBlock2 top
  36507.         ifTrue: [characterBlock1 left < characterBlock2 left
  36508.                     ifTrue: 
  36509.                         [initialRectangle _ 
  36510.                             (characterBlock1 topLeft corner: characterBlock2 bottomLeft)
  36511.                                 intersect: visibleRectangle]
  36512.                     ifFalse: 
  36513.                         [initialRectangle _ 
  36514.                             (characterBlock2 topLeft corner: characterBlock1 bottomLeft)
  36515.                                 intersect: visibleRectangle]]
  36516.         ifFalse: [characterBlock1 top < characterBlock2 top
  36517.                     ifTrue: 
  36518.                         [initialRectangle _ 
  36519.                             (characterBlock1 topLeft 
  36520.                                 corner: visibleRectangle right @ characterBlock1 bottom)
  36521.                                 intersect: visibleRectangle.
  36522.                         characterBlock1 bottom = characterBlock2 top
  36523.                             ifTrue: 
  36524.                                 [finalRectangle _ 
  36525.                                     (visibleRectangle left @ characterBlock2 top 
  36526.                                         corner: characterBlock2 bottomLeft)
  36527.                                         intersect: visibleRectangle]
  36528.                             ifFalse: 
  36529.                                 [interiorRectangle _ 
  36530.                                     (visibleRectangle left @ characterBlock1 bottom
  36531.                                         corner: visibleRectangle right 
  36532.                                                         @ characterBlock2 top)
  36533.                                         intersect: visibleRectangle.
  36534.                                 finalRectangle _ 
  36535.                                     (visibleRectangle left @ characterBlock2 top 
  36536.                                         corner: characterBlock2 bottomLeft)
  36537.                                         intersect: visibleRectangle]]
  36538.                 ifFalse: 
  36539.                     [initialRectangle _ 
  36540.                         (visibleRectangle left @ characterBlock1 top 
  36541.                             corner: characterBlock1 bottomLeft)
  36542.                             intersect: visibleRectangle.
  36543.                     characterBlock1 top = characterBlock2 bottom
  36544.                         ifTrue: 
  36545.                             [finalRectangle _ 
  36546.                                 (characterBlock2 topLeft 
  36547.                                     corner: visibleRectangle right 
  36548.                                                 @ characterBlock2 bottom)
  36549.                                     intersect: visibleRectangle]
  36550.                         ifFalse: 
  36551.                             [interiorRectangle _ 
  36552.                                 (visibleRectangle left @ characterBlock2 bottom 
  36553.                                     corner: visibleRectangle right @ characterBlock1 top)
  36554.                                     intersect: visibleRectangle.
  36555.                             finalRectangle _ 
  36556.                                 (characterBlock2 topLeft 
  36557.                                     corner: visibleRectangle right 
  36558.                                                 @ characterBlock2 bottom)
  36559.                                     intersect: visibleRectangle]]].
  36560.     self hiliteRect: initialRectangle.
  36561.     self hiliteRect: interiorRectangle.
  36562.     self hiliteRect: finalRectangle.! !
  36563.  
  36564. !Paragraph methodsFor: 'scrolling'!
  36565. scrollBy: heightToMove 
  36566.     ^ self scrollBy: heightToMove withSelectionFrom: nil to: nil!
  36567. scrollBy: heightToMove withSelectionFrom: startBlock to: stopBlock 
  36568.     "Translate the composition rectangle up (dy<0) by heightToMove.
  36569.     Repainting text as necessary, and selection if blocks not nil.
  36570.     Return true unless scrolling limits have been reached."
  36571.     | max min amount |
  36572.     max _ 0 max: "cant scroll up more than dist to (top of) bottom line"
  36573.         compositionRectangle bottom - textStyle lineGrid - clippingRectangle top.
  36574.     min _ 0 min: "cant scroll down more than top is above clipRect"
  36575.         compositionRectangle top - clippingRectangle top.
  36576.     amount _ ((heightToMove truncateTo: textStyle lineGrid) min: max) max: min.
  36577.     amount ~= 0
  36578.         ifTrue: [self scrollUncheckedBy: amount
  36579.                     withSelectionFrom: startBlock to: stopBlock.
  36580.                 ^ true]
  36581.         ifFalse: [^ false]!
  36582. scrollDelta
  36583.     "By comparing this before and after, you know if scrolling happened"
  36584.     ^ clippingRectangle top - compositionRectangle top!
  36585. scrollUncheckedBy: heightToMove withSelectionFrom: startBlock to: stopBlock 
  36586.     "Scroll by the given amount.  Copy bits where possible, display the rest.
  36587.     If selection blocks are not nil, then select the newly visible text as well."
  36588.     | savedClippingRectangle delta |
  36589.     delta _ 0 @ (0 - heightToMove).
  36590.     compositionRectangle moveBy: delta.
  36591.     startBlock == nil ifFalse:
  36592.         [startBlock moveBy: delta.
  36593.         stopBlock moveBy: delta].
  36594.     savedClippingRectangle _ clippingRectangle.
  36595.     clippingRectangle _ clippingRectangle intersect: Display boundingBox.
  36596.     heightToMove abs >= clippingRectangle height
  36597.       ifTrue: 
  36598.         ["Entire visible region must be repainted"
  36599.         self displayLines: (1 to: lastLine) affectedRectangle: clippingRectangle]
  36600.       ifFalse:
  36601.         ["Copy bits where possible / display the rest"
  36602.         destinationForm
  36603.             copyBits: clippingRectangle from: destinationForm
  36604.             at: clippingRectangle topLeft + delta
  36605.             clippingBox: clippingRectangle
  36606.             rule: Form over fillColor: nil.
  36607.         "Set clippingRectangle to 'vacated' area for lines 'pulled' into view."
  36608.         clippingRectangle _ heightToMove < 0
  36609.             ifTrue:  "On the top"
  36610.                 [clippingRectangle topLeft corner: clippingRectangle topRight + delta]
  36611.             ifFalse:  "At the bottom"
  36612.                 [clippingRectangle bottomLeft + delta corner: clippingRectangle bottomRight].
  36613.         self displayLines: (1 to: lastLine)   "Refresh vacated region"
  36614.             affectedRectangle: clippingRectangle].
  36615.     startBlock == nil ifFalse:
  36616.         [self reverseFrom: startBlock to: stopBlock].
  36617.     "And restore the clippingRectangle to its original value. "
  36618.     clippingRectangle _ savedClippingRectangle! !
  36619.  
  36620. !Paragraph methodsFor: 'alignment'!
  36621. centered 
  36622.     "Set the alignment for the style with which the receiver displays its text 
  36623.     so that text is centered in the composition rectangle."
  36624.  
  36625.     textStyle alignment: Centered!
  36626. justified 
  36627.     "Set the alignment for the style with which the receiver displays its text 
  36628.     so that the characters in each of text end on an even border in the 
  36629.     composition rectangle."
  36630.  
  36631.     textStyle alignment: Justified!
  36632. leftFlush 
  36633.     "Set the alignment for the style with which the receiver displays its text 
  36634.     so that the characters in each of text begin on an even border in the 
  36635.     composition rectangle. This is also known as ragged-right."
  36636.  
  36637.     textStyle alignment: LeftFlush!
  36638. rightFlush 
  36639.     "Set the alignment for the style with which the receiver displays its text 
  36640.     so that the characters in each of text end on an even border in the 
  36641.     composition rectangle but the beginning of each line does not. This is 
  36642.     also known as ragged-left."
  36643.  
  36644.     textStyle alignment: RightFlush!
  36645. toggleAlignment 
  36646.     "Set the alignment for the style with which the receiver displays its text 
  36647.     so that it moves from centered to justified to leftFlush to rightFlush and 
  36648.     back to centered again."
  36649.  
  36650.     textStyle alignment: textStyle alignment + 1! !
  36651.  
  36652. !Paragraph methodsFor: 'indicating'!
  36653. flash 
  36654.     "Complement twice the visible area in which the receiver displays."
  36655.  
  36656.     Display flash: clippingRectangle!
  36657. outline 
  36658.     "Display a border around the visible area in which the receiver presents 
  36659.     its text."
  36660.  
  36661.     clippingRectangle bottom <= compositionRectangle bottom
  36662.       ifTrue: [Display 
  36663.                 border: (clippingRectangle intersect: compositionRectangle) 
  36664.                 width: 2]
  36665.       ifFalse: [Display 
  36666.                 border: (clippingRectangle intersect: destinationForm boundingBox)
  36667.                 width: 2].
  36668.     ! !
  36669.  
  36670. !Paragraph methodsFor: 'utilities'!
  36671. clearVisibleRectangle 
  36672.     "Display the area in which the receiver presents its text so that the area 
  36673.     is all one tone--in this case, all white."
  36674.  
  36675.     destinationForm
  36676.       fill: clippingRectangle
  36677.       rule: rule
  36678.       fillColor: self backgroundColor!
  36679. contentsCopy
  36680.     "Refer to the comment in Object.contentsCopy.  7/28/96 sw"
  36681.  
  36682.     ^ self deepCopy release!
  36683. deepCopy
  36684.     "Don't want to copy the destForm (Display) or fonts in the TextStyle.  9/13/96 tk"
  36685.  
  36686.     | new |
  36687.     new _ self copy.
  36688.     new textStyle: textStyle copy.
  36689.     new destinationForm: destinationForm.
  36690.     new lines: lines copy.
  36691.     new text: text deepCopy.
  36692.     ^ new!
  36693. destinationForm: destForm
  36694.     destinationForm _ destForm!
  36695. fit
  36696.     "Make the bounding rectangle of the receiver contain all the text without 
  36697.     changing the width of the receiver's composition rectangle."
  36698.  
  36699.     [(self lineIndexOfTop: clippingRectangle top) = 1]
  36700.         whileFalse: [self scrollBy: (0-1)*textStyle lineGrid].
  36701.     self updateCompositionHeight.
  36702.     clippingRectangle bottom: compositionRectangle bottom!
  36703. gridWithLead: leadInteger 
  36704.     "Set the line grid of the receiver's style for displaying text to the height 
  36705.     of the first font in the receiver's style + the argument, leadInteger."
  36706.  
  36707.     textStyle 
  36708.         gridForFont: (text emphasisAt: 1)
  36709.         withLead: leadInteger        "assumes only one font referred to by runs"!
  36710. lines: lineArray
  36711.     lines _ lineArray!
  36712. visibleRectangle 
  36713.     "May be less than the clippingRectangle if text ends part way down.
  36714.     Also some fearful history includes Display intersection;
  36715.     it shouldn't be necessary"
  36716.  
  36717.     ^ (clippingRectangle intersect: compositionRectangle)
  36718.         intersect: destinationForm boundingBox! !
  36719.  
  36720. !Paragraph methodsFor: 'converting'!
  36721. asForm
  36722.     "Answer a Form made up of the bits that represent the receiver's 
  36723.     displayable text."
  36724.     | aForm |
  36725.     aForm _ Form extent: compositionRectangle extent.
  36726.     self displayOn: aForm
  36727.         at: 0 @ 0
  36728.         clippingBox: aForm boundingBox
  36729.         rule: Form over
  36730.         fillColor: nil.
  36731.     aForm offset: offset.
  36732.     ^ aForm!
  36733. asString
  36734.     "Answer the string of characters of the receiver's text."
  36735.  
  36736.     ^text string!
  36737. asText
  36738.     "Answer the receiver's text."
  36739.  
  36740.     ^text! !
  36741.  
  36742. !Paragraph methodsFor: 'private'!
  36743. compositionRectangle: compositionRect text: aText style: aTextStyle offset: aPoint
  36744.  
  36745.     compositionRectangle _ compositionRect copy.
  36746.     text _ aText.
  36747.     textStyle _ aTextStyle.
  36748.     rule _ DefaultRule.
  36749.     mask _ DefaultMask.
  36750.     marginTabsLevel _ 0.
  36751.     destinationForm _ Display.
  36752.     offset _ aPoint.
  36753.     ^self composeAll!
  36754. compositionRectangleDelta
  36755.     "A handy number -- mostly for scrolling."
  36756.  
  36757.     ^compositionRectangle top - clippingRectangle top!
  36758. displayLines: linesInterval 
  36759.     ^ self displayLines: linesInterval
  36760.         affectedRectangle: self visibleRectangle!
  36761. displayLines: linesInterval affectedRectangle: affectedRectangle
  36762.     "This is the first level workhorse in the display portion of the TextForm routines.
  36763.     It checks to see which lines in the interval are actually visible, has the
  36764.     CharacterScanner display only those, clears out the areas in which display will
  36765.     occur, and clears any space remaining in the visibleRectangle following the space
  36766.     occupied by lastLine."
  36767.  
  36768.     | lineGrid topY firstLineIndex lastLineIndex lastLineIndexBottom |
  36769.     lineGrid _ textStyle lineGrid.
  36770.     "Save some time by only displaying visible lines"
  36771.     firstLineIndex _ self lineIndexOfTop: affectedRectangle top.
  36772.     firstLineIndex < linesInterval first ifTrue: [firstLineIndex _ linesInterval first].
  36773.     lastLineIndex _ self lineIndexOfTop: affectedRectangle bottom - 1.
  36774.     lastLineIndex > linesInterval last 
  36775.         ifTrue:
  36776.             [linesInterval last > lastLine
  36777.                  ifTrue: [lastLineIndex _ lastLine]
  36778.                   ifFalse: [lastLineIndex _ linesInterval last]].
  36779.     ((Rectangle 
  36780.         origin: affectedRectangle left @ (topY _ self topAtLineIndex: firstLineIndex) 
  36781.         corner: affectedRectangle right @ 
  36782.                     (lastLineIndexBottom _ (self topAtLineIndex: lastLineIndex)
  36783.                       + lineGrid))
  36784.       intersects: affectedRectangle)
  36785.         ifTrue: [ " . . . (skip to clear-below if no lines displayed)"
  36786.     "Clear space for the lines in linesInterval."
  36787.     destinationForm
  36788.       fill: (affectedRectangle left @ (topY max: affectedRectangle top)
  36789.             corner: affectedRectangle right @ (lastLineIndexBottom min: affectedRectangle bottom))
  36790.       rule: rule fillColor: self backgroundColor.
  36791.     DisplayScanner new
  36792.       displayLines: (firstLineIndex to: lastLineIndex)
  36793.       in: self clippedBy: affectedRectangle].
  36794.     lastLineIndex = lastLine ifTrue: 
  36795.          [destinationForm  "Clear out white space below last line"
  36796.              fill: (affectedRectangle left @ (lastLineIndexBottom max: affectedRectangle top)
  36797.                 corner: affectedRectangle bottomRight)
  36798.              rule: rule fillColor: self backgroundColor]!
  36799. displayOn: aDisplayMedium lines: lineInterval
  36800.  
  36801.     | saveDestinationForm |
  36802.     saveDestinationForm _ destinationForm.
  36803.     destinationForm _ aDisplayMedium.
  36804.     self displayLines: lineInterval.
  36805.     destinationForm _ saveDestinationForm!
  36806. leftMarginForCompositionForLine: lineIndex 
  36807.     "Build the left margin for composition of a line. Depends upon
  36808.     marginTabsLevel and the indent."
  36809.  
  36810.     | indent |
  36811.     lineIndex = 1
  36812.         ifTrue: [indent _ textStyle firstIndent]
  36813.         ifFalse: [indent _ textStyle restIndent].
  36814.     ^indent + (textStyle leftMarginTabAt: marginTabsLevel)!
  36815. leftMarginForDisplayForLine: lineIndex 
  36816.     "Build the left margin for display of a line. Depends upon
  36817.     leftMarginForComposition, compositionRectangle left and the alignment."
  36818.  
  36819.     | pad |
  36820.     (textStyle alignment = LeftFlush or: [textStyle alignment = Justified])
  36821.         ifTrue: 
  36822.             [^compositionRectangle left 
  36823.                 + (self leftMarginForCompositionForLine: lineIndex)].
  36824.     "When called from character location code and entire string has been cut,
  36825.     there are no valid lines, hence following nil check."
  36826.     (lines at: lineIndex) ~~ nil
  36827.         ifTrue: 
  36828.             [pad _ (lines at: lineIndex) paddingWidth]
  36829.         ifFalse: 
  36830.             [pad _ 
  36831.                 compositionRectangle width - textStyle firstIndent - textStyle rightIndent].
  36832.     textStyle alignment = Centered 
  36833.         ifTrue: 
  36834.             [^compositionRectangle left 
  36835.                 + (self leftMarginForCompositionForLine: lineIndex) + (pad // 2)].
  36836.     textStyle alignment = RightFlush 
  36837.         ifTrue:
  36838.             [^compositionRectangle left 
  36839.                 + (self leftMarginForCompositionForLine: lineIndex) + pad].
  36840.     self error: ['no such alignment']!
  36841. lineAt: indexInteger put: aTextLineInterval 
  36842.     "Store a line, track last, and grow lines if necessary."
  36843.     indexInteger > lastLine ifTrue: [lastLine _ indexInteger].
  36844.     lastLine > lines size ifTrue: [lines _ lines , (Array new: lines size)].
  36845.     ^lines at: indexInteger put: aTextLineInterval!
  36846. lineIndexOfCharacterIndex: characterIndex 
  36847.     "Answer the line index for a given characterIndex."
  36848.  
  36849.     1 to: lastLine do: 
  36850.         [:lineIndex | 
  36851.         (lines at: lineIndex) last >= characterIndex ifTrue: [^lineIndex]].
  36852.     ^lastLine!
  36853. lineIndexOfTop: top 
  36854.     "Answer the line index at a given top y."
  36855.  
  36856.     ^(top - compositionRectangle top // textStyle lineGrid + 1 max: 1)
  36857.         min: lastLine!
  36858. lines
  36859.  
  36860.     ^lines!
  36861. removeFirstChars: numberOfChars
  36862.     "Remove a number of characters from the beginning of the receiver,
  36863.     adjusting the composition rectangle so the displayed text moves as little as
  36864.     possible. Special kludge for TextCollectorController."
  36865.     "9/14/82 SBP"
  36866.  
  36867.     | delta scrollDelta |
  36868.     delta _ ((self lineIndexOfCharacterIndex: numberOfChars)-1)*self lineGrid.
  36869.     scrollDelta _ self compositionRectangleDelta negated.
  36870.     delta > scrollDelta ifTrue:
  36871.         [delta _ scrollDelta.     "deleting some visible lines"
  36872.         self clearVisibleRectangle].
  36873.     self replaceFrom: 1 to: numberOfChars with: '' asText displaying: false.
  36874.     compositionRectangle moveBy: 0@delta.
  36875.     delta = scrollDelta ifTrue: [self display]!
  36876. rightMarginForComposition
  36877.     "Build the right margin for a line. Depends upon compositionRectangle
  36878.     width, marginTabsLevel, and right indent."
  36879.  
  36880.     ^compositionRectangle width 
  36881.         - (textStyle rightMarginTabAt: marginTabsLevel) 
  36882.         - textStyle rightIndent!
  36883. rightMarginForDisplay 
  36884.     "Build the right margin for a line. Depends upon compositionRectangle
  36885.     rightSide, marginTabsLevel, and right indent."
  36886.  
  36887.     ^compositionRectangle right - 
  36888.         textStyle rightIndent - (textStyle rightMarginTabAt: marginTabsLevel)!
  36889. setWithText: aText style: aTextStyle 
  36890.     "Set text and adjust bounding rectangles to fit."
  36891.  
  36892.     | shrink i compositionWidth unbounded |
  36893.     unbounded _ Rectangle origin: 0 @ 0 extent: 10000@10000.
  36894.     compositionWidth _ self
  36895.         setWithText: aText style: aTextStyle compositionRectangle: unbounded clippingRectangle: unbounded.
  36896.     compositionRectangle width: compositionWidth.
  36897.     clippingRectangle _ compositionRectangle copy.
  36898.     shrink _ unbounded width - compositionWidth.
  36899.     "Shrink padding widths accordingly"
  36900.     1 to: lastLine do:
  36901.         [:i | (lines at: i) paddingWidth: (lines at: i) paddingWidth - shrink]!
  36902. setWithText: aText style: aTextStyle compositionRectangle: compRect clippingRectangle: clipRect 
  36903.     "Set text and using supplied parameters. Answer max composition width."
  36904.  
  36905.     clippingRectangle _ clipRect copy.
  36906.     ^self
  36907.         compositionRectangle: compRect
  36908.         text: aText
  36909.         style: aTextStyle
  36910.         offset: 0 @ 0!
  36911. setWithText: aText style: aTextStyle compositionRectangle: compRect clippingRectangle: clipRect foreColor: cf backColor: cb
  36912.     "Set text and using supplied parameters. Answer max composition width."
  36913.  
  36914.     clippingRectangle _ clipRect copy.
  36915.     self foregroundColor: cf backgroundColor: cb.
  36916.     ^ self
  36917.         compositionRectangle: compRect
  36918.         text: aText
  36919.         style: aTextStyle
  36920.         offset: 0 @ 0!
  36921. topAtLineIndex: lineIndex 
  36922.     "Answer the top y of given line."
  36923.  
  36924.     ^compositionRectangle top + (lineIndex - 1 * textStyle lineGrid)!
  36925. trimLinesTo: lastLineInteger
  36926.  
  36927.     (lastLineInteger + 1 to: lastLine) do: [:i | lines at: i put: nil].
  36928.     (lastLine _ lastLineInteger) < (lines size // 2) 
  36929.         ifTrue: [lines _ lines copyFrom: 1 to: lines size - (lines size // 2)]!
  36930. updateCompositionHeight
  36931.     "Mainly used to insure that intersections with compositionRectangle work."
  36932.  
  36933.     compositionRectangle height: textStyle lineGrid * lastLine.
  36934.     (text size ~= 0 and: [(text at: text size) = CR])
  36935.         ifTrue: [compositionRectangle 
  36936.                     height: compositionRectangle height + textStyle lineGrid]! !
  36937. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  36938.  
  36939. Paragraph class
  36940.     instanceVariableNames: ''!
  36941.  
  36942. !Paragraph class methodsFor: 'instance creation'!
  36943. new
  36944.     "Do not allow an uninitialized view. Create with text that has no
  36945.     characters."
  36946.  
  36947.     ^self withText: '' asText!
  36948. withText: aText 
  36949.     "Answer an instance of me with text set to aText and style set to the 
  36950.     system's default text style."
  36951.  
  36952.     ^self withText: aText style: DefaultTextStyle copy!
  36953. withText: aText style: aTextStyle 
  36954.     "Answer an instance of me with text set to aText and style set to 
  36955.     aTextStyle."
  36956.  
  36957.     ^super new setWithText: aText style: aTextStyle!
  36958. withText: aText style: aTextStyle compositionRectangle: compRect clippingRectangle: clipRect foreColor: c1 backColor: c2
  36959.     "Answer an instance of me with text set to aText and style set to 
  36960.     aTextStyle, composition rectangle is compRect and the clipping rectangle 
  36961.     is clipRect."
  36962.     | para |
  36963.     para _ super new.
  36964.     para setWithText: aText
  36965.         style: aTextStyle
  36966.         compositionRectangle: compRect
  36967.         clippingRectangle: clipRect
  36968.         foreColor: c1 backColor: c2.
  36969.     ^para! !
  36970.  
  36971. !Paragraph class methodsFor: 'examples'!
  36972. example
  36973.     "This simple example illustrates how to display a few lines of text on the screen at the current cursor point. "
  36974.  
  36975.     | para point |
  36976.     point _ Sensor waitButton.
  36977.     para _ 'This is the first line of characters
  36978. and this is the second line.' asParagraph.
  36979.     para displayOn: Display at: point.
  36980.     para
  36981.         displayOn: Display
  36982.         at: point + (0 @ para height)
  36983.         clippingBox: (point + (0 @ para height) extent: para extent)
  36984.         rule: Form over
  36985.         fillColor: Color gray
  36986.  
  36987.     "Paragraph example"! !ScrollController subclass: #ParagraphEditor
  36988.     instanceVariableNames: 'paragraph startBlock stopBlock beginTypeInBlock emphasisHere initialText selectionShowing otherInterval '
  36989.     classVariableNames: 'UndoInterval UndoSelection CurrentSelection Keyboard TextEditorYellowButtonMenu TextEditorYellowButtonMessages CmdActions UndoParagraph Undone UndoMessage ShiftCmdActions FindText ChangeText '
  36990.     poolDictionaries: 'TextConstants '
  36991.     category: 'Graphics-Editors'!
  36992. ParagraphEditor comment:
  36993. 'I am a Controller for editing a Paragraph. I am a kind of ScrollController, so that more text can be created for the Paragraph than can be viewed on the screen. Editing messages are sent by issuing commands from a yellow button menu or from keys on the keyboard. My instances keep control as long as the cursor is within the view when the red or yellow mouse button is pressed; they give up control if the blue button is pressed.'!
  36994.  
  36995. !ParagraphEditor methodsFor: 'initialize-release'!
  36996. changeParagraph: aParagraph 
  36997.     "Install aParagraph as the one to be edited by the receiver."
  36998.  
  36999.     UndoParagraph == paragraph ifTrue: [UndoParagraph _ nil].
  37000.     paragraph _ aParagraph.
  37001.     self resetState!
  37002. initialize
  37003.     "Initialize a new ParagraphEditor.  It is initially not in control, so its
  37004.      would-be-instance variables, UndoInterval and PriorInterval, are stashed in
  37005.      beginTypeInBlock."
  37006.  
  37007.     super initialize.
  37008.     self initializeYellowButtonMenu.
  37009.     beginTypeInBlock _ Array with: (1 to: 0) with: (1 to: 0)!
  37010. resetState 
  37011.     "Establish the initial conditions for editing the paragraph: place caret 
  37012.     before first character, set the emphasis to that of the first character, and 
  37013.     save the paragraph for purposes of canceling."
  37014.  
  37015.     | insetDisplayBox |
  37016.     insetDisplayBox _ paragraph compositionRectangle.
  37017.     startBlock _ 
  37018.         CharacterBlock
  37019.             stringIndex: 1
  37020.             character: nil
  37021.             boundingRectangle: (insetDisplayBox topLeft extent: 0 @ 0).
  37022.     stopBlock _ startBlock copy.
  37023.     beginTypeInBlock _ nil.
  37024.     UndoInterval _ otherInterval _ 1 to: 0.
  37025.     self setEmphasisHere.
  37026.     selectionShowing _ false.
  37027.     initialText _ paragraph text copy! !
  37028.  
  37029. !ParagraphEditor methodsFor: 'accessing'!
  37030. lockModel
  37031.     "If the receiver is lock, do so to the receiver's model.  This does something real in StringHolderController, but here it is a no-op, put in so that the Character Recognizer won't fail when used with a vanilla ParagrahEditor.  8/9/96 sw"!
  37032. replace: oldInterval with: newText and: selectingBlock 
  37033.     "Replace the text in oldInterval with newText and execute selectingBlock to establish the new selection.  Create an undoAndReselect:redoAndReselect: undoer to allow perfect undoing."
  37034.  
  37035.     | undoInterval |
  37036.     undoInterval _ self selectionInterval.
  37037.     undoInterval = oldInterval ifFalse: [self selectInterval: oldInterval].
  37038.     UndoSelection _ self selection.
  37039.     self zapSelectionWith: newText.
  37040.     selectingBlock value.
  37041.     otherInterval _ self selectionInterval.
  37042.     self undoer: #undoAndReselect:redoAndReselect: with: undoInterval with: otherInterval!
  37043. replaceSelectionWith: aText
  37044.     "Remember the selection text in UndoSelection.
  37045.      Deselect, and replace the selection text by aText.
  37046.      Remember the resulting selectionInterval in UndoInterval and PriorInterval.
  37047.      Set up undo to use UndoReplace."
  37048.  
  37049.     beginTypeInBlock ~~ nil ifTrue: [^self zapSelectionWith: aText]. "called from old code"
  37050.     UndoSelection _ self selection.
  37051.     self zapSelectionWith: aText.
  37052.     self undoer: #undoReplace!
  37053. selection
  37054.     "Answer the text in the paragraph that is currently selected."
  37055.  
  37056.     ^paragraph text copyFrom: startBlock stringIndex to: stopBlock stringIndex - 1 !
  37057. selectionAsStream
  37058.     "Answer a ReadStream on the text in the paragraph that is currently 
  37059.     selected."
  37060.  
  37061.     ^ReadWriteStream
  37062.         on: paragraph string
  37063.         from: startBlock stringIndex
  37064.         to: stopBlock stringIndex - 1!
  37065. selectionInterval
  37066.     "Answer the interval that is currently selected."
  37067.  
  37068.     ^startBlock stringIndex to: stopBlock stringIndex - 1 !
  37069. setSearch: aString
  37070.     "Set the FindText and ChangeText to seek aString; except if already seeking aString, leave ChangeText alone so again will repeat last replacement."
  37071.  
  37072.     FindText string = aString
  37073.         ifFalse: [FindText _ ChangeText _ aString asText]!
  37074. text
  37075.     "Answer the text of the paragraph being edited."
  37076.  
  37077.     ^paragraph text!
  37078. zapSelectionWith: aText
  37079.     "Deselect, and replace the selection text by aText.
  37080.      Remember the resulting selectionInterval in UndoInterval and otherInterval.
  37081.      Do not set up for undo."
  37082.  
  37083.     | start stop |
  37084.     self deselect.
  37085.     start _ startBlock stringIndex.
  37086.     stop _ stopBlock stringIndex.
  37087.     (start = stop and: [aText size = 0]) ifFalse:
  37088.         [paragraph
  37089.             replaceFrom: start
  37090.             to: stop - 1
  37091.             with: aText
  37092.             displaying: true.
  37093.         self computeIntervalFrom: start to: start + aText size - 1.
  37094.         UndoInterval _ otherInterval _ self selectionInterval]! !
  37095.  
  37096. !ParagraphEditor methodsFor: 'controlling'!
  37097. controlActivity
  37098.     self scrollBarContainsCursor
  37099.         ifTrue: [self scroll]
  37100.         ifFalse: [self processKeyboard.
  37101.                 self processMouseButtons]!
  37102. controlInitialize
  37103.  
  37104.     super controlInitialize.
  37105.     self recomputeInterval.
  37106.     self initializeSelection.
  37107.     beginTypeInBlock _ nil!
  37108. controlTerminate
  37109.  
  37110.     self closeTypeIn.  "Must call to establish UndoInterval"
  37111.     super controlTerminate.
  37112.     self deselect!
  37113. isControlActive
  37114.  
  37115.     ^super isControlActive & sensor blueButtonPressed not! !
  37116.  
  37117. !ParagraphEditor methodsFor: 'scrolling'!
  37118. computeMarkerRegion 
  37119.     "Refer to the comment in ScrollController|computeMarkerRegion."
  37120.  
  37121.     paragraph compositionRectangle height = 0
  37122.         ifTrue:    [^0@0 extent: 10 @ scrollBar inside height]
  37123.         ifFalse:    [^0@0 extent:
  37124.                     10 @ ((paragraph clippingRectangle height asFloat /
  37125.                             self scrollRectangleHeight * scrollBar inside height) rounded
  37126.                             min: scrollBar inside height)]!
  37127. markerDelta
  37128.  
  37129.     ^marker top - scrollBar top - ((paragraph clippingRectangle top -
  37130.         paragraph compositionRectangle top) asFloat /
  37131.             (self scrollRectangleHeight max: 1) asFloat *
  37132.                 scrollBar height asFloat) rounded!
  37133. scrollAmount 
  37134.     "Refer to the comment in ScrollController|scrollAmount."
  37135.  
  37136.     ^sensor cursorPoint y - scrollBar top!
  37137. scrollBy: heightToMove
  37138.     "Move the paragraph by heightToMove, and reset the text selection."
  37139.     ^ paragraph scrollBy: heightToMove withSelectionFrom: startBlock to: stopBlock!
  37140. scrollRectangleHeight
  37141.  
  37142.     ^paragraph compositionRectangle height 
  37143.         + paragraph lineGrid!
  37144. scrollToBottom
  37145.     "Scroll so that the tail end of the text is visible in the view.  5/6/96 sw"
  37146.  
  37147.     self scrollView: (paragraph clippingRectangle bottom 
  37148.         - paragraph compositionRectangle bottom)!
  37149. scrollToTop
  37150.     "Scroll so that the paragraph is at the top of the view."
  37151.  
  37152.     self scrollView: (paragraph clippingRectangle top 
  37153.         - paragraph compositionRectangle top)!
  37154. scrollView: anInteger 
  37155.     "Paragraph scrolling uses opposite polarity"
  37156.     ^ self scrollBy: anInteger negated!
  37157. updateMarker
  37158.     "A variation of computeMarkerRegion--only redisplay the marker in the scrollbar if an actual change has occurred in the positioning of the paragraph."
  37159.     self moveMarkerTo: self computeMarkerRegion!
  37160. viewDelta 
  37161.     "Refer to the comment in ScrollController|viewDelta."
  37162.  
  37163.     ^paragraph clippingRectangle top 
  37164.         - paragraph compositionRectangle top 
  37165.         - ((marker top - scrollBar inside top) asFloat 
  37166.                 / scrollBar inside height asFloat * self scrollRectangleHeight asFloat)
  37167.             roundTo: paragraph lineGrid! !
  37168.  
  37169. !ParagraphEditor methodsFor: 'sensor access'!
  37170. processBlueButton
  37171.     "The user pressed the blue button on the mouse. Determine what action 
  37172.     to take."
  37173.  
  37174.     ^self!
  37175. processKeyboard
  37176.     "Determine whether the user pressed the keyboard. If so, read the keys."
  37177.  
  37178.     sensor keyboardPressed ifTrue: [self readKeyboard]!
  37179. processMouseButtons
  37180.     "Determine whether the user pressed any mouse button. For each possible 
  37181.     button, determine what actions to take."
  37182.  
  37183.     sensor redButtonPressed ifTrue: [self processRedButton].
  37184.     sensor yellowButtonPressed ifTrue: [self processYellowButton].
  37185.     sensor blueButtonPressed ifTrue: [self processBlueButton]!
  37186. processRedButton
  37187.     "The user pressed a red mouse button, meaning create a new text 
  37188.     selection. Highlighting the selection is carried out by the paragraph 
  37189.     itself. Double clicking causes a selection of the area between the nearest 
  37190.     enclosing delimitors."
  37191.  
  37192.     | previousStartBlock previousStopBlock selectionBlocks tempBlock clickPoint oldDelta oldInterval |
  37193.  
  37194.     clickPoint _ sensor cursorPoint.
  37195.     (view containsPoint: clickPoint) ifFalse: [^ self].
  37196.     oldInterval _ startBlock stringIndex to: stopBlock stringIndex - 1.
  37197.     previousStartBlock _ startBlock.
  37198.     previousStopBlock _ stopBlock.
  37199.     oldDelta _ paragraph scrollDelta.
  37200.     sensor leftShiftDown
  37201.         ifFalse:
  37202.             [self deselect.
  37203.             self closeTypeIn.
  37204.             selectionBlocks _ paragraph mouseSelect: clickPoint]
  37205.         ifTrue:
  37206.             [selectionBlocks _ paragraph extendSelectionAt: startBlock endBlock: stopBlock.
  37207.             self closeTypeIn].
  37208.     selectionShowing _ true.
  37209.     startBlock _ selectionBlocks at: 1.
  37210.     stopBlock _ selectionBlocks at: 2.
  37211.     startBlock > stopBlock
  37212.         ifTrue: 
  37213.             [tempBlock _ startBlock.
  37214.             startBlock _ stopBlock.
  37215.             stopBlock _ tempBlock].
  37216.     (startBlock = stopBlock 
  37217.         and: [previousStartBlock = startBlock and: [previousStopBlock = stopBlock]])
  37218.         ifTrue: [self selectWord].
  37219.     oldDelta ~= paragraph scrollDelta "case of autoscroll"
  37220.             ifTrue: [self updateMarker].
  37221.     self setEmphasisHere.
  37222.     (self isDisjointFrom: oldInterval) ifTrue:
  37223.         [otherInterval _ oldInterval]!
  37224. processYellowButton
  37225.     "User pressed the yellow button on the mouse. Determine what actions to 
  37226.     take."
  37227.  
  37228.     self yellowButtonActivity! !
  37229.  
  37230. !ParagraphEditor methodsFor: 'displaying'!
  37231. display
  37232.     "Redisplay the paragraph."
  37233.  
  37234.     | selectionState |
  37235.     selectionState _ selectionShowing.
  37236.     self deselect.
  37237.     paragraph foregroundColor: view foregroundColor
  37238.             backgroundColor: view backgroundColor;
  37239.             displayOn: Display.
  37240.     selectionState ifTrue: [self select]!
  37241. flash
  37242.     "Causes the view of the paragraph to complement twice in succession."
  37243.  
  37244.     paragraph flash! !
  37245.  
  37246. !ParagraphEditor methodsFor: 'menu messages'!
  37247. accept
  37248.     "Save the current text of the text being edited as the current acceptable version for purposes of canceling.  
  37249.     7/16/96 sw: call view.accepted, giving the view a chance to take special action at this juncture."
  37250.  
  37251.     initialText _ paragraph text copy.
  37252.     view accepted!
  37253. again
  37254.     "Text substitution. If the left shift key is down, the substitution is made 
  37255.     throughout the entire Paragraph. Otherwise, only the next possible 
  37256.     substitution is made.
  37257.     Undoer & Redoer: #undoAgain:andReselect:typedKey:."
  37258.  
  37259.     "If last command was also 'again', use same keys as before"
  37260.     self againOrSame: (UndoMessage sends: #undoAgain:andReselect:typedKey:)!
  37261. align
  37262.     "Align text according to the next greater alignment value--cycling among 
  37263.     left flush, right flush, center, justified.  No effect on the undoability of the pre
  37264.     preceding command."
  37265.  
  37266.     paragraph toggleAlignment.
  37267.     paragraph displayOn: Display.
  37268.     self recomputeInterval!
  37269. browseIt
  37270.     "Launch a browser for the current selection, if appropriate.  2/96 sw.
  37271.     In this initial version, we open a system browser on a class, and an implementors browser on a selector, otherwise we flash.
  37272.     2/29/96 sw: select current line first, if selection was an insertion pt"
  37273.  
  37274.     | aSymbol anEntry |
  37275.     self selectLine.
  37276.  
  37277.     (aSymbol _ self selectedSymbol) isNil ifTrue: [^ view flash].
  37278.  
  37279.     self terminateAndInitializeAround:
  37280.         [aSymbol first isUppercase
  37281.             ifTrue:
  37282.                 [anEntry _ (Smalltalk at: aSymbol ifAbsent: [nil]).
  37283.                 anEntry isNil ifTrue: [^ view flash].
  37284.                 (anEntry isKindOf: Class)
  37285.                     ifTrue:
  37286.                         [BrowserView browseFullForClass: anEntry method: nil from: self]
  37287.                     ifFalse:
  37288.                         [anEntry inspect]]
  37289.             ifFalse:
  37290.                 [Smalltalk implementorsOf: aSymbol]]!
  37291. browseItHere
  37292.     "Retarget the receiver's window to look at the selected class, if appropriate.  3/1/96 sw"
  37293.  
  37294.     | aSymbol foundClass b |
  37295.  
  37296.     (((b _ view topView model) isKindOf: Browser) and: [b couldBrowseAnyClass])
  37297.         ifFalse: [^ view flash].
  37298.     model okToChange ifFalse: [^ view flash].
  37299.     self selectLine.
  37300.     (aSymbol _ self selectedSymbol) isNil ifTrue: [^ view flash].
  37301.  
  37302.     self terminateAndInitializeAround:
  37303.         [foundClass _ (Smalltalk at: aSymbol ifAbsent: [nil]).
  37304.             foundClass isNil ifTrue: [^ view flash].
  37305.             (foundClass isKindOf: Class)
  37306.                 ifTrue:
  37307.                     [model systemCategoryListIndex: (model systemCategoryList indexOf: foundClass category).
  37308.         model classListIndex: (model classList indexOf: foundClass name)]]!
  37309. cancel 
  37310.     "Restore the text of the paragraph to be the text saved since initialization 
  37311.     or the last accept.  Undoer & Redoer: undoAndReselect:redoAndReselect:.
  37312.     This used to call controlTerminate and controlInitialize but this seemed illogical.
  37313.     Sure enough, nobody overrode them who had cancel in the menu, and if
  37314.     anybody really cared they could override cancel."
  37315.  
  37316.     UndoSelection _ paragraph text.
  37317.     self undoer: #undoAndReselect:redoAndReselect: with: self selectionInterval with: (1 to: 0).
  37318.     view clearInside.
  37319.     self changeParagraph: (paragraph text: initialText).
  37320.     UndoParagraph _ paragraph.
  37321.     otherInterval _ UndoInterval _ 1 to: initialText size. "so undo will replace all"
  37322.     paragraph displayOn: Display.
  37323.     self selectAt: 1.
  37324.     self scrollToTop
  37325. !
  37326. changeStyle
  37327.     "Let user change styles for the current text pane  8/20/96 tk
  37328.      Moved from experimentalCommand to its own method  8/20/96 sw"
  37329.  
  37330.     | aList reply style |
  37331.     aList _ (TextConstants at: #StyleNames).
  37332.     reply _ (SelectionMenu labelList: aList selections: aList) startUp.
  37333.     reply ~~ nil ifTrue:
  37334.         [style _ TextConstants at: reply ifAbsent: [self beep. ^ true].
  37335.         style class == TextStyle ifFalse: [self beep. ^ true].
  37336.         paragraph textStyle: style.
  37337.         paragraph composeAll.
  37338.         self recomputeSelection.
  37339.         Display fill: paragraph clippingRectangle 
  37340.             fillColor: view backgroundColor.    "very brute force"
  37341.         self display.
  37342.         "paragraph changed"].
  37343.     ^ true!
  37344. clipboardText
  37345.     "Return text currently on the clipboard.  If it is different from the
  37346.     Mac clipboard, then use the latter, since it must be more recent"
  37347.     | s |
  37348.     s _ Smalltalk clipboardText.
  37349.     s = CurrentSelection string
  37350.         ifTrue: [^ CurrentSelection]
  37351.         ifFalse: [^ s asText]!
  37352. clipboardTextPut: text
  37353.     "Set text currently on the clipboard.  Also export to Mac"
  37354.  
  37355.     CurrentSelection _ text.
  37356.     Smalltalk clipboardText: CurrentSelection string!
  37357. compareToClipboard
  37358.     "Check to see if whether the receiver's text is the same as the text currently on the clipboard, and inform the user.  4/29/96 sw"
  37359.     | count s |
  37360.     s _ self clipboardText string.
  37361.     count _ paragraph text string charactersExactlyMatching: s.
  37362.     count == (paragraph text string size max: s size) 
  37363.         ifTrue:
  37364.             [^ self inform: 'Exact match'].
  37365.  
  37366.     self selectFrom: 1 to: count!
  37367. copySelection
  37368.     "Copy the current selection and store it in the paste buffer, unless a caret.  Undoer & Redoer: undoCutCopy:.
  37369.      2/29/96 sw: select line first, if selection was an insertion point"
  37370.  
  37371.     self selectLine.
  37372.     startBlock = stopBlock ifTrue: [^ view flash.].
  37373.  
  37374.     "Simulate 'substitute: self selection' without locking the controller"
  37375.     UndoSelection _ self selection.
  37376.     self undoer: #undoCutCopy: with: self clipboardText.
  37377.     UndoInterval _ self selectionInterval.
  37378.     self clipboardTextPut: UndoSelection!
  37379. cut
  37380.     "Cut out the current selection and redisplay the paragraph if necessary.  Undoer & Redoer: undoCutCopy:.
  37381.     2/29/96 sw: select line first, if selection was an insertion point"
  37382.  
  37383.     self selectLine.
  37384.     startBlock = stopBlock ifTrue: [^ view flash].
  37385.  
  37386.     self replaceSelectionWith: self nullText. 
  37387.     self undoer: #undoCutCopy: with: self clipboardText.
  37388.     self clipboardTextPut: UndoSelection!
  37389. exchange
  37390.     "See comment in exchangeWith:"
  37391.  
  37392.     self exchangeWith: otherInterval!
  37393. experimentalCommand
  37394.     "Use for experimental command-key implementation.  using this, you can try things out without forever needing to reinitialize the ParagraphEditor.  2/7/96 sw"
  37395.  
  37396.     self flag: #scottPrivate.
  37397.     self inform: 
  37398. 'Cmd-t is not currently used.
  37399. To get "ifTrue: [" inserted, 
  37400. use Cmd-SHIFT-t'.
  37401.     ^ true
  37402. !
  37403. explain
  37404.     "Try to shed some light on what kind of entity the current selection is. 
  37405.     The selection must be a single token or construct. Insert the answer after 
  37406.     the selection. Send private messages whose names begin with 'explain' 
  37407.     that return a string if they recognize the selection, else nil.
  37408.     1/15/96 sw: put here intact from BrowserCodeController.  But there's too many things that still don't work, as the explain code was very tightly bound with properties of code browsers.  So for the moment, in the interest of system integrity, we don't permit.  2/5/96 sw"
  37409.  
  37410.     | string tiVars cgVars selectors delimitors numbers symbol sorry reply newLine |
  37411.  
  37412.     true ifTrue:
  37413.         [self flag: #noteToTed.   "Feel like taking this on?  Plenty of things make sense to explain in any text window, but my efforts to elevate the explain facility to more generic use ran out of steam before success."
  37414.         ^ self inform: 'Sorry, explain is currently available
  37415. only in code panes.  Someday, it may be available
  37416. in any text pane.  Maybe.'].
  37417.  
  37418.     newLine _ String with: Character cr.
  37419.     Cursor execute
  37420.         showWhile: 
  37421.             [sorry _ '"Sorry, I can''t explain that.  Please select a single token, construct, or special character.'.
  37422.             sorry _ sorry , (model isUnlocked
  37423.                             ifTrue: ['"']
  37424.                             ifFalse: ['  Also, please cancel or accept."']).
  37425.             (string _ self selection asString) isEmpty
  37426.                 ifTrue: [reply _ '']
  37427.                 ifFalse: 
  37428.                     [string _ self explainScan: string.
  37429.                     "Remove space, tab, cr"
  37430.                     "Temps and Instance vars need only test strings that are 
  37431.                     all  
  37432.                     letters"
  37433.                     (string detect: [:char | (char isLetter or: [char isDigit]) not]
  37434.                         ifNone: [])
  37435.                         ~~ nil
  37436.                         ifFalse: 
  37437.                             [tiVars _ self explainTemp: string.
  37438.                             tiVars == nil ifTrue: [tiVars _ self explainInst: string]].
  37439.                     (tiVars == nil and: [model class == Browser])
  37440.                         ifTrue: [tiVars _ model explainSpecial: string].
  37441.                     tiVars == nil
  37442.                         ifTrue: [tiVars _ '']
  37443.                         ifFalse: [tiVars _ tiVars , newLine].
  37444.                     "Context, Class, Pool, and Global vars, and Selectors need 
  37445.                     only test symbols"
  37446.                     (Symbol hasInterned: string ifTrue: [:symbol | symbol])
  37447.                         ifTrue: 
  37448.                             [cgVars _ self explainCtxt: symbol.
  37449.                             cgVars == nil
  37450.                                 ifTrue: 
  37451.                                     [cgVars _ self explainClass: symbol.
  37452.                                     cgVars == nil ifTrue: [cgVars _ self explainGlobal: symbol]].
  37453.                             "See if it is a Selector (sent here or not)"
  37454.                             selectors _ self explainMySel: symbol.
  37455.                             selectors == nil
  37456.                                 ifTrue: 
  37457.                                     [selectors _ self explainPartSel: string.
  37458.                                     selectors == nil ifTrue: [selectors _ self explainAnySel: symbol]]]
  37459.                         ifFalse: [selectors _ self explainPartSel: string].
  37460.                     cgVars == nil
  37461.                         ifTrue: [cgVars _ '']
  37462.                         ifFalse: [cgVars _ cgVars , newLine].
  37463.                     selectors == nil
  37464.                         ifTrue: [selectors _ '']
  37465.                         ifFalse: [selectors _ selectors , newLine].
  37466.                     string size = 1
  37467.                         ifTrue: ["single special characters"
  37468.                             delimitors _ self explainChar: string]
  37469.                         ifFalse: ["matched delimitors"
  37470.                             delimitors _ self explainDelimitor: string].
  37471.                     numbers _ self explainNumber: string.
  37472.                     numbers == nil ifTrue: [numbers _ ''].
  37473.                     delimitors == nil ifTrue: [delimitors _ ''].
  37474.                     reply _ tiVars , cgVars , selectors , delimitors , numbers].
  37475.             reply size = 0 ifTrue: [reply _ sorry].
  37476.             self afterSelectionInsertAndSelect: reply]!
  37477. explainClass: string 
  37478.     "1/15/96 sw: place holder"
  37479.     ^ nil!
  37480. explainCtxt: string 
  37481.     "1/15/96 sw: place holder"
  37482.     ^ nil!
  37483. explainGlobal: symbol 
  37484.     "Is symbol a global variable?
  37485.      1/15/96 sw: copied intact from BrowserCodeController"
  37486.  
  37487.     | each pool reply classes newLine |
  37488.     self flag: #noteToTed.  "a fumbling piece of the generic-explain attempt."
  37489.  
  37490.     newLine _ String with: Character cr.
  37491.     reply _ Smalltalk at: symbol ifAbsent: [^nil].
  37492.     (reply isKindOf: Behavior)
  37493.         ifTrue: [^'"is a global variable.  ' , symbol , ' is a class in category ', reply category,
  37494.             '."', newLine, 'Browser newOnClass: ' , symbol , '.'].
  37495.     symbol == #Smalltalk ifTrue: [^'"is a global.  Smalltalk is the only instance of SystemDictionary and holds all global variables."'].
  37496.     reply class == Dictionary
  37497.         ifTrue: 
  37498.             [classes _ Set new.
  37499.             Smalltalk allBehaviorsDo: [:each | (each sharedPools detect: [:pool | pool == reply]
  37500.                     ifNone: [])
  37501.                     ~~ nil ifTrue: [classes add: each]].
  37502.             classes _ classes printString.
  37503.             ^'"is a global variable.  ' , symbol , ' is a Dictionary.  It is a pool which is used by the following classes' , (classes copyFrom: 4 to: classes size) , '"'].
  37504.     ^'"is a global variable.  ' , symbol , ' is ' , reply printString , '"'!
  37505. explainInst: string 
  37506.     "1/15/96 sw: place holder"
  37507.     ^ nil!
  37508. explainMySel: symbol 
  37509.     "1/15/96 sw"
  37510.  
  37511.     | lits classes |
  37512.     self flag: #noteToTed.  "a halting piece of the generic-explain attempt."
  37513.  
  37514.     classes _ Smalltalk allClassesImplementing: symbol.
  37515.     ^ classes size > 0
  37516.         ifTrue: ['Smalltalk browseAllImplementorsOf: #', symbol]
  37517.         ifFalse: [nil]!
  37518. explainPartSel:  string 
  37519.     "1/15/96 sw: place holder"
  37520.     ^ nil!
  37521. explainScan: string 
  37522.     "Remove beginning and trailing space, tab, cr.
  37523.      1/15/96 sw: copied intact from BrowserCodeController"
  37524.  
  37525.     | c beg end |
  37526.     beg _ 1.
  37527.     end _ string size.
  37528.     
  37529.     [beg = end ifTrue: [^string copyFrom: 1 to: 1].
  37530.     "if all blank, tell about the first"
  37531.     c _ string at: beg.
  37532.     c = Character space or: [c = Character tab or: [c = Character cr]]]
  37533.         whileTrue: [beg _ beg + 1].
  37534.     
  37535.     [c _ string at: end.
  37536.     c = Character space or: [c = Character tab or: [c = Character cr]]]
  37537.         whileTrue: [end _ end - 1].
  37538.     ^string copyFrom: beg to: end    "Return purely visible characters"!
  37539. explainTemp: string 
  37540.     "1/15/96 sw: place holder"
  37541.     ^ nil!
  37542. fileItIn
  37543.     "Make a Stream on the text selection and fileIn it.
  37544.      1/24/96 sw: moved here from FileController; this function can be useful from any text window that shows stuff in chunk format"
  37545.  
  37546.     | aStream selection |
  37547.  
  37548.     self controlTerminate.
  37549.     selection _ self selection.
  37550.     (ReadWriteStream on: selection string from: 1 to: selection size) fileIn.
  37551.     self controlInitialize!
  37552. find
  37553.     "Prompt the user for a string to search for, and search the receiver from the current selection onward for it.  1/26/96 sw"
  37554.  
  37555.     | reply |
  37556.     reply _ FillInTheBlank request: 'Find what? ' initialAnswer: ''.
  37557.     reply size == 0 ifTrue: [^ self].
  37558.     self setSearch: reply.
  37559.     self againOrSame: true
  37560.     
  37561. !
  37562. findAgain
  37563.     "Find the text-to-find again.  1/24/96 sw"
  37564.  
  37565.     self againOrSame: true!
  37566. fit
  37567.     "Make the bounding rectangle of the paragraph contain all the text while 
  37568.      not changing the width of the view of the paragraph.  No effect on undoability
  37569.      of the preceding command."
  37570.  
  37571.     paragraph clearVisibleRectangle.
  37572.     paragraph fit.
  37573.     paragraph displayOn: Display; outline.
  37574.     self recomputeInterval!
  37575. format
  37576.     "Put here as a backstop for situations where the menu command is available but a method context is not extablished.  1/24/96 sw"
  37577.  
  37578.     view flash!
  37579. implementorsOfIt
  37580.     "Open an implementors browser on the selected selector.  1/8/96 sw.
  37581.     1/18/96 sw: converted to use selectedSelector
  37582.     2/29/96 sw: select current line if selection is insertion point"
  37583.  
  37584.     | aSelector |
  37585.     self selectLine.
  37586.     startBlock = stopBlock ifTrue: [view flash.  ^ self].
  37587.     (aSelector _ self selectedSelector) == nil ifTrue: [^ view flash].
  37588.     self terminateAndInitializeAround: [Smalltalk browseAllImplementorsOf: aSelector]!
  37589. methodNamesContainingIt
  37590.     "Open a browser on methods names containing the selected string.  1/17/96 sw"
  37591.  
  37592.     startBlock = stopBlock ifTrue: [view flash.  ^ self].
  37593.     Cursor wait showWhile:
  37594.         [self terminateAndInitializeAround: [Smalltalk browseMethodsWhoseNamesContain: self selection string]].
  37595.     Cursor normal show!
  37596. methodSourceContainingIt
  37597.     "Open a browser on methods which contain the current selection in their source (case-sensitive full-text search of source).   EXTREMELY slow!!"
  37598.  
  37599.     startBlock = stopBlock ifTrue: [view flash.  ^ self].
  37600.     (PopUpMenu confirm: 'This will take a few minutes.
  37601. Shall I proceed?') ifFalse: [^ self].
  37602.     Smalltalk browseMethodsWithSourceString: self selection string!
  37603. methodStringsContainingit
  37604.     "Open a browser on methods which contain the current selection as part of a string constant.  2/1/96 sw"
  37605.  
  37606.     startBlock = stopBlock ifTrue: [view flash.  ^ self].
  37607.     Cursor wait showWhile:
  37608.         [self terminateAndInitializeAround: [Smalltalk browseMethodsWithString: self selection string]].
  37609.     Cursor normal show!
  37610. paste
  37611.     "Paste the text from the shared buffer over the current selection and 
  37612.     redisplay if necessary.  Undoer & Redoer: undoAndReselect."
  37613.  
  37614.     self replace: self selectionInterval with: self clipboardText and:
  37615.         [self selectAt: stopBlock stringIndex]!
  37616. performMenuMessage: aSelector
  37617.     "If a menu command is invoked, typeIn must be closed first, the selection
  37618.      must be unhighlighted before and rehighlighted after, and the marker
  37619.      must be updated."
  37620.  
  37621.     self closeTypeIn.
  37622.     self deselect.
  37623.     super performMenuMessage: aSelector.
  37624.     self selectAndScroll.
  37625.     self updateMarker!
  37626. presentSpecialMenu
  37627.     "Present a list of expressions, and if the user chooses one, evaluate it in the context of the receiver, a ParagraphEditor.  Primarily for debugging, this provides a convenient way to talk to the various views, controllers, and models associated with any text pane.  2/5/96 sw"
  37628.  
  37629.     | aList reply items |
  37630.     self flag: #scottPrivate.
  37631.     self terminateAndInitializeAround:
  37632.         [aList _ self specialMenuItems.
  37633.         reply _ (PopUpMenu labelArray: (items _ self specialMenuItems) lines: #()) startUp.
  37634.         reply = 0 ifTrue: [^ self].
  37635.         Utilities evaluate: (items at: reply) in: [] to: self]
  37636.     !
  37637. referencesToIt
  37638.     "Open a references browser on the selected symbol.  1/8/96 sw.
  37639.      2/29/96 sw: select current line first if appropriate, and call selectedSymbol, to avoid pointless interning of spurious selections"
  37640.  
  37641.     self selectLine.
  37642.     startBlock = stopBlock ifTrue: [view flash. ^ self].
  37643.     self terminateAndInitializeAround: [Smalltalk browseAllCallsOn: (Smalltalk associationAt: self selectedSymbol)]!
  37644. selectedSelector
  37645.     "Try to make a selector out of the current text selection.
  37646.     6/18/96 sw: incorporated Dan's code for hunting down selectors with keyword parts; while this doesn't give a true parse, and will not handle parentheses correctly, for example, in most cases it does what we want, in where it doesn't, we're none the worse for it."
  37647.  
  37648.     | sel |
  37649.  
  37650.     sel _  self selection string withBlanksTrimmed.
  37651.  
  37652.     (sel includes: $:) ifTrue:
  37653.         [sel _ String streamContents:
  37654.             [:s | ((sel findTokens: Character separators)
  37655.                         select: [:tok | tok last = $:])
  37656.                     do: [:key | s nextPutAll: key]]].
  37657.  
  37658.     sel size == 0 ifTrue: [^ nil].
  37659.     Symbol hasInterned: sel ifTrue:
  37660.         [:aSymbol | ^ aSymbol].
  37661.  
  37662.     ^ nil!
  37663. selectedSymbol
  37664.     "Return the currently selected symbol, or nil if none.  If the selection involves a method send, return the relevent selector.  If the selection is a class name, return that. 1/15/96 sw.
  37665.     2/29/96 sw: strip crs before lookup"
  37666.  
  37667.     | aString |
  37668.     startBlock = stopBlock ifTrue: [^ nil].
  37669.     aString _ self selection string copyWithout: Character cr.
  37670.     aString size == 0 ifTrue: [^ nil].
  37671.     Symbol hasInterned: aString  ifTrue: [:sym | ^ sym].
  37672.  
  37673.     ^ nil!
  37674. sendersOfIt
  37675.     "Open a senders browser on the selected selector.  1/8/96 sw
  37676.     1/18/96 sw: converted to use selectedSelector
  37677.     2/29/96 sw: select current line first, if selection was an insertion pt"
  37678.  
  37679.     | aSelector |
  37680.     self selectLine.
  37681.     startBlock = stopBlock ifTrue: [view flash.  ^ self].
  37682.     (aSelector _ self selectedSelector) == nil ifTrue: [^ view flash].
  37683.     self terminateAndInitializeAround: [Smalltalk browseAllCallsOn: aSelector]!
  37684. setSearchString
  37685.     "Make the current selection, if any, be the current search string.  2/29/96 sw"
  37686.  
  37687.     startBlock = stopBlock ifTrue: [view flash. ^ self].
  37688.     self setSearch:  self selection string!
  37689. shiftedYellowButtonMenu
  37690.     "Answer the menu to be presented when the yellow button is pressed while the shift key is down. 3/13/96 sw
  37691.      5/27/96 sw: added font menu"
  37692.  
  37693.     ^ PopUpMenu labels: 
  37694. 'set font... (k)
  37695. set style... (K)
  37696. explain
  37697. format
  37698. file it in
  37699. recognizer (r)
  37700. spawn (o)
  37701. browse it (b)
  37702. senders of it (n)
  37703. implementors of it (m)
  37704. references to it (N)
  37705. selectors containing it (W)
  37706. method strings with it
  37707. method source with it
  37708. special menu...
  37709. more...' 
  37710.         lines: #(2 7 14).!
  37711. shiftedYellowButtonMessages
  37712.     "Answer the set of messages that go with the shifted menu.  Inconvenient to have it here in this separate method; when/if we consolidate via a class variable, as for unshifted, the problem will go away.  1/17/96 sw
  37713.      3/7/96 sw: added methodSourceContainingIt
  37714.      3/13/96 sw: merged ParagraphEditor and StringHolderController versions into ParagraphEditor, and deleted the StringHolderController versions
  37715.      5/27/96 sw: added offerFontMenu
  37716.      8/20/96 sw: makeover"
  37717.  
  37718.     ^ #(offerFontMenu changeStyle explain format fileItIn recognizeCharacters spawn browseIt sendersOfIt implementorsOfIt referencesToIt  methodNamesContainingIt methodStringsContainingit methodSourceContainingIt  presentSpecialMenu unshiftedYellowButtonActivity)
  37719.  
  37720. "set font... (k)
  37721. set style... (K)
  37722. explain
  37723. format
  37724. file it in
  37725. recognizer (r)
  37726. spawn (o)
  37727. browse it (b)
  37728. senders of it (n)
  37729. implementors of it (m)
  37730. references to it (N)
  37731. selectors containing it (W)
  37732. method strings with it
  37733. method source with it
  37734. special menu...
  37735. more..."!
  37736. spawn
  37737.     "Put here as a backstop for situations where the menu command is available but a method context is not extablished.  1/24/96 sw"
  37738.  
  37739.     view flash!
  37740. specialMenuItems
  37741.     "Refer to comment under #presentSpecialMenu.  4/29/96 sw."
  37742.  
  37743.     ^ #(    'Transcript cr; show: ''testing'''
  37744.             'view superView model inspect'
  37745.             'view superView model browseObjClass'
  37746.             'view display'
  37747.             'self inspect'
  37748.             'view backgroundColor: Color fromUser'
  37749.             'view topView inspect'
  37750.             'self compareToClipboard'
  37751.             'view insideColor: Form white'
  37752.         ) !
  37753. undo
  37754.     "Reset the state of the paragraph prior to the previous edit.
  37755.      If another ParagraphEditor instance did that edit, UndoInterval is invalid;
  37756.      just recover the contents of the undo-buffer at the start of the paragraph."
  37757.  
  37758.     [sensor keyboardPressed] whileTrue: [sensor keyboard]. "a way to flush stuck keys"
  37759.  
  37760.     UndoParagraph == paragraph ifFalse: "Can't undo another paragraph's edit"
  37761.         [UndoMessage _ Message selector: #undoReplace.
  37762.         UndoInterval _ 1 to: 0.
  37763.         Undone _ true].
  37764.     UndoInterval ~= self selectionInterval ifTrue: "blink the actual target"
  37765.         [self selectInterval: UndoInterval; deselect].
  37766.  
  37767.     "Leave a signal of which phase is in progress"
  37768.     UndoParagraph _ Undone ifTrue: [#redoing] ifFalse: [#undoing].
  37769.     UndoMessage sentTo: self.
  37770.     UndoParagraph _ paragraph! !
  37771.  
  37772. !ParagraphEditor methodsFor: 'editing keys'!
  37773. align: characterStream 
  37774.     "Triggered by Cmd-u;  cycle through alignment alternatives.  8/11/96 sw"
  37775.  
  37776.     sensor keyboard.        "flush character"
  37777.     self align.
  37778.     ^ true!
  37779. browseIt: characterStream 
  37780.     "Triggered by Cmd-B; browse the thing represented by the current selection, if plausible.  1/18/96 sw"
  37781.  
  37782.     sensor keyboard.        "flush character"
  37783.     self browseIt.
  37784.     ^ true!
  37785. browseItHere: characterStream 
  37786.     "Triggered by Cmd-shift-B; browse the thing represented by the current selection, if plausible, in the receiver's own window.  3/1/96 sw"
  37787.  
  37788.     sensor keyboard.        "flush character"
  37789.     self browseItHere.
  37790.     ^ true!
  37791. cancel: characterStream 
  37792.     "Cancel unsubmitted changes.  Flushes typeahead.  1/12/96 sw
  37793.      1/22/96 sw: put in control terminate/init"
  37794.  
  37795.     self controlTerminate.
  37796.     sensor keyboard.
  37797.     self cancel.
  37798.     self controlInitialize.
  37799.     ^ true!
  37800. changeEmphasis: characterStream
  37801.     "Change the emphasis of the current selection or prepare to accept 
  37802.     characters with the change in emphasis. Emphasis change amounts to a 
  37803.     font change.  Keeps typeahead."
  37804.  
  37805.     | newCode |
  37806.     newCode _ (sensor keyboard asciiValue - $0 asciiValue) + 1.
  37807.     beginTypeInBlock ~~ nil
  37808.         ifTrue:  "only change emphasisHere while typing"
  37809.             [self insertTypeAhead: characterStream.
  37810.             emphasisHere _ newCode.
  37811.             ^true].
  37812.     self replaceSelectionWith:
  37813.         (Text string: self selection asString emphasis: (newCode max: 1)).
  37814.     ^true!
  37815. compareToClipboard: characterStream 
  37816.     "Compare the receiver to the text on the clipboard.  Flushes typeahead.  5/1/96 sw"
  37817.  
  37818.     sensor keyboard.    
  37819.     self compareToClipboard.
  37820.     ^ true!
  37821. copySelection: characterStream 
  37822.     "Copy the current text selection.  Flushes typeahead."
  37823.  
  37824.     sensor keyboard.        "flush character"
  37825.     self copySelection.
  37826.     ^true!
  37827. cut: characterStream 
  37828.     "Cut out the current text selection.  Flushes typeahead."
  37829.  
  37830.     sensor keyboard.        "flush character"
  37831.     self cut.
  37832.     ^true!
  37833. doIt: characterStream 
  37834.     "Called when user hits cmd-d.  Select the current line, if relevant, then evaluate and execute.  2/1/96 sw.
  37835.     2/29/96 sw: don't call selectLine; it's done by doIt now"
  37836.  
  37837.     sensor keyboard.    
  37838.     self doIt.
  37839.     ^ true!
  37840. duplicate: characterStream
  37841.     "Paste the current selection over the prior selection, if it is non-overlapping and
  37842.      legal.  Flushes typeahead.  Undoer & Redoer: undoAndReselect."
  37843.  
  37844.     sensor keyboard.
  37845.     self closeTypeIn.
  37846.     (startBlock ~= stopBlock and: [self isDisjointFrom: otherInterval])
  37847.         ifTrue: "Something to duplicate"
  37848.             [self replace: otherInterval with: self selection and:
  37849.                 [self selectAt: stopBlock stringIndex]]
  37850.         ifFalse:
  37851.             [view flash].
  37852.     ^true!
  37853. enclose: characterStream
  37854.     "Insert or remove bracket characters around the current selection.
  37855.      Flushes typeahead."
  37856.  
  37857.     | char left right startIndex stopIndex oldSelection which text |
  37858.     char _ Sensor keyboard.
  37859.     self closeTypeIn.
  37860.     startIndex _ startBlock stringIndex.
  37861.     stopIndex _ stopBlock stringIndex.
  37862.     oldSelection _ self selection.
  37863.     which _ '([<{"''' indexOf: char ifAbsent: [ ^true ].
  37864.     left _ '([<{"''' at: which.
  37865.     right _ ')]>}"''' at: which.
  37866.     text _ paragraph text.
  37867.     ((startIndex > 1 and: [stopIndex <= text size])
  37868.         and:
  37869.         [(text at: startIndex-1) = left and: [(text at: stopIndex) = right]])
  37870.         ifTrue:
  37871.             ["already enclosed; strip off brackets"
  37872.             self selectFrom: startIndex-1 to: stopIndex.
  37873.             self replaceSelectionWith: oldSelection]
  37874.         ifFalse:
  37875.             ["not enclosed; enclose by matching brackets"
  37876.             self replaceSelectionWith:
  37877.                 (Text string: (String with: left), oldSelection string ,(String with: right)
  37878.                     emphasis: emphasisHere).
  37879.             self selectFrom: startIndex+1 to: stopIndex].
  37880.     ^true!
  37881. exchange: characterStream
  37882.     "Exchange the current and prior selections.  Keeps typeahead."
  37883.  
  37884.     sensor keyboard.     "Flush character"
  37885.     self closeTypeIn: characterStream.
  37886.     self exchange.
  37887.     ^true!
  37888. implementorsOfIt: characterStream 
  37889.     "Triggered by Cmd-m; browse implementors of the selector represented by the current selection, if plausible. 2/1/96 sw"
  37890.  
  37891.     sensor keyboard.        "flush character"
  37892.     self implementorsOfIt.
  37893.     ^ true!
  37894. indent: characterStream
  37895.     "Add a tab at the front of every line occupied by the selection. Flushes typeahead.  Invoked from keyboard via cmd-shift-R.  2/29/96 sw"
  37896.  
  37897.     ^ self inOutdent: characterStream delta: 1!
  37898. inOutdent: characterStream delta: delta
  37899.     "Add/remove a tab at the front of every line occupied by the selection. Flushes typeahead.  Derived from work by Larry Tesler back in December 1985.  Now triggered by Cmd-L and Cmd-R.  2/29/96 sw"
  37900.  
  37901.     | cr tab realStart realStop lines startLine stopLine start stop adjustStart indentation size origSize numLines inStream newString outStream |
  37902.     sensor keyboard.  "Flush typeahead"
  37903.     cr _ Character cr.
  37904.     tab _ Character tab.
  37905.  
  37906.     "Operate on entire lines, but remember the real selection for re-highlighting later"
  37907.     realStart _ startBlock stringIndex.
  37908.     realStop _ stopBlock stringIndex - 1.
  37909.  
  37910.     "Special case a caret on a line of its own, including weird case at end of paragraph"
  37911.     (realStart > realStop and:
  37912.                 [realStart < 2 or: [(paragraph string at: realStart - 1) == cr]])
  37913.         ifTrue:
  37914.             [delta < 0
  37915.                 ifTrue:
  37916.                     [view flash]
  37917.                 ifFalse:
  37918.                     [self replaceSelectionWith: Character tab asSymbol asText.
  37919.                     self selectAt: realStart + 1].
  37920.             ^true].
  37921.  
  37922.     lines _ paragraph lines.
  37923.     startLine _ paragraph lineIndexOfCharacterIndex: realStart.
  37924.     stopLine _ paragraph lineIndexOfCharacterIndex: (realStart max: realStop).
  37925.     start _ (lines at: startLine) first.
  37926.     stop _ (lines at: stopLine) last.
  37927.     
  37928.     "Pin the start of highlighting unless the selection starts a line"
  37929.     adjustStart _ realStart > start.
  37930.  
  37931.     "Find the indentation of the least-indented non-blank line; never outdent more"
  37932.     indentation _ (startLine to: stopLine) inject: 1000 into:
  37933.         [:m :l |
  37934.         m _ m min: (paragraph indentationOfLineIndex: l ifBlank: [:tabs | 1000])].            
  37935.  
  37936.     size _ origSize _ stop + 1 - start.
  37937.     numLines _ stopLine + 1 - startLine.
  37938.     inStream _ ReadStream on: paragraph string from: start to: stop.
  37939.  
  37940.     newString _ String new: size + ((numLines * delta) max: 0).
  37941.     outStream _ ReadWriteStream on: newString.
  37942.  
  37943.     "This subroutine does the actual work"
  37944.     self indent: delta fromStream: inStream toStream: outStream.
  37945.  
  37946.     "Adjust the range that will be highlighted later"
  37947.     adjustStart ifTrue: [realStart _ (realStart + delta) max: start].
  37948.     realStop _ realStop + outStream position - size.
  37949.  
  37950.     "Prepare for another iteration"
  37951.     indentation _ indentation + delta.
  37952.     size _ outStream position.
  37953.     inStream _ outStream setFrom: 1 to: size.
  37954.  
  37955.     outStream == nil
  37956.         ifTrue:     "tried to outdent but some line(s) were already left flush"
  37957.             [view flash]
  37958.         ifFalse:
  37959.             [self selectInvisiblyFrom: start to: stop.
  37960.             size = newString size ifFalse: [newString _ outStream contents].
  37961.             self replaceSelectionWith: newString asText].
  37962.     self selectFrom: realStart to: realStop.     "highlight only the original range"
  37963.     ^ true!
  37964. inspectIt: characterStream 
  37965.     "Inspect the selection -- invoked via cmd-i.  If there is no current selection, use the current line.  1/17/96 sw
  37966.      2/29/96 sw: don't call selectLine; it's done by inspectIt now"
  37967.  
  37968.     sensor keyboard.        "flush character"
  37969.     self inspectIt.
  37970.     ^ true!
  37971. methodNamesContainingIt: characterStream 
  37972.     "Triggered by Cmd-K; browse selectors containing the selection in their names.  8/11/96 sw"
  37973.  
  37974.     sensor keyboard.        "flush character"
  37975.     self methodNamesContainingIt.
  37976.     ^ true!
  37977. noop: characterStream 
  37978.     "Unimplemented keyboard command; just ignore it."
  37979.  
  37980.     sensor keyboard.      "flush character"
  37981.     ^ true
  37982. !
  37983. offerFontMenu
  37984.     "Present a menu of available fonts, and if one is chosen, apply it to the current selection.  5/27/96 sw
  37985.     Use only names of Fonts of this paragraph  8/19/96 tk"
  37986.  
  37987.     | aList reply |
  37988.     aList _ paragraph textStyle fontNames.
  37989.     reply _ (SelectionMenu labelList: aList selections: aList) startUp.
  37990.     reply ~~ nil ifTrue:
  37991.         [self replaceSelectionWith:
  37992.             (Text string: self selection asString emphasis: (aList indexOf: reply))] !
  37993. offerFontMenu: characterStream 
  37994.     "The user typed the command key that requests a font change; Offer the font menu.  5/27/96 sw
  37995.      Keeps typeahead.  (?? should flush?)"
  37996.  
  37997.     sensor keyboard.        "flush character"
  37998.     self closeTypeIn: characterStream.
  37999.     self offerFontMenu.
  38000.     ^ true!
  38001. outdent: characterStream
  38002.     "Remove a tab from the front of every line occupied by the selection. Flushes typeahead.  Invoked from keyboard via cmd-shift-L.  2/29/96 sw"
  38003.  
  38004.     ^ self inOutdent: characterStream delta: -1!
  38005. paste: characterStream 
  38006.     "Replace the current text selection by the text in the shared buffer.
  38007.      Keeps typeahead."
  38008.  
  38009.     sensor keyboard.        "flush character"
  38010.     self closeTypeIn: characterStream.
  38011.     self paste.
  38012.     ^true!
  38013. pasteInitials: characterStream 
  38014.     "Replace the current text selection by an authorship name/date stamp; invoked by cmd-shift-v, easy way to put an authorship stamp in the comments of an editor.
  38015.      Keeps typeahead."
  38016.  
  38017.     sensor keyboard.        "flush character"
  38018.     self closeTypeIn: characterStream.
  38019.     self replace: self selectionInterval with: (Text fromString: Utilities changeStamp) and: [self selectAt: stopBlock stringIndex].
  38020.     ^ true!
  38021. printIt: characterStream 
  38022.     "Print the results of evaluting the selection -- invoked via cmd-p.  If there is no current selection, use the current line.  1/17/96 sw
  38023.      2/29/96 sw: don't call selectLine now, since it's called by doIt"
  38024.  
  38025.     sensor keyboard.        "flush character"
  38026.     self printIt.
  38027.     ^ true!
  38028. recognizer: characterStream 
  38029.     "Invoke Alan's character recognizer from cmd-r 2/2/96 sw"
  38030.  
  38031.     sensor keyboard.
  38032.     self recognizeCharacters.
  38033.     ^ true!
  38034. referencesToIt: characterStream 
  38035.     "Triggered by Cmd-N; browse references to the current selection"
  38036.  
  38037.     sensor keyboard.        "flush character"
  38038.     self referencesToIt.
  38039.     ^ true!
  38040. save: characterStream 
  38041.     "Submit the current text.  Equivalent to 'accept' 1/18/96 sw
  38042.      Keeps typeahead."
  38043.  
  38044.     sensor keyboard.        "flush character"
  38045.     self closeTypeIn: characterStream.
  38046.     self accept.
  38047.     ^ true!
  38048. selectLine
  38049.     "Make the receiver's selection, if it currently consists of an insertion point only, encompass the current line. 2/29/96 sw"
  38050.  
  38051.     | string left right |
  38052.  
  38053.     string _ paragraph text string.
  38054.     left _ startBlock stringIndex.
  38055.     right _ stopBlock stringIndex - 1.
  38056.     left > right ifFalse: [^ self].
  38057.  
  38058.     [left > 1 and: [(string at: (left - 1)) ~= Character cr]] whileTrue:
  38059.         [left _ left - 1].
  38060.     [right < string size and: [(string at: (right + 1)) ~= Character cr]] whileTrue:
  38061.         [right _ right + 1].
  38062.     self selectFrom: left to: (right + 1 min: string size)!
  38063. sendersOfIt: characterStream 
  38064.     "Triggered by Cmd-n; browse implementors of the selector represented by the current selection, if plausible. 2/1/96 sw"
  38065.  
  38066.     sensor keyboard.        "flush character"
  38067.     self sendersOfIt.
  38068.     ^ true!
  38069. shiftEnclose: characterStream
  38070.     "Insert or remove bracket characters around the current selection.
  38071.      Flushes typeahead."
  38072.  
  38073.     | char left right startIndex stopIndex oldSelection which text |
  38074.     char _ Sensor keyboard.
  38075.     char = $9 ifTrue: [ char _ $( ].
  38076.     char = $, ifTrue: [ char _ $< ].
  38077.     char = $[ ifTrue: [ char _ ${ ].
  38078.     char = $' ifTrue: [ char _ $" ].
  38079.     char asciiValue = 27 ifTrue: [ char _ ${ ].    "ctrl-["
  38080.  
  38081.     self closeTypeIn.
  38082.     startIndex _ startBlock stringIndex.
  38083.     stopIndex _ stopBlock stringIndex.
  38084.     oldSelection _ self selection.
  38085.     which _ '([<{"''' indexOf: char ifAbsent: [1].
  38086.     left _ '([<{"''' at: which.
  38087.     right _ ')]>}"''' at: which.
  38088.     text _ paragraph text.
  38089.     ((startIndex > 1 and: [stopIndex <= text size])
  38090.         and:
  38091.         [(text at: startIndex-1) = left and: [(text at: stopIndex) = right]])
  38092.         ifTrue:
  38093.             ["already enclosed; strip off brackets"
  38094.             self selectFrom: startIndex-1 to: stopIndex.
  38095.             self replaceSelectionWith: oldSelection]
  38096.         ifFalse:
  38097.             ["not enclosed; enclose by matching brackets"
  38098.             self replaceSelectionWith:
  38099.                 (Text string: (String with: left), oldSelection string ,(String with: right)
  38100.                     emphasis: emphasisHere).
  38101.             self selectFrom: startIndex+1 to: stopIndex].
  38102.     ^true!
  38103. spawnIt: characterStream 
  38104.     "Triggered by Cmd-o; spawn a new code window, if it makes sense.  Reimplemented by BrowserCodeController  2/1/96 sw"
  38105.  
  38106.     sensor keyboard.        "flush character"
  38107.     view flash.
  38108.     ^ true!
  38109. swapChars: characterStream 
  38110.     "Triggered byCmd-Y;.  Swap two characters, either those straddling the insertion point, or the two that comprise the selection.  Suggested by Ted Kaehler.  1/18/96 sw"
  38111.  
  38112.     | currentSelection aString chars |
  38113.     sensor keyboard.        "flush the triggering cmd-key character"
  38114.     (chars _ self selection) size == 0
  38115.         ifTrue:
  38116.             [currentSelection _ startBlock stringIndex]
  38117.         ifFalse:
  38118.             [chars size == 2
  38119.                 ifFalse:
  38120.                     [view flash.  ^ true]
  38121.                 ifTrue:
  38122.                     [currentSelection _ startBlock stringIndex + 1]].
  38123.  
  38124.     self selectFrom: currentSelection - 1 to: currentSelection.
  38125.     aString _ self selection string.
  38126.     self replaceSelectionWith: (Text fromString: aString backwards).
  38127.     self selectAt: currentSelection + 1.
  38128.     ^ true!
  38129. tempCommand: characterStream 
  38130.     "Experimental.  Triggered by Cmd-t; put trial cmd-key commands here to see how they work, before hanging them on their own cmd accelerators.   2/7/96 sw "
  38131.  
  38132.     | currentSelection aString chars |
  38133.     self flag: #scottPrivate.
  38134.     sensor keyboard.        "flush the triggering cmd-key character"
  38135.     self experimentalCommand.
  38136.     ^ true!
  38137. undo: characterStream 
  38138.     "Undo the last edit.  Keeps typeahead, so undo twice is a full redo."
  38139.  
  38140.     sensor keyboard.     "flush character"
  38141.     self closeTypeIn: characterStream.
  38142.     self undo.
  38143.     ^true! !
  38144.  
  38145. !ParagraphEditor methodsFor: 'typing/selecting keys'!
  38146. argAdvance: characterStream
  38147.     "Invoked by Ctrl-a.  Useful after Ctrl-q.
  38148.      Search forward from the end of the selection for a colon followed by
  38149.         a space.  Place the caret after the space.  If none are found, place the
  38150.         caret at the end of the text.  Does not affect the undoability of the 
  38151.          previous command."
  38152.  
  38153.     | start |
  38154.     sensor keyboard.        "flush character"
  38155.     self closeTypeIn: characterStream.
  38156.     start _ paragraph text findString: ': ' startingAt: stopBlock stringIndex.
  38157.     start = 0 ifTrue: [start _ paragraph text size + 1].
  38158.     self selectAt: start + 2.
  38159.     ^true!
  38160. backspace: characterStream 
  38161.     "Backspace over the last character."
  38162.  
  38163.     | startIndex |
  38164.     characterStream isEmpty
  38165.         ifTrue:
  38166.             [startIndex _ startBlock stringIndex +
  38167.                 (startBlock = stopBlock ifTrue: [0] ifFalse: [1]).
  38168.             [sensor keyboardPressed and:
  38169.              [sensor keyboardPeek asciiValue = 8]] whileTrue: [
  38170.                 "process multiple backspaces"
  38171.                 sensor keyboard.
  38172.                 startIndex _ 1 max: startIndex - 1.
  38173.             ].
  38174.             self backTo: startIndex]
  38175.         ifFalse:
  38176.             [sensor keyboard.
  38177.             characterStream skip: -1].
  38178.     ^false!
  38179. backWord: characterStream 
  38180.     "If the selection is not a caret, delete it and leave it in the backspace buffer.
  38181.      Else if there is typeahead, delete it.
  38182.      Else, delete the word before the caret."
  38183.  
  38184.     | startIndex |
  38185.     sensor keyboard.
  38186.     characterStream isEmpty
  38187.         ifTrue:
  38188.             [startBlock = stopBlock
  38189.                 ifTrue: "a caret, delete at least one character"
  38190.                     [startIndex _ 1 max: startBlock stringIndex - 1.
  38191.                     [startIndex > 1 and:
  38192.                         [(paragraph text at: startIndex - 1) asCharacter tokenish]]
  38193.                         whileTrue:
  38194.                             [startIndex _ startIndex - 1]]
  38195.                 ifFalse: "a non-caret, just delete it"
  38196.                     [startIndex _ startBlock stringIndex].
  38197.             self backTo: startIndex]
  38198.         ifFalse:
  38199.             [characterStream reset].
  38200.     ^false!
  38201. changeStyle: characterStream 
  38202.     "Put up the style-change menu"
  38203.  
  38204.     sensor keyboard.        "flush character"
  38205.     self closeTypeIn: characterStream.
  38206.     self changeStyle.
  38207.     ^ true!
  38208. displayIfFalse: characterStream 
  38209.     "Replace the current text selection with the text 'ifFalse:'--initiated by 
  38210.     ctrl-f."
  38211.  
  38212.     sensor keyboard.        "flush character"
  38213.     characterStream nextPutAll: 'ifFalse: ['.
  38214.     ^false!
  38215. displayIfTrue: characterStream 
  38216.     "Replace the current text selection with the text 'ifTrue:'--initiated by 
  38217.     ctrl-t."
  38218.  
  38219.     sensor keyboard.        "flush character"
  38220.     characterStream nextPutAll: 'ifTrue: ['.
  38221.     ^false!
  38222. doAgainMany: characterStream 
  38223.     "Do the previous thing again repeatedly. 1/26/96 sw"
  38224.  
  38225.     sensor keyboard.        "flush character"
  38226.     self closeTypeIn: characterStream.
  38227.     self againOrSame: (UndoMessage sends: #undoAgain:andReselect:typedKey:) many: true.
  38228.     ^ true!
  38229. doAgainOnce: characterStream 
  38230.     "Do the previous thing again once. 1/26/96 sw"
  38231.  
  38232.     sensor keyboard.        "flush character"
  38233.     self closeTypeIn: characterStream.
  38234.     self again.
  38235.     ^ true!
  38236. find: characterStream
  38237.     "Prompt the user for what to find, then find it, searching from the current selection onward.  1/24/96 sw"
  38238.  
  38239.     sensor keyboard.        "flush character"
  38240.     self closeTypeIn: characterStream.
  38241.     self find.
  38242.     ^ true!
  38243. findAgain: characterStream 
  38244.     "Find the desired text again.  1/24/96 sw"
  38245.  
  38246.     sensor keyboard.        "flush character"
  38247.     self closeTypeIn: characterStream.
  38248.     self findAgain.
  38249.     ^ true!
  38250. normalCharacter: characterStream 
  38251.     "A nonspecial character is to be added to the stream of characters."
  38252.  
  38253.     characterStream nextPut: sensor keyboard.
  38254.     ^false!
  38255. querySymbol: characterStream
  38256.     "Invoked by Ctrl-q to query the Symbol table and display alternate symbols.
  38257.      See comment in completeSymbol:lastOffering: for details."
  38258.  
  38259.     sensor keyboard.        "flush character"
  38260.     self closeTypeIn: characterStream.    "keep typeahead"
  38261.     startBlock = stopBlock
  38262.         ifTrue: "Ctrl-q typed when a caret"
  38263.             [self perform: #completeSymbol:lastOffering: withArguments:
  38264.                 ((UndoParagraph == paragraph and: [UndoMessage sends: #undoQuery:lastOffering:])
  38265.                     ifTrue: [UndoMessage arguments] "repeated Ctrl-q"
  38266.                     ifFalse: [Array with: nil with: nil])] "initial Ctrl-q"
  38267.         ifFalse: "Ctrl-q typed when statements were highlighted"
  38268.             [view flash].
  38269.     ^true!
  38270. search: characterStream
  38271.     "Invoked by Ctrl-S.  Same as 'again', but always uses the existing FindText
  38272.      and ChangeText regardless of the last edit."
  38273.  
  38274.     sensor keyboard.        "flush character"
  38275.     self closeTypeIn: characterStream.
  38276.     self againOrSame: true. "true means use same keys"
  38277.     ^true!
  38278. selectAll: characterStream 
  38279.     "select everything, invoked by cmd-a.  1/17/96 sw"
  38280.  
  38281.     sensor keyboard.        "flush character"
  38282.     self closeTypeIn: characterStream.
  38283.     self selectFrom: 1 to: paragraph text string size.
  38284.     ^ true!
  38285. selectCurrentTypeIn: characterStream 
  38286.     "Select what would be replaced by an undo (e.g., the last typeIn)."
  38287.  
  38288.     | prior |
  38289.  
  38290.     prior _ otherInterval.
  38291.     sensor keyboard.        "flush character"
  38292.     self closeTypeIn: characterStream.
  38293.     self selectInterval: UndoInterval.
  38294.     otherInterval _ prior.
  38295.     ^ true!
  38296. setSearchString: characterStream
  38297.     "Establish the current selection as the current search string.  2/7/96 sw"
  38298.  
  38299.     | aString |
  38300.     sensor keyboard.        "flush character"
  38301.     aString _  self selection string.
  38302.     aString size == 0 ifTrue: [^ self flash].
  38303.     self setSearch: aString.
  38304.     ^ true!
  38305. simulatedBackspace
  38306.     "Backspace over the last character, derived from hand-char recognition.  2/5/96 sw"
  38307.  
  38308.     | startIndex |
  38309.     startIndex _ startBlock stringIndex + (startBlock = stopBlock ifTrue: [0] ifFalse: [1]).
  38310.  
  38311.     startIndex _ 1 max: startIndex - 1.
  38312.     self backTo: startIndex.
  38313.     ^ false! !
  38314.  
  38315. !ParagraphEditor methodsFor: 'typing support'!
  38316. backTo: startIndex
  38317.     "During typing, backspace to startIndex.  Deleted characters fall into three
  38318.      clusters, from left to right in the text: (1) preexisting characters that were
  38319.      backed over; (2) newly typed characters that were backed over (excluding
  38320.      typeahead, which never even appears); (3) preexisting characters that
  38321.      were highlighted before typing began.  If typing has not yet been opened,
  38322.      open it and watch for the first and third cluster.  If typing has been opened,
  38323.      watch for the first and second cluster.  Save characters from the first and third
  38324.      cluster in UndoSelection.  Tally characters from the first cluster in UndoMessage's parameter.
  38325.      Delete all the clusters.  Do not alter Undoer or UndoInterval (except via
  38326.      openTypeIn).  The code is shorter than the comment."
  38327.  
  38328.     | saveLimit newBackovers |
  38329.     saveLimit _ beginTypeInBlock == nil
  38330.         ifTrue: [self openTypeIn. UndoSelection _ self nullText. stopBlock stringIndex]
  38331.         ifFalse: [beginTypeInBlock stringIndex].
  38332.     startBlock _ paragraph characterBlockForIndex: startIndex.
  38333.     startIndex < saveLimit ifTrue:
  38334.         [newBackovers _ beginTypeInBlock stringIndex - startIndex.
  38335.         beginTypeInBlock _ startBlock copy.
  38336.         UndoSelection replaceFrom: 1 to: 0 with:
  38337.             (paragraph text copyFrom: startIndex to: saveLimit - 1).
  38338.         UndoMessage argument: UndoMessage argument + newBackovers].
  38339.     self zapSelectionWith: self nullText.
  38340.     startBlock _ stopBlock copy!
  38341. closeTypeIn
  38342.     "See comment in openTypeIn.  It is important to call closeTypeIn before executing
  38343.      any non-typing key, making a new selection, etc.  It is called automatically for
  38344.      menu commands.
  38345.      Typing commands can call 'closeTypeIn: aCharacterStream' instead of this to
  38346.      save typeahead.  Undoer & Redoer: undoAndReselect:redoAndReselect:."
  38347.  
  38348.     | begin start stop |
  38349.     beginTypeInBlock == nil ifFalse:
  38350.         [(UndoMessage sends: #noUndoer) ifTrue: "should always be true, but just in case..."
  38351.             [begin _ beginTypeInBlock stringIndex.
  38352.             start _ startBlock stringIndex.
  38353.             stop _ stopBlock stringIndex.
  38354.             self undoer: #undoAndReselect:redoAndReselect:
  38355.                 with: (begin + UndoMessage argument to: begin + UndoSelection size - 1)
  38356.                 with: (stop to: stop - 1).
  38357.             UndoInterval _ begin to: stop - 1].
  38358.         beginTypeInBlock _ nil]!
  38359. closeTypeIn: characterStream
  38360.     "Call instead of closeTypeIn when you want typeahead to be inserted before the
  38361.      control character is executed, e.g., from Ctrl-V."
  38362.  
  38363.     self insertTypeAhead: characterStream.
  38364.     self closeTypeIn!
  38365. dispatchOnCharacter: char with: typeAheadStream
  38366.     "Carry out the action associated with this character, if any.
  38367.     Type-ahead is passed so some routines can flush or use it."
  38368.  
  38369.     "enter, backspace, and escape keys (ascii 3, 8, and 27) are command keys"
  38370.     (sensor commandKeyPressed or: [#(3 8 27) includes: char asciiValue]) ifTrue: [
  38371.         sensor leftShiftDown ifTrue: [
  38372.             ^ self perform: (ShiftCmdActions at: char asciiValue + 1) with: typeAheadStream.
  38373.         ] ifFalse: [
  38374.             ^ self perform: (CmdActions at: char asciiValue + 1) with: typeAheadStream.
  38375.         ].
  38376.     ].
  38377.  
  38378.     "the control key can be used to invoke shift-cmd shortcuts"
  38379.     sensor controlKeyPressed ifTrue: [
  38380.         ^ self perform: (ShiftCmdActions at: char asciiValue + 1) with: typeAheadStream.
  38381.     ].
  38382.     ^ self perform: #normalCharacter: with: typeAheadStream!
  38383. insertTypeAhead: typeAhead
  38384.  
  38385.     typeAhead isEmpty ifFalse:
  38386.         [self zapSelectionWith: 
  38387.             (Text string: typeAhead contents emphasis: emphasisHere).
  38388.         typeAhead reset.
  38389.         startBlock _ stopBlock copy]!
  38390. openTypeIn
  38391.     "Set up UndoSelection to null text (to be added to by readKeyboard and backTo:),
  38392.      beginTypeInBlock to keep track of the leftmost backspace, and UndoParameter to tally
  38393.      how many deleted characters were backspaced over rather than 'cut'.
  38394.      You can't undo typing until after closeTypeIn."
  38395.  
  38396.     beginTypeInBlock == nil ifTrue:
  38397.         [UndoSelection _ self nullText.
  38398.         self undoer: #noUndoer with: 0.
  38399.         beginTypeInBlock _ startBlock copy]!
  38400. readKeyboard
  38401.     "Key struck on the keyboard. Find out which one and, if special, carry 
  38402.     out the associated special action. Otherwise, add the character to the 
  38403.     stream of characters.  Undoer & Redoer: see closeTypeIn."
  38404.  
  38405.     | typeAhead char |
  38406.     typeAhead _ WriteStream on: (String new: 128).
  38407.     [sensor keyboardPressed] whileTrue: 
  38408.         [self deselect.
  38409.          [sensor keyboardPressed] whileTrue: 
  38410.             [char _ sensor keyboardPeek.
  38411.             (self dispatchOnCharacter: char with: typeAhead) ifTrue:
  38412.                 [beginTypeInBlock _ nil.
  38413.                 ^self selectAndScroll; updateMarker].
  38414.             self openTypeIn].
  38415.         startBlock = stopBlock ifFalse: "save highlighted characters"
  38416.             [UndoSelection _ self selection]. 
  38417.         self zapSelectionWith: 
  38418.             (Text string: typeAhead contents emphasis: emphasisHere).
  38419.         typeAhead reset.
  38420.         startBlock _ stopBlock copy.
  38421.         sensor keyboardPressed ifFalse: 
  38422.             [self selectAndScroll.
  38423.             sensor keyboardPressed
  38424.                 ifFalse: [self updateMarker]]]!
  38425. recognizeCharacters
  38426.     "Recognize hand-written characters and put them into the receiving pane.  Invokes Alan's character recognizer.  2/5/96 sw"
  38427.  
  38428.     self recognizeCharactersWhileMouseIn: view insetDisplayBox!
  38429. recognizeCharactersWhileMouseIn: box
  38430.     "Recognize hand-written characters and put them into the receiving pane.  Invokes Alan's character recognizer.  2/5/96 sw"
  38431.  
  38432.     | aRecognizer |
  38433.     Cursor marker showWhile:
  38434.         [aRecognizer _ CharRecog new.
  38435.         aRecognizer recognizeAndDispatch:
  38436.             [:char | char == BS
  38437.                 ifTrue:
  38438.                     [self simulatedBackspace]
  38439.                 ifFalse:
  38440.                     [self simulatedKeystroke: char]]
  38441.         until:
  38442.             [(box containsPoint: sensor cursorPoint) not]].
  38443.     view display!
  38444. setEmphasisHere
  38445.  
  38446.     emphasisHere _ paragraph text emphasisAt: startBlock stringIndex!
  38447. simulatedKeystroke: char
  38448.     "Accept char as if it were struck on the keyboard.   This version does not (yet) deal with command keys, and achieves update in the receiver's typically inactive window via the sledge-hammer of uncache-bits.  1/31/96 sw"
  38449.  
  38450.     self deselect.
  38451.     self openTypeIn.
  38452.     startBlock = stopBlock ifFalse: "save highlighted characters"
  38453.             [UndoSelection _ self selection]. 
  38454.     self zapSelectionWith: 
  38455.         (Text string: char asString emphasis: emphasisHere).
  38456.     self lockModel.
  38457.     startBlock _ stopBlock copy.
  38458.     self selectAndScroll.
  38459.     self updateMarker.
  38460.     view topView uncacheBits! !
  38461.  
  38462. !ParagraphEditor methodsFor: 'undoers'!
  38463. undoAgain: indices andReselect: home typedKey: wasTypedKey
  38464.     "The last command was again.  Undo it. Redoer: itself."
  38465.  
  38466.     | findSize substText index subject |
  38467.     (self isRedoing & wasTypedKey) ifTrue: "redelete search key"
  38468.         [self selectInterval: home.
  38469.         self zapSelectionWith: self nullText].
  38470.  
  38471.     findSize _ (self isRedoing ifTrue: [FindText] ifFalse: [ChangeText]) size.
  38472.     substText _ self isUndoing ifTrue: [FindText] ifFalse: [ChangeText].
  38473.     (self isUndoing ifTrue: [indices size to: 1 by: -1] ifFalse: [1 to: indices size]) do:
  38474.         [:i |
  38475.         index _ indices at: i.
  38476.         (subject _ index to: index + findSize - 1) = self selectionInterval ifFalse:
  38477.             [self selectInterval: subject].
  38478.         FindText == ChangeText ifFalse: [self zapSelectionWith: substText]].
  38479.  
  38480.     self isUndoing
  38481.         ifTrue:  "restore selection to where it was when 'again' was invoked"
  38482.             [wasTypedKey
  38483.                 ifTrue: "search started by typing key at a caret; restore it"
  38484.                     [self selectAt: home first.
  38485.                     self zapSelectionWith: FindText.
  38486.                     self selectAt: home last + 1]
  38487.                 ifFalse: [self selectInterval: home]].
  38488.  
  38489.     self undoMessage: UndoMessage forRedo: self isUndoing!
  38490. undoAndReselect: undoHighlight redoAndReselect: redoHighlight
  38491.     "Undo typing, cancel, paste, and other operations that are like replaces
  38492.      but the selection is not the whole restored text after undo, redo, or both.
  38493.      undoHighlight is selected after this phase and redoHighlight after the next phase.
  38494.     Redoer: itself."
  38495.  
  38496.     self replace: self selectionInterval with: UndoSelection and:
  38497.         [self selectInterval: undoHighlight].
  38498.     self undoMessage: (UndoMessage argument: redoHighlight) forRedo: self isUndoing
  38499. !
  38500. undoCutCopy: oldPasteBuffer
  38501.     "Undo of a cut, copy, or any edit that changed CurrentSelection.  Be sure
  38502.      undo-copy does not lock the model.  Redoer: itself, so never isRedoing."
  38503.  
  38504.     | recentCut |
  38505.     recentCut _ self clipboardText.    
  38506.     UndoSelection size = UndoInterval size
  38507.         ifFalse: [self replaceSelectionWith: UndoSelection].
  38508.     self clipboardTextPut: oldPasteBuffer.
  38509.     self undoer: #undoCutCopy: with: recentCut!
  38510. undoQuery: hintText lastOffering: selectorOrNil
  38511.     "Undo ctrl-q.  selectorOrNil (if not nil) is the previously offered selector.
  38512.      hintText is the original hint.  Redoer: completeSymbol."
  38513.  
  38514.     self zapSelectionWith: UndoSelection.
  38515.     self undoMessage: (Message selector: #completeSymbol:lastOffering: arguments: UndoMessage arguments) forRedo: true.
  38516.     self selectAt: stopBlock stringIndex!
  38517. undoReplace
  38518.     "Undo of any command that replaced a selection by other text that it left
  38519.      highlighted, and that is undone and redone by simple reversal of the
  38520.      operation.  This is the most common Undoer; call replaceSelectionWith:
  38521.      to get this setup.  Redoer: itself, so never isRedoing."
  38522.  
  38523.     self replaceSelectionWith: UndoSelection! !
  38524.  
  38525. !ParagraphEditor methodsFor: 'undo support'!
  38526. isDoing
  38527.     "Call from a doer/undoer/redoer any time to see which it is."
  38528.  
  38529.     ^(self isUndoing | self isRedoing) not!
  38530. isRedoing
  38531.     "Call from a doer/undoer/redoer any time to see which it is."
  38532.  
  38533.     ^UndoParagraph == #redoing!
  38534. isUndoing
  38535.     "Call from a doer/undoer/redoer any time to see which it is."
  38536.  
  38537.     ^UndoParagraph == #undoing!
  38538. noUndoer
  38539.     "The Undoer to use when the command can not be undone.  Checked for
  38540.      specially by readKeyboard."
  38541.  
  38542.     UndoMessage _ Message selector: #noUndoer!
  38543. undoer: aSelector
  38544.     "See comment in undoMessage:.  Use this version when aSelector has no arguments, and you are doing or redoing and want to prepare for undoing."
  38545.  
  38546.     self undoMessage: (Message selector: aSelector) forRedo: false!
  38547. undoer: aSelector with: arg1
  38548.     "See comment in undoMessage:.  Use this version when aSelector has one argument, and you are doing or redoing and want to prepare for undoing."
  38549.  
  38550.     self undoMessage: (Message selector: aSelector argument: arg1) forRedo: false!
  38551. undoer: aSelector with: arg1 with: arg2
  38552.     "See comment in undoMessage:.  Use this version when aSelector has two arguments, and you are doing or redoing and want to prepare for undoing."
  38553.  
  38554.     self undoMessage: (Message selector: aSelector arguments: (Array with: arg1 with: arg2)) forRedo: false!
  38555. undoer: aSelector with: arg1 with: arg2 with: arg3
  38556.     "See comment in undoMessage:.  Use this version when aSelector has three arguments, and you are doing or redoing and want to prepare for undoing."
  38557.  
  38558.     self undoMessage: (Message selector: aSelector arguments: (Array with: arg1 with: arg2 with: arg3)) forRedo: false!
  38559. undoMessage: aMessage forRedo: aBoolean
  38560.     "Call this from an undoer/redoer to set up UndoMessage as the
  38561.      corresponding redoer/undoer.  Also set up UndoParagraph, as well
  38562.      as the state variable Undone.  It is assumed that UndoInterval has been
  38563.      established (generally by zapSelectionWith:) and that UndoSelection has been
  38564.      saved (generally by replaceSelectionWith: or replace:With:and:)."
  38565.  
  38566.     self isDoing ifTrue: [UndoParagraph _ paragraph].
  38567.     UndoMessage _ aMessage.
  38568.     Undone _ aBoolean! !
  38569.  
  38570. !ParagraphEditor methodsFor: 'current selection'!
  38571. deselect
  38572.     "If the text selection is visible on the screen, reverse its highlight."
  38573.  
  38574.     selectionShowing ifTrue: [self reverseSelection]!
  38575. initializeSelection
  38576.     "Do the initial activity when starting up the receiver. For example, in the 
  38577.     ParagraphEditor highlight the current selection."
  38578.  
  38579.     self select!
  38580. recomputeInterval
  38581.     "The same characters are selected but their coordinates may have changed."
  38582.  
  38583.     self computeIntervalFrom: startBlock stringIndex to: stopBlock stringIndex - 1!
  38584. recomputeSelection
  38585.     "Redetermine the selection according to the start and stop block indices; 
  38586.     do not highlight."
  38587.  
  38588.     self deselect; recomputeInterval!
  38589. reverseSelection
  38590.     "Reverse the valence of the current selection highlighting."
  38591.     selectionShowing _ selectionShowing not.
  38592.     paragraph reverseFrom: startBlock to: stopBlock!
  38593. select
  38594.     "If the text selection is visible on the screen, highlight it."
  38595.  
  38596.     selectionShowing ifFalse: [self reverseSelection]!
  38597. selectAndScroll
  38598.     "Scroll until the selection is in the view and then highlight it."
  38599.     | lineHeight deltaY clippingRectangle |
  38600.     self select.
  38601.     lineHeight _ paragraph textStyle lineGrid.
  38602.     clippingRectangle _ paragraph clippingRectangle.
  38603.     deltaY _ stopBlock top - clippingRectangle top.
  38604.     deltaY >= 0 
  38605.         ifTrue: [deltaY _ stopBlock bottom - clippingRectangle bottom max: 0].
  38606.                         "check if stopIndex below bottom of clippingRectangle"
  38607.     deltaY ~= 0 
  38608.         ifTrue: [self scrollBy: (deltaY abs + lineHeight - 1 truncateTo: lineHeight)
  38609.                                     * deltaY sign]! !
  38610.  
  38611. !ParagraphEditor methodsFor: 'new selection'!
  38612. computeIntervalFrom: start to: stop
  38613.     "Select the designated characters, inclusive.  Make no visual changes."
  38614.  
  38615.     startBlock _ paragraph characterBlockForIndex: start.
  38616.     stopBlock _ start > stop
  38617.         ifTrue: [startBlock copy]
  38618.         ifFalse: [paragraph characterBlockForIndex: stop + 1]!
  38619. selectAt: characterIndex 
  38620.     "Deselect, then place the caret before the character at characterIndex.
  38621.      Be sure it is in view."
  38622.  
  38623.     self selectFrom: characterIndex to: characterIndex - 1!
  38624. selectFrom: start to: stop
  38625.     "Deselect, then select the specified characters inclusive.
  38626.      Be sure the selection is in view."
  38627.  
  38628.     (start = startBlock stringIndex and: [stop + 1 = stopBlock stringIndex]) ifFalse:
  38629.         [self deselect.
  38630.         self selectInvisiblyFrom: start to: stop].
  38631.     self selectAndScroll!
  38632. selectInterval: anInterval
  38633.     "Deselect, then select the specified characters inclusive.
  38634.      Be sure the selection is in view."
  38635.  
  38636.     self selectFrom: anInterval first to: anInterval last!
  38637. selectInvisiblyFrom: start to: stop
  38638.     "Select the designated characters, inclusive.  Make no visual changes."
  38639.  
  38640.     (start = startBlock stringIndex and: [stop + 1 = stopBlock stringIndex]) ifFalse:
  38641.         [self computeIntervalFrom: start to: stop]!
  38642. selectPrecedingIdentifier
  38643.     "Invisibly select the identifier that ends at the end of the selection, if any."
  38644.  
  38645.     | string sep stop tok |
  38646.     tok _ false.
  38647.     string _ paragraph text string.
  38648.     stop _ stopBlock stringIndex - 1.
  38649.     [stop > 0 and: [(string at: stop) isSeparator]] whileTrue: [stop _ stop - 1].
  38650.     sep _ stop.
  38651.     [sep > 0 and: [(string at: sep) tokenish]] whileTrue: [tok _ true. sep _ sep - 1].
  38652.     tok ifTrue: [self selectInvisiblyFrom: sep + 1 to: stop]!
  38653. selectWord
  38654.     "Select delimited text or word--the result of double-clicking."
  38655.  
  38656.     | openDelimiter closeDelimiter direction match level leftDelimiters rightDelimiters
  38657.     string here hereChar start stop |
  38658.     string _ paragraph text string.
  38659.     here _ startBlock stringIndex.
  38660.     (here between: 2 and: string size)
  38661.         ifFalse: ["if at beginning or end, select entire string"
  38662.             ^self selectFrom: 1 to: string size].
  38663.     leftDelimiters _ '([{<''"
  38664. '.
  38665.     rightDelimiters _ ')]}>''"
  38666. '.
  38667.     openDelimiter _ string at: here - 1.
  38668.     match _ leftDelimiters indexOf: openDelimiter.
  38669.     match > 0
  38670.         ifTrue: 
  38671.             ["delimiter is on left -- match to the right"
  38672.             start _ here.
  38673.             direction _ 1.
  38674.             here _ here - 1.
  38675.             closeDelimiter _ rightDelimiters at: match]
  38676.         ifFalse: 
  38677.             [openDelimiter _ string at: here.
  38678.             match _ rightDelimiters indexOf: openDelimiter.
  38679.             match > 0
  38680.                 ifTrue: 
  38681.                     ["delimiter is on right -- match to the left"
  38682.                     stop _ here - 1.
  38683.                     direction _ -1.
  38684.                     closeDelimiter _ leftDelimiters at: match]
  38685.                 ifFalse: ["no delimiters -- select a token"
  38686.                     direction _ -1]].
  38687.     level _ 1.
  38688.     [level > 0 and: [direction > 0
  38689.             ifTrue: [here < string size]
  38690.             ifFalse: [here > 1]]]
  38691.         whileTrue: 
  38692.             [hereChar _ string at: (here _ here + direction).
  38693.             match = 0
  38694.                 ifTrue: ["token scan goes left, then right"
  38695.                     hereChar tokenish
  38696.                         ifTrue: [here = 1
  38697.                                 ifTrue: 
  38698.                                     [start _ 1.
  38699.                                     "go right if hit string start"
  38700.                                     direction _ 1]]
  38701.                         ifFalse: [direction < 0
  38702.                                 ifTrue: 
  38703.                                     [start _ here + 1.
  38704.                                     "go right if hit non-token"
  38705.                                     direction _ 1]
  38706.                                 ifFalse: [level _ 0]]]
  38707.                 ifFalse: ["bracket match just counts nesting level"
  38708.                     hereChar = closeDelimiter
  38709.                         ifTrue: [level _ level - 1"leaving nest"]
  38710.                         ifFalse: [hereChar = openDelimiter 
  38711.                                     ifTrue: [level _ level + 1"entering deeper nest"]]]].
  38712.  
  38713.     level > 0 ifTrue: ["in case ran off string end"    here _ here + direction].
  38714.     direction > 0
  38715.         ifTrue: [self selectFrom: start to: here - 1]
  38716.         ifFalse: [self selectFrom: here + 1 to: stop]! !
  38717.  
  38718. !ParagraphEditor methodsFor: 'private'!
  38719. againOnce: indices
  38720.     "Find the next occurrence of FindText.  If none, answer false.
  38721.      Append the start index of the occurrence to the stream indices, and, if
  38722.      ChangeText is not the same object as FindText, replace the occurrence by it."
  38723.  
  38724.     | where |
  38725.     where _ paragraph text findString: FindText startingAt: stopBlock stringIndex.
  38726.     where = 0 ifTrue: [^false].
  38727.     self deselect; selectInvisiblyFrom: where to: where + FindText size - 1.
  38728.     ChangeText ~~ FindText ifTrue: [self zapSelectionWith: ChangeText].
  38729.     indices nextPut: where.
  38730.     self selectAndScroll.
  38731.     ^true!
  38732. againOrSame: useOldKeys
  38733.     "Subroutine of search: and again.  If useOldKeys, use same FindText and ChangeText as before.
  38734.      1/26/96 sw: real worked moved to againOrSame:many:"
  38735.  
  38736.     ^ self againOrSame: useOldKeys many: sensor leftShiftDown!
  38737. againOrSame: useOldKeys many: many
  38738.     "Subroutine of search: and again.  If useOldKeys, use same FindText and ChangeText as before.  If many is true, do it repeatedly.  Created 1/26/96 sw by adding the many argument to #againOrSame."
  38739.  
  38740.     |  home indices wasTypedKey |
  38741.  
  38742.     home _ self selectionInterval.  "what was selected when 'again' was invoked"
  38743.  
  38744.     "If new keys are to be picked..."
  38745.     useOldKeys ifFalse: "Choose as FindText..."
  38746.         [FindText _ UndoSelection.  "... the last thing replaced."
  38747.         "If the last command was in another paragraph, ChangeText is set..."
  38748.         paragraph == UndoParagraph ifTrue: "... else set it now as follows."
  38749.             [UndoInterval ~= home ifTrue: [self selectInterval: UndoInterval]. "blink"
  38750.             ChangeText _ ((UndoMessage sends: #undoCutCopy:) and: [startBlock ~= stopBlock])
  38751.                 ifTrue: [FindText] "== objects signal no model-locking by 'undo copy'"
  38752.                 ifFalse: [self selection]]]. "otherwise, change text is last-replaced text"
  38753.  
  38754.     (wasTypedKey _ FindText size = 0)
  38755.         ifTrue: "just inserted at a caret"
  38756.             [home _ self selectionInterval.
  38757.             self replaceSelectionWith: self nullText.  "delete search key..."
  38758.             FindText _ ChangeText] "... and search for it, without replacing"
  38759.         ifFalse: "Show where the search will start"
  38760.             [home last = self selectionInterval last ifFalse:
  38761.                 [self selectInterval: home]].
  38762.  
  38763.     "Find and Change, recording start indices in the array"
  38764.     indices _ WriteStream on: (Array new: 20). "an array to store change locs"
  38765.     [(self againOnce: indices) & many] whileTrue. "<-- this does the work"
  38766.     indices isEmpty ifTrue:  "none found"
  38767.         [self flash.
  38768.         wasTypedKey ifFalse: [^self]].
  38769.  
  38770.     (many | wasTypedKey) ifFalse: "after undo, select this replacement"
  38771.         [home _ startBlock stringIndex to:
  38772.             startBlock stringIndex + UndoSelection size - 1].
  38773.  
  38774.     self undoer: #undoAgain:andReselect:typedKey: with: indices contents with: home with: wasTypedKey!
  38775. completeSymbol: hintText lastOffering: selectorOrNil
  38776.     "Invoked by Ctrl-q when there is only a caret.
  38777.         Do selector-completion, i.e., try to replace the preceding identifier by a
  38778.         selector that begins with those characters & has as many keywords as possible.
  38779.          Leave two spaces after each colon (only one after the last) as space for
  38780.         arguments.  Put the caret after the space after the first keyword.  If the
  38781.         user types Ctrl-q again immediately, choose a different selector.
  38782.      Undoer: #undoQuery:lastOffering:; Redoer: itself.
  38783.     If redoing, just redisplay the last offering, selector[OrNil]."
  38784.  
  38785.     | firstTime input prior caret newStart sym kwds blockNode outStream |
  38786.     firstTime _ self isRedoing
  38787.         ifTrue: [prior _ sym _ selectorOrNil. true]
  38788.         ifFalse: [hintText isNil].
  38789.     firstTime
  38790.         ifTrue: "Initial Ctrl-q (or redo)"                    
  38791.             [caret _ startBlock stringIndex.
  38792.             self selectPrecedingIdentifier.
  38793.             input _ self selection]
  38794.         ifFalse: "Repeated Ctrl-q"
  38795.             [caret _ UndoInterval first + hintText size.
  38796.             self selectInvisiblyFrom: UndoInterval first to: UndoInterval last.
  38797.             input _ hintText.
  38798.             prior _ selectorOrNil].
  38799.     (input size ~= 0 and: [sym ~~ nil or:
  38800.             [(sym _ Symbol thatStarts: input string skipping: prior) ~~ nil]])
  38801.         ifTrue: "found something to offer"
  38802.             [newStart _ startBlock stringIndex.
  38803.             outStream _ WriteStream on: (String new: 2 * sym size).
  38804.             1 to: (kwds _ sym keywords) size do:
  38805.                 [:i |
  38806.                 outStream nextPutAll: (kwds at: i).
  38807.                 i = 1 ifTrue: [caret _ newStart + outStream contents size + 1].
  38808.                 outStream nextPutAll:
  38809.                     (i < kwds size ifTrue: ['  '] ifFalse: [' '])].
  38810.             UndoSelection _ input.
  38811.             self deselect; zapSelectionWith: outStream contents asText.
  38812.             self undoer: #undoQuery:lastOffering: with: input with: sym]
  38813.         ifFalse: "no more matches"
  38814.             [firstTime ifFalse: "restore original text & set up for a redo"
  38815.                 [UndoSelection _ self selection.
  38816.                 self deselect; zapSelectionWith: input.
  38817.                 self undoer: #completeSymbol:lastOffering: with: input with: prior.
  38818.                 Undone _ true].
  38819.             view flash].
  38820.     self selectAt: caret!
  38821. exchangeWith: prior
  38822.     "If the prior selection is non-overlapping and legal, exchange the text of
  38823.      it with the current selection and leave the currently selected text selected
  38824.      in the location of the prior selection (or leave a caret after a non-caret if it was
  38825.      exchanged with a caret).  If both selections are carets, flash & do nothing.
  38826.      Don't affect the paste buffer.  Undoer: itself; Redoer: Undoer."
  38827.  
  38828.     | start stop before selection priorSelection delta altInterval |
  38829.     start _ startBlock stringIndex.
  38830.     stop _ stopBlock stringIndex - 1.
  38831.     ((prior first <= prior last) | (start <= stop) "Something to exchange" and:
  38832.             [self isDisjointFrom: prior])
  38833.         ifTrue:
  38834.             [before _ prior last < start.
  38835.             selection _ self selection.
  38836.             priorSelection _ paragraph text copyFrom: prior first to: prior last.
  38837.  
  38838.             delta _ before ifTrue: [0] ifFalse: [priorSelection size - selection size].
  38839.             self zapSelectionWith: priorSelection.
  38840.             self selectFrom: prior first + delta to: prior last + delta.
  38841.  
  38842.             delta _ before ifTrue: [stop - prior last] ifFalse: [start - prior first].
  38843.             self zapSelectionWith: selection.
  38844.             altInterval _ prior first + delta to: prior last + delta.
  38845.             self undoer: #exchangeWith: with: altInterval.
  38846.             "If one was a caret, make it otherInterval & leave the caret after the other"
  38847.             prior first > prior last ifTrue: [self selectAt: UndoInterval last + 1].
  38848.             otherInterval _ start > stop
  38849.                 ifTrue: [self selectAt: altInterval last + 1. UndoInterval]
  38850.                 ifFalse: [altInterval]]
  38851.         ifFalse:
  38852.             [view flash]!
  38853. indent: delta fromStream: inStream toStream: outStream
  38854.     "Append the contents of inStream to outStream, adding or deleting delta or -delta
  38855.      tabs at the beginning, and after every CR except a final CR.  Do not add tabs
  38856.      to totally empty lines, and be sure nothing but tabs are removed from lines."
  38857.  
  38858.     | ch skip cr tab prev atEnd |
  38859.     cr _ Character cr.
  38860.     tab _ Character tab.
  38861.     delta > 0
  38862.         ifTrue: "shift right"
  38863.             [prev _ cr.
  38864.              [ch _ (atEnd _ inStream atEnd) ifTrue: [cr] ifFalse: [inStream next].
  38865.               (prev == cr and: [ch ~~ cr]) ifTrue:
  38866.                 [delta timesRepeat: [outStream nextPut: tab]].
  38867.               atEnd]
  38868.                 whileFalse:
  38869.                     [outStream nextPut: ch.
  38870.                     prev _ ch]]
  38871.         ifFalse: "shift left"
  38872.             [skip _ delta. "a negative number"
  38873.              [inStream atEnd] whileFalse:
  38874.                 [((ch _ inStream next) == tab and: [skip < 0]) ifFalse:
  38875.                     [outStream nextPut: ch].
  38876.                 skip _ ch == cr ifTrue: [delta] ifFalse: [skip + 1]]]!
  38877. initializeYellowButtonMenu
  38878.  
  38879.     self yellowButtonMenu: TextEditorYellowButtonMenu 
  38880.         yellowButtonMessages: TextEditorYellowButtonMessages !
  38881. isDisjointFrom: anInterval
  38882.     "Answer true if anInterval is a caret not touching or within the current
  38883.      interval, or if anInterval is a non-caret that does not overlap the current
  38884.      selection."
  38885.  
  38886.     | fudge |
  38887.     fudge _ anInterval size = 0 ifTrue: [1] ifFalse: [0].
  38888.     ^(anInterval last + fudge < startBlock stringIndex or:
  38889.             [anInterval first - fudge >= stopBlock stringIndex])
  38890. !
  38891. nullText
  38892.  
  38893.     ^Text string: '' emphasis: emphasisHere! !
  38894. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  38895.  
  38896. ParagraphEditor class
  38897.     instanceVariableNames: ''!
  38898.  
  38899. !ParagraphEditor class methodsFor: 'class initialization'!
  38900. initialize
  38901.     "Initialize the keyboard shortcut maps and the shared buffers for copying text across views and managing again and undo.
  38902.     6/18/96 sw: call initializeTextEditorMenus
  38903.     other times: marked change to trigger reinit"
  38904.  
  38905.     "ParagraphEditor initialize"
  38906.  
  38907.     CurrentSelection _ UndoSelection _ FindText _ ChangeText _ Text new.
  38908.     UndoMessage _ Message selector: #halt.
  38909.  
  38910.     self initializeCmdKeyShortcuts.
  38911.     self initializeShiftCmdKeyShortcuts.
  38912.  
  38913.     self initializeTextEditorMenus
  38914. !
  38915. initializeTextEditorMenus
  38916.     "Initialize the yellow button pop-up menu and corresponding messages.
  38917.     6/1/96 sw moved here from StringHolderController initialize so it can be shared by vanilla ParagraphEditors."
  38918.  
  38919.     TextEditorYellowButtonMenu _ 
  38920.         PopUpMenu 
  38921.             labels: 
  38922. 'find...(f)
  38923. find again (g)
  38924. set search string (h)
  38925. do again (j)
  38926. undo (z)
  38927. copy (c)
  38928. cut (x)
  38929. paste (v)
  38930. do it (d)
  38931. print it (p)
  38932. inspect it (i)
  38933. accept (s)
  38934. cancel (l)
  38935. more...' 
  38936.         lines: #(3 5  8 11 13).
  38937.     TextEditorYellowButtonMessages _ 
  38938.         #(find findAgain setSearchString again undo copySelection cut paste doIt printIt inspectIt accept cancel shiftedYellowButtonActivity)
  38939.  
  38940.     "ParagraphEditor initializeTextEditorMenus"! !
  38941.  
  38942. !ParagraphEditor class methodsFor: 'instance creation'!
  38943. new
  38944.     "Answer a new instance of me with a null Paragraph to be edited."
  38945.  
  38946.     | aParagraphEditor |
  38947.     aParagraphEditor _ super new.
  38948.     aParagraphEditor initialize.
  38949.     aParagraphEditor changeParagraph: '' asParagraph.
  38950.     ^aParagraphEditor!
  38951. newParagraph: aParagraph 
  38952.     "Answer an instance of me with aParagraph as the text to be edited."
  38953.  
  38954.     | aParagraphEditor |
  38955.     aParagraphEditor _ super new.
  38956.     aParagraphEditor initialize.
  38957.     aParagraphEditor changeParagraph: aParagraph.
  38958.     ^aParagraphEditor! !
  38959.  
  38960. !ParagraphEditor class methodsFor: 'keyboard shortcut tables'!
  38961. initializeCmdKeyShortcuts
  38962.     "Initialize the (unshifted) command-key shortcut table."
  38963.     "ParagraphEditor initialize"
  38964.  
  38965.     | cmdMap cmds |
  38966.     cmdMap _ Array new: 256.  "use temp in case of a crash"
  38967.     cmdMap atAllPut: #noop:.
  38968.     cmdMap at: ( 8 + 1) put: #backspace:.            "ctrl-H or delete key"
  38969.     cmdMap at: (27 + 1) put: #selectCurrentTypeIn:.    "escape key"
  38970.  
  38971.     '0123456789'    do: [ :char | cmdMap at: (char asciiValue + 1) put: #changeEmphasis: ].
  38972.     '([{''"<'        do: [ :char | cmdMap at: (char asciiValue + 1) put: #enclose: ].
  38973.     cmdMap at: ($, asciiValue + 1) put: #shiftEnclose:.
  38974.  
  38975.     cmds _ #(
  38976.         $a    selectAll:
  38977.         $b    browseIt:
  38978.         $c    copySelection:
  38979.         $d    doIt:
  38980.         $e    exchange:
  38981.         $f    find:
  38982.         $g    findAgain:
  38983.         $h    setSearchString:
  38984.         $i    inspectIt:
  38985.         $j    doAgainOnce:
  38986.         $k  offerFontMenu:
  38987.         $l    cancel:
  38988.         $m    implementorsOfIt:
  38989.         $n    sendersOfIt:
  38990.         $o    spawnIt:
  38991.         $p    printIt:
  38992.         $q    querySymbol:
  38993.         $r    recognizer:
  38994.         $s    save:
  38995.         $t    tempCommand:
  38996.         $u    align:
  38997.         $v    paste:
  38998.         $w    backWord:
  38999.         $x    cut:
  39000.         $y    swapChars:
  39001.         $z    undo:
  39002.     ).
  39003.     1 to: cmds size by: 2 do: [ :i |
  39004.         cmdMap at: ((cmds at: i) asciiValue + 1) put: (cmds at: i + 1).
  39005.     ].
  39006.     CmdActions _ cmdMap.
  39007. !
  39008. initializeShiftCmdKeyShortcuts
  39009.     "Initialize the shift-command-key (or control-key) shortcut table."
  39010.  
  39011.     | cmdMap cmds |
  39012.     "shift-command and control shortcuts"
  39013.     cmdMap _ Array new: 256.  "use temp in case of a crash"
  39014.     cmdMap atAllPut: #noop:.
  39015.     cmdMap at: ( 8 + 1) put: #backspace:.            "ctrl-H or delete key"
  39016.     cmdMap at: (27 + 1) put: #selectCurrentTypeIn:.    "escape key"
  39017.  
  39018.     "Note: Command key overrides shift key, so, for example, cmd-shift-9 produces $9 not $("
  39019.     '9[,''' do: [ :char | cmdMap at: (char asciiValue + 1) put: #shiftEnclose: ].    "({< and double-quote"
  39020.     cmdMap at: (27 + 1) put: #shiftEnclose:.    "ctrl-["
  39021.     "Note: Must use cmd-9 or ctrl-9 to get '()' since cmd-shift-9 is a Mac FKey command."
  39022.  
  39023.     cmds _ #(
  39024.         $a    argAdvance:
  39025.         $b    browseItHere:
  39026.         $c    compareToClipboard:
  39027.         $d    duplicate:
  39028.         $f    displayIfFalse:
  39029.         $j    doAgainMany:
  39030.         $k    changeStyle:
  39031.         $n    referencesToIt:
  39032.         $r    indent:
  39033.         $l    outdent:
  39034.         $s    search:
  39035.         $t    displayIfTrue:
  39036.         $w    methodNamesContainingIt:
  39037.         $v    pasteInitials:
  39038.     ).
  39039.     1 to: cmds size by: 2 do: [ :i |
  39040.         cmdMap at: ((cmds at: i) asciiValue + 1)            put: (cmds at: i + 1).
  39041.         cmdMap at: (((cmds at: i) asciiValue - 96) + 1)    put: (cmds at: i + 1).
  39042.     ].
  39043.     ShiftCmdActions _ cmdMap.! !
  39044.  
  39045. !ParagraphEditor class methodsFor: 'clipboard access'!
  39046. clipboardContents
  39047.     "Answer a copy of the text last cut or copied.  5/29/96 sw"
  39048.  
  39049.     ^ CurrentSelection deepCopy! !
  39050.  
  39051. ParagraphEditor initialize!
  39052. Object subclass: #ParseNode
  39053.     instanceVariableNames: 'comment '
  39054.     classVariableNames: 'StdSelectors NodeThisContext Send NodeFalse LdInstLong LdLitIndType Jmp LdSuper LdThisContext SendType StdLiterals Store LdTrue Dup NodeSelf ShortStoP LdInstType NodeTrue LdSelf JmpLong CodeBases StdVariables LdFalse SendPlus JmpLimit CodeLimits SendLimit Bfp LdTempType LdNil BtpLong EndMethod StorePop LdMinus1 LdLitType SendLong NodeNil NodeSuper EndRemote Pop '
  39055.     poolDictionaries: ''
  39056.     category: 'System-Compiler'!
  39057. ParseNode comment:
  39058. 'This superclass of most compiler/decompiler classes declares common class variables, default messages, and the code emitters for jumps. Some of the class variables are initialized here; the rest are initialized in class VariableNode.'!
  39059.  
  39060. !ParseNode methodsFor: 'testing'!
  39061. assignmentCheck: encoder at: location
  39062.     "For messageNodes masquerading as variables for the debugger.
  39063.     For now we let this through - ie we allow stores ev
  39064.     into args.  Should check against numArgs, though."
  39065.     ^ -1!
  39066. canBeSpecialArgument
  39067.     "Can I be an argument of (e.g.) ifTrue:?"
  39068.  
  39069.     ^false!
  39070. canCascade
  39071.  
  39072.     ^false!
  39073. isArg
  39074.  
  39075.     ^false!
  39076. isComplex
  39077.     "Used for pretty printing to determine whether to start a new line"
  39078.  
  39079.     ^false!
  39080. isConstantNumber  "Overridden in LiteralNode"
  39081.     ^false!
  39082. isMessage: selSymbol receiver: rcvrPred arguments: argsPred
  39083.     "See comment in MessageNode."
  39084.  
  39085.     ^false!
  39086. isReturningIf
  39087.  
  39088.     ^false!
  39089. isReturnSelf
  39090.  
  39091.     ^false!
  39092. isSelfPsuedoVariable    "Overridden in VariableNode."
  39093.     ^false!
  39094. isSpecialConstant
  39095.     ^ false!
  39096. isVariableReference
  39097.  
  39098.     ^false!
  39099. prefersValue
  39100.     "return true of this node generates shorter code when it leaves a value
  39101.     on the stack"
  39102.     ^ true!
  39103. toDoIncrement: ignored
  39104.     "Only meant for Messages or Assignments - else return nil"
  39105.     ^ nil! !
  39106.  
  39107. !ParseNode methodsFor: 'code generation'!
  39108. emitBranchOn:
  39109. condition dist: dist pop: stack on: strm
  39110.     stack pop: 1.
  39111.     dist = 0 ifTrue: [^ strm nextPut: Pop].
  39112.     condition
  39113.         ifTrue: [self emitLong: dist code: BtpLong on: strm]
  39114.         ifFalse: [self emitShortOrLong: dist code: Bfp on: strm]!
  39115. emitForEffect: stack on: strm
  39116.  
  39117.     self emitForValue: stack on: strm.
  39118.     strm nextPut: Pop.
  39119.     stack pop: 1!
  39120. emitForReturn: stack on: strm
  39121.  
  39122.     self emitForValue: stack on: strm.
  39123.     strm nextPut: EndMethod!
  39124. emitJump: dist on: strm
  39125.  
  39126.     dist = 0 ifFalse: [self emitShortOrLong: dist code: Jmp on: strm]!
  39127. emitLong: dist code: longCode on: aStream 
  39128.     "Force a two-byte jump."
  39129.     | code distance |
  39130.     code _ longCode.
  39131.     distance _ dist.
  39132.     distance < 0
  39133.         ifTrue: 
  39134.             [distance _ distance + 1024.
  39135.             code _ code - 4]
  39136.         ifFalse: 
  39137.             [distance > 1023 ifTrue: [distance _ -1]].
  39138.     distance < 0
  39139.         ifTrue: 
  39140.             [self error: 'A block compiles more than 1K bytes of code']
  39141.         ifFalse: 
  39142.             [aStream nextPut: distance // 256 + code.
  39143.             aStream nextPut: distance \\ 256]!
  39144. emitShortOrLong: dist code: shortCode on: strm
  39145.     (1 <= dist and: [dist <= JmpLimit])
  39146.         ifTrue: [strm nextPut: shortCode + dist - 1]
  39147.         ifFalse: [self emitLong: dist code: shortCode + (JmpLong-Jmp) on: strm]!
  39148. noteToDan
  39149.     "Bytecode 132 has now been redefined as DoubleExtendedDoAnything
  39150.         byte2                byte3        Operation
  39151. (hi 3 bits)  (lo 5 bits)
  39152.     0        nargs            lit index    Send Literal Message 0-255
  39153.     1        nargs            lit index    Super-Send Lit Msg 0-255
  39154.     2        ignored            rcvr index    Push Receiver Variable 0-255
  39155.     3        ignored            lit index    Push Literal Constant 0-255
  39156.     4        ignored            lit index    Push Literal Variable 0-255
  39157.     5        ignored            rcvr index    Store Receiver Variable 0-255
  39158.     6        ignored            rcvr index    Store-pop Receiver Variable 0-255
  39159.     7        ignored            lit index    Store Literal Variable 0-255"
  39160.  
  39161.     "Bytecode 134 has also been redefined as a second extended send
  39162.     that can access literals up to 64 for nargs up to 3.  It is just like
  39163.     131, except that the extendion byte is aallllll instead of aaalllll,
  39164.     where aaa are bits of argument count, and lll are bits of literal index."
  39165.  
  39166.     "What remains is to start compiling and using these operations...
  39167.     First compile 2, 5, 6, and test on a class with >63 inst vars.
  39168.     Note that quick-returns already work above 63.
  39169.     Then compile 3, 4, 7, and test on a method with > 63 literals."
  39170. !
  39171. sizeBranchOn: condition dist: dist
  39172.     dist = 0 ifTrue: [^1].
  39173.     ^ condition
  39174.         ifTrue: [2]  "Branch on true is always 2 bytes"
  39175.         ifFalse: [self sizeShortOrLong: dist]!
  39176. sizeForEffect: encoder
  39177.  
  39178.     ^(self sizeForValue: encoder) + 1!
  39179. sizeForReturn: encoder
  39180.  
  39181.     ^(self sizeForValue: encoder) + 1!
  39182. sizeJump: dist
  39183.  
  39184.     dist = 0 ifTrue: [^0].
  39185.     ^self sizeShortOrLong: dist!
  39186. sizeShortOrLong: dist
  39187.  
  39188.     (1 <= dist and: [dist <= JmpLimit])
  39189.         ifTrue: [^1].
  39190.     ^2! !
  39191.  
  39192. !ParseNode methodsFor: 'encoding'!
  39193. encodeSelector: selector
  39194.  
  39195.     ^nil! !
  39196.  
  39197. !ParseNode methodsFor: 'comment'!
  39198. comment
  39199.  
  39200.     ^comment!
  39201. comment: newComment
  39202.  
  39203.     comment _ newComment! !
  39204.  
  39205. !ParseNode methodsFor: 'converting'!
  39206. asReturnNode
  39207.  
  39208.     ^ReturnNode new expr: self! !
  39209.  
  39210. !ParseNode methodsFor: 'printing'!
  39211. printCommentOn: aStream indent: indent
  39212.  
  39213.     | thisComment |
  39214.     comment == nil ifTrue: [^self].
  39215.     1 to: comment size do: 
  39216.         [:index | 
  39217.         index > 1 ifTrue: [aStream crtab: indent].
  39218.         aStream nextPut: $".
  39219.         thisComment _ comment at: index.
  39220.         self printSingleComment: thisComment
  39221.             on: aStream
  39222.             indent: indent.
  39223.         aStream nextPut: $"].
  39224.     comment _ nil!
  39225. printOn: aStream 
  39226.     "Refer to the comment in Object|printOn:."
  39227.  
  39228.     aStream nextPutAll: '{'.
  39229.     self printOn: aStream indent: 0.
  39230.     aStream nextPutAll: '}'!
  39231. printOn: aStream indent: anInteger 
  39232.     "If control gets here, avoid recursion loop."
  39233.  
  39234.     super printOn: aStream!
  39235. printOn: aStream indent: level precedence: p
  39236.  
  39237.     self printOn: aStream indent: level! !
  39238.  
  39239. !ParseNode methodsFor: 'private'!
  39240. nextWordFrom: aStream setCharacter: aBlock
  39241.  
  39242.     | outStream char |
  39243.     outStream _ WriteStream on: (String new: 16).
  39244.     [aStream atEnd
  39245.         or: 
  39246.             [char _ aStream next.
  39247.             char = Character cr or: [char = Character space]]]
  39248.         whileFalse: [outStream nextPut: char].
  39249.     aBlock value: char.
  39250.     ^outStream contents!
  39251. printSingleComment: aString on: aStream indent: indent 
  39252.     "Print the comment string, assuming it has been indented indent tabs.   
  39253.     Break the string at word breaks, given the widths in the default font, at 
  39254.     450 points."
  39255.  
  39256.     | readStream word position lineBreak lastChar font wordWidth tabWidth spaceWidth |
  39257.     readStream _ ReadStream on: aString.
  39258.     font _ TextStyle default defaultFont.
  39259.     tabWidth _ TextConstants at: #DefaultTab.
  39260.     spaceWidth _ font widthOf: Character space.
  39261.     position _ indent * tabWidth.
  39262.     lineBreak _ 450.
  39263.     [readStream atEnd]
  39264.         whileFalse: 
  39265.             [word _ self nextWordFrom: readStream setCharacter: [:lastChar | lastChar].
  39266.             wordWidth _ 0.
  39267.             word do: [:char | wordWidth _ wordWidth + (font widthOf: char)].
  39268.             position _ position + wordWidth.
  39269.             position > lineBreak
  39270.                 ifTrue: 
  39271.                     [aStream crtab: indent.
  39272.                     position _ indent * tabWidth + wordWidth + spaceWidth.
  39273.                     lastChar = Character cr
  39274.                         ifTrue: [[readStream peekFor: Character tab] whileTrue].
  39275.                     aStream nextPutAll: word; space]
  39276.                 ifFalse: 
  39277.                     [aStream nextPutAll: word.
  39278.                     readStream atEnd
  39279.                         ifFalse: 
  39280.                             [position _ position + spaceWidth.
  39281.                             aStream space].
  39282.                     lastChar = Character cr
  39283.                         ifTrue: 
  39284.                             [aStream crtab: indent.
  39285.                             position _ indent * tabWidth.
  39286.                             [readStream peekFor: Character tab] whileTrue]]]! !
  39287.  
  39288. !ParseNode methodsFor: 'equation translation-public access'!
  39289. allVariables
  39290.     ^self collectVariables asSet! !
  39291.  
  39292. !ParseNode methodsFor: 'equation translation'!
  39293. collectVariables
  39294.     "Collects all the variables in my subtree and returns their keys
  39295.     as an array.  Does not eliminate duplicates."
  39296.     self subclassResponsibility!
  39297. copyReplacingVariables: varDict
  39298.     "Return a copy of myself but replace any variable in the dictionary
  39299.     with the corresponding tree."
  39300.     self subclassResponsibility!
  39301. match: aTree using: matchDict 
  39302.     "Match myself as a pattern against the tree.  Because I can
  39303.     contain variables that match complete subtrees, I keep a dictionary
  39304.     of such matches that I found so far."
  39305.     ^(aTree isMemberOf: self class)
  39306.         and: [self specificMatch: aTree using: matchDict]!
  39307. moveVariableToFarLeft: aVariable
  39308.     "Move the variable with this key as far left as possible
  39309.     using the message 'swapSides'."
  39310.     self subclassResponsibility! !
  39311. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  39312.  
  39313. ParseNode class
  39314.     instanceVariableNames: ''!
  39315.  
  39316. !ParseNode class methodsFor: 'class initialization'!
  39317. initialize
  39318.     "ParseNode initialize. VariableNode initialize"
  39319.     LdInstType _ 1.
  39320.     LdTempType _ 2.
  39321.     LdLitType _ 3.
  39322.     LdLitIndType _ 4.
  39323.     SendType _ 5.
  39324.     CodeBases _ #(0 16 32 64 208 ).
  39325.     CodeLimits _ #(16 16 32 32 16 ).
  39326.     LdSelf _ 112.
  39327.     LdTrue _ 113.
  39328.     LdFalse _ 114.
  39329.     LdNil _ 115.
  39330.     LdMinus1 _ 116.
  39331.     LdInstLong _ 128.
  39332.     Store _ 129.
  39333.     StorePop _ 130.
  39334.     ShortStoP _ 96.
  39335.     SendLong _ 131.
  39336.     LdSuper _ 133.
  39337.     Pop _ 135.
  39338.     Dup _ 136.
  39339.     LdThisContext _ 137.
  39340.     EndMethod _ 124.
  39341.     EndRemote _ 125.
  39342.     Jmp _ 144.
  39343.     Bfp _ 152.
  39344.     JmpLimit _ 8.
  39345.     JmpLong _ 164.  "code for jmp 0"
  39346.     BtpLong _ 168.
  39347.     SendPlus _ 176.
  39348.     Send _ 208.
  39349.     SendLimit _ 16! !
  39350.  
  39351. ParseNode initialize!
  39352. Scanner subclass: #Parser
  39353.     instanceVariableNames: 'here hereType hereMark prevToken prevMark encoder requestor parseNode failBlock requestorOffset tempsMark '
  39354.     classVariableNames: ''
  39355.     poolDictionaries: ''
  39356.     category: 'System-Compiler'!
  39357. Parser comment:
  39358. 'I parse Smalltalk syntax and create a MethodNode that is the root of the parse tree. I look one token ahead.'!
  39359.  
  39360. !Parser methodsFor: 'public access'!
  39361. encoder
  39362.     ^ encoder!
  39363. parse: sourceStream class: class noPattern: noPattern context: ctxt notifying: req ifFail: aBlock 
  39364.     "Answer a MethodNode for the argument, sourceStream, that is the root of 
  39365.     a parse tree. Parsing is done with respect to the argument, class, to find 
  39366.     instance, class, and pool variables; and with respect to the argument, 
  39367.     ctxt, to find temporary variables. Errors in parsing are reported to the 
  39368.     argument, req, if not nil; otherwise aBlock is evaluated. The argument 
  39369.     noPattern is a Boolean that is true if the the sourceStream does not 
  39370.     contain a method header (i.e., for DoIts)."
  39371.  
  39372.      | meth |
  39373.     self init: sourceStream notifying: req failBlock: [^aBlock value].
  39374.     encoder _ Encoder new init: class context: ctxt notifying: self.
  39375.     failBlock_ aBlock.
  39376.     meth _ self method: noPattern context: ctxt.
  39377.     encoder _ failBlock _ requestor _ parseNode _ nil. "break cycles & mitigate refct overflow"
  39378.     ^meth!
  39379. parseArgsAndTemps: aString notifying: req 
  39380.     "Parse the argument, aString, notifying req if an error occurs. Otherwise, 
  39381.     answer a two-element Array containing Arrays of strings (the argument 
  39382.     names and temporary variable names)."
  39383.  
  39384.     aString == nil ifTrue: [^#()].
  39385.     ^self
  39386.         initPattern: aString
  39387.         notifying: req
  39388.         return: [:pattern | (pattern at: 2) , self temporaries]!
  39389. parseMethodComment: aString setPattern: aBlock
  39390.     "Answer the method comment for the argument, aString. Evaluate aBlock 
  39391.     with the message pattern in the form #(selector, arguments, precedence)."
  39392.  
  39393.     self
  39394.         initPattern: aString
  39395.         notifying: nil
  39396.         return: aBlock.
  39397.     currentComment==nil
  39398.         ifTrue:    [^OrderedCollection new]
  39399.         ifFalse:    [^currentComment]!
  39400. parseSelector: aString 
  39401.     "Answer the message selector for the argument, aString, which should 
  39402.     parse successfully up to the temporary declaration or the end of the 
  39403.     method header."
  39404.  
  39405.     ^self
  39406.         initPattern: aString
  39407.         notifying: nil
  39408.         return: [:pattern | pattern at: 1]! !
  39409.  
  39410. !Parser methodsFor: 'expression types'!
  39411. argumentName
  39412.  
  39413.     hereType == #word
  39414.         ifFalse: [^self expected: 'Argument name'].
  39415.     ^self advance!
  39416. assignment: varNode
  39417.     " var '_' expression => AssignmentNode."
  39418.  
  39419.     | loc |
  39420.     (loc _ varNode assignmentCheck: encoder at: prevMark + requestorOffset) >= 0
  39421.         ifTrue: [^self notify: 'Cannot store into' at: loc].
  39422.     self advance.
  39423.     self expression ifFalse: [^self expected: 'Expression'].
  39424.     parseNode _ AssignmentNode new
  39425.                 variable: varNode
  39426.                 value: parseNode
  39427.                 from: encoder.
  39428.     ^true!
  39429. blockExpression
  39430.     " [ {:var} ( | statements) ] => BlockNode."
  39431.  
  39432.     | argNodes |
  39433.     argNodes _ OrderedCollection new.
  39434.     [self match: #colon
  39435.     "gather any arguments"]
  39436.         whileTrue: 
  39437.             [argNodes addLast: (encoder autoBind: self argumentName)].
  39438.     (argNodes size > 0 & (hereType ~~ #rightBracket) and: [(self match: #verticalBar) not])
  39439.         ifTrue: [^self expected: 'Vertical bar'].
  39440.     self statements: argNodes innerBlock: true.
  39441.     (self match: #rightBracket)
  39442.         ifFalse: [^self expected: 'Period or right bracket']!
  39443. braceExpression
  39444.     " { elements } => BraceNode."
  39445.  
  39446.     | elements locations loc more |
  39447.     elements _ OrderedCollection new.
  39448.     locations _ OrderedCollection new.
  39449.     self advance.
  39450.     more _ hereType ~~ #rightBrace.
  39451.     [more]
  39452.         whileTrue: 
  39453.             [loc _ hereMark + requestorOffset.
  39454.             self expression
  39455.                 ifTrue: 
  39456.                     [elements addLast: parseNode.
  39457.                     locations addLast: loc]
  39458.                 ifFalse:
  39459.                     [^self expected: 'Variable or expression'].
  39460.             more _ self match: #period].
  39461.     parseNode _ BraceNode new elements: elements sourceLocations: locations.
  39462.     (self match: #rightBrace)
  39463.         ifFalse: [^self expected: 'Period or right brace'].
  39464.     ^true!
  39465. cascade
  39466.     " {; message} => CascadeNode."
  39467.  
  39468.     | rcvr msgs |
  39469.     parseNode canCascade
  39470.         ifFalse: [^self expected: 'Cascading not'].
  39471.     rcvr _ parseNode cascadeReceiver.
  39472.     msgs _ OrderedCollection with: parseNode.
  39473.     [self match: #semicolon]
  39474.         whileTrue: 
  39475.             [parseNode _ rcvr.
  39476.             (self messagePart: 3 repeat: false)
  39477.                 ifFalse: [^self expected: 'Cascade'].
  39478.             parseNode canCascade
  39479.                 ifFalse: [^self expected: '<- No special messages'].
  39480.             parseNode cascadeReceiver.
  39481.             msgs addLast: parseNode].
  39482.     parseNode _ CascadeNode new receiver: rcvr messages: msgs!
  39483. expression
  39484.  
  39485.     (hereType == #word and: [tokenType == #leftArrow])
  39486.         ifTrue: [^self assignment: self variable].
  39487.     hereType == #leftBrace
  39488.         ifTrue: [self braceExpression.
  39489.                 hereType == #leftArrow
  39490.                     ifTrue:
  39491.                         [^self assignment: parseNode]]
  39492.         ifFalse: [self primaryExpression
  39493.                     ifFalse: [^false]].
  39494.     (self messagePart: 3 repeat: true)
  39495.         ifTrue:
  39496.             [hereType == #semicolon ifTrue: [self cascade]].
  39497.     ^true!
  39498. messagePart: level repeat: repeat
  39499.  
  39500.     | start receiver selector args precedence words keywordStart |
  39501.     [receiver _ parseNode.
  39502.     (hereType == #keyword and: [level >= 3])
  39503.         ifTrue: 
  39504.             [start _ self startOfNextToken.
  39505.             selector _ WriteStream on: (String new: 32).
  39506.             args _ OrderedCollection new.
  39507.             words _ OrderedCollection new.
  39508.             [hereType == #keyword]
  39509.                 whileTrue: 
  39510.                     [keywordStart _ self startOfNextToken + requestorOffset.
  39511.                     selector nextPutAll: self advance.
  39512.                     words addLast: (keywordStart to: self endOfLastToken + requestorOffset).
  39513.                     self primaryExpression ifFalse: [^self expected: 'Argument'].
  39514.                     self messagePart: 2 repeat: true.
  39515.                     args addLast: parseNode].
  39516.             (Symbol hasInterned: selector contents ifTrue: [ :sym | selector _ sym])
  39517.                 ifFalse: [ selector _ self correctSelector: selector contents
  39518.                                         wordIntervals: words
  39519.                                         exprInterval: (start to: self endOfLastToken)
  39520.                                         ifAbort: [ ^ self fail ] ].
  39521.             precedence _ 3]
  39522.         ifFalse: [((hereType == #binary or: [hereType == #verticalBar])
  39523.                 and: [level >= 2])
  39524.                 ifTrue: 
  39525.                     [start _ self startOfNextToken.
  39526.                     selector _ self advance asSymbol.
  39527.                     self primaryExpression ifFalse: [^self expected: 'Argument'].
  39528.                     self messagePart: 1 repeat: true.
  39529.                     args _ Array with: parseNode.
  39530.                     precedence _ 2]
  39531.                 ifFalse: [hereType == #word
  39532.                         ifTrue: 
  39533.                             [start _ self startOfNextToken.
  39534.                             selector _ self advance.
  39535.                             args _ #().
  39536.                             words _ OrderedCollection with: (start  + requestorOffset to: self endOfLastToken + requestorOffset).
  39537.                             (Symbol hasInterned: selector ifTrue: [ :sym | selector _ sym])
  39538.                                 ifFalse: [ selector _ self correctSelector: selector
  39539.                                                     wordIntervals: words
  39540.                                                     exprInterval: (start to: self endOfLastToken)
  39541.                                                     ifAbort: [ ^ self fail ] ].
  39542.                             precedence _ 1]
  39543.                         ifFalse: [^args notNil]]].
  39544.     parseNode _ MessageNode new
  39545.                 receiver: receiver
  39546.                 selector: selector
  39547.                 arguments: args
  39548.                 precedence: precedence
  39549.                 from: encoder
  39550.                 sourceRange: (start to: self endOfLastToken).
  39551.     repeat]
  39552.         whileTrue: [].
  39553.     ^true!
  39554. method: doit context: ctxt 
  39555.     " pattern [ | temporaries ] block => MethodNode."
  39556.  
  39557.     | sap blk prim temps messageComment methodNode |
  39558.     sap _ self pattern: doit inContext: ctxt.
  39559.     "sap={selector, arguments, precedence}"
  39560.     (sap at: 2) do: [:argNode | argNode isArg: true].
  39561.     temps _ self temporaries.
  39562.     messageComment _ currentComment.
  39563.     currentComment _ nil.
  39564.     prim _ doit ifTrue: [0] ifFalse: [self primitive].
  39565.     self statements: #() innerBlock: doit.
  39566.     blk _ parseNode.
  39567.     doit 
  39568.         ifTrue: [blk returnLast]
  39569.         ifFalse: [blk returnSelfIfNoOther].
  39570.     hereType == #doIt ifFalse: [^self expected: 'Nothing more'].
  39571.     methodNode _ MethodNode new comment: messageComment.
  39572.     ^methodNode
  39573.         selector: (sap at: 1)
  39574.         arguments: (sap at: 2)
  39575.         precedence: (sap at: 3)
  39576.         temporaries: temps
  39577.         block: blk
  39578.         encoder: encoder
  39579.         primitive: prim!
  39580. pattern: fromDoit inContext: ctxt 
  39581.     " unarySelector | binarySelector arg | keyword arg {keyword arg} => 
  39582.     {selector, arguments, precedence}."
  39583.  
  39584.     | args selector |
  39585.     fromDoit 
  39586.         ifTrue: 
  39587.             [ctxt == nil
  39588.                 ifTrue: [^Array with: #DoIt with: #() with: 1]
  39589.                 ifFalse: [^Array 
  39590.                             with: #DoItIn: 
  39591.                             with: (Array 
  39592.                                     with: (encoder encodeVariable: 'homeContext')) 
  39593.                                     with: 3]].
  39594.     hereType == #word 
  39595.         ifTrue: [^Array with: self advance asSymbol with: #() with: 1].
  39596.     (hereType == #binary or: [hereType == #verticalBar])
  39597.         ifTrue: 
  39598.             [selector _ self advance asSymbol.
  39599.             args _ Array with: (encoder bindTemp: self argumentName).
  39600.             ^Array with: selector with: args with: 2].
  39601.     hereType == #keyword
  39602.         ifTrue: 
  39603.             [selector _ WriteStream on: (String new: 32).
  39604.             args _ OrderedCollection new.
  39605.             [hereType == #keyword]
  39606.                 whileTrue: 
  39607.                     [selector nextPutAll: self advance.
  39608.                     args addLast: (encoder bindTemp: self argumentName)].
  39609.             ^Array with: selector contents asSymbol with: args with: 3].
  39610.     ^self expected: 'Message pattern'!
  39611. primaryExpression
  39612.  
  39613.     hereType == #word
  39614.         ifTrue: 
  39615.             [parseNode _ self variable.
  39616.             ^true].
  39617.     hereType == #leftBracket
  39618.         ifTrue: 
  39619.             [self advance.
  39620.             self blockExpression.
  39621.             ^true].
  39622.     hereType == #leftBrace
  39623.         ifTrue: 
  39624.             [self braceExpression.
  39625.             ^true].
  39626.     hereType == #leftParenthesis
  39627.         ifTrue: 
  39628.             [self advance.
  39629.             self expression ifFalse: [^self expected: 'expression'].
  39630.             (self match: #rightParenthesis)
  39631.                 ifFalse: [^self expected: 'right parenthesis'].
  39632.             ^true].
  39633.     (hereType == #string or: [hereType == #number or: [hereType == #literal]])
  39634.         ifTrue: 
  39635.             [parseNode _ encoder encodeLiteral: self advance.
  39636.             ^true].
  39637.     (here == #- and: [tokenType == #number])
  39638.         ifTrue: 
  39639.             [self advance.
  39640.             parseNode _ encoder encodeLiteral: self advance negated.
  39641.             ^true].
  39642.     ^false!
  39643. statements: argNodes innerBlock: inner
  39644.  
  39645.     | stmts returns start more blockComment |
  39646.     stmts _ OrderedCollection new.
  39647.     "give initial comment to block, since others trail statements"
  39648.     blockComment _ currentComment.
  39649.     currentComment _ nil.
  39650.     returns _ false.
  39651.     more _ hereType ~~ #rightBracket.
  39652.     [more]
  39653.         whileTrue: 
  39654.         [start _ self startOfNextToken.
  39655.         (returns _ self match: #upArrow)
  39656.             ifTrue: 
  39657.                 [self expression
  39658.                     ifFalse: [^self expected: 'Expression to return'].
  39659.                 self addComment.
  39660.                 stmts addLast: (parseNode isReturningIf
  39661.                     ifTrue: [parseNode]
  39662.                     ifFalse: [ReturnNode new
  39663.                             expr: parseNode
  39664.                             encoder: encoder
  39665.                             sourceRange: (start to: self endOfLastToken)])]
  39666.             ifFalse: 
  39667.                 [self expression
  39668.                     ifTrue: 
  39669.                         [self addComment.
  39670.                         stmts addLast: parseNode]
  39671.                     ifFalse: 
  39672.                         [self addComment.
  39673.                         stmts size = 0
  39674.                             ifTrue: 
  39675.                                 [stmts addLast: 
  39676.                                     (encoder encodeVariable:
  39677.                                         (inner ifTrue: ['nil'] ifFalse: ['self']))]]].
  39678.         returns 
  39679.             ifTrue: 
  39680.                 [self match: #period.
  39681.                 (hereType == #rightBracket or: [hereType == #doIt])
  39682.                     ifFalse: [^self expected: 'End of block']].
  39683.         more _ returns not and: [self match: #period]].
  39684.     parseNode _ BlockNode new
  39685.                 arguments: argNodes
  39686.                 statements: stmts
  39687.                 returns: returns
  39688.                 from: encoder.
  39689.     parseNode comment: blockComment.
  39690.     ^ true!
  39691. temporaries
  39692.     " [ '|' (variable)* '|' ] "
  39693.     | vars |
  39694.     (self match: #verticalBar) ifFalse:    "no temps"
  39695.         [tempsMark _ hereMark.
  39696.         ^ #()].
  39697.     vars _ OrderedCollection new.
  39698.     [hereType == #word]
  39699.         whileTrue: [vars addLast: (encoder bindTemp: self advance)].
  39700.     (self match: #verticalBar) ifTrue:
  39701.         [tempsMark _ prevMark.
  39702.         ^ vars].
  39703.     ^self expected: 'Vertical bar'!
  39704. variable
  39705.  
  39706.     | varName varStart varEnd |
  39707.     varStart _ self startOfNextToken + requestorOffset.
  39708.     varName _ self advance.
  39709.     varEnd _ self endOfLastToken + requestorOffset.
  39710.     ^encoder encodeVariable: varName ifUnknown:
  39711.         [self correctVariable: varName interval: (varStart to: varEnd)]! !
  39712.  
  39713. !Parser methodsFor: 'scanning'!
  39714. advance
  39715.  
  39716.     | this |
  39717.     prevMark _ hereMark.
  39718.     prevToken _ "Now means prev size"
  39719.         hereType == #number
  39720.             ifTrue: [mark - prevMark]
  39721.             ifFalse: [here size].
  39722.     this _ here.
  39723.     here _ token.
  39724.     hereType _ tokenType.
  39725.     hereMark _ mark.
  39726.     self scanToken.
  39727.     ^this!
  39728. endOfLastToken
  39729.  
  39730.     "hereType == #doIt ifTrue: [^prevMark + prevToken + 1]."
  39731.     "tokenType == #doIt ifTrue: [^prevMark + prevToken]."
  39732.     ^prevMark + prevToken - 1!
  39733. match: type 
  39734.     "Answer with true if next tokens type matches."
  39735.  
  39736.     hereType == type
  39737.         ifTrue: 
  39738.             [self advance.
  39739.             ^true].
  39740.     ^false!
  39741. matchToken: thing 
  39742.     "Matches the token, not its type."
  39743.  
  39744.     here = thing ifTrue: [self advance. ^true].
  39745.     ^false!
  39746. startOfNextToken
  39747.     "Return starting position in source of next token."
  39748.  
  39749.     hereType == #doIt ifTrue: [^source position + 1].
  39750.     ^hereMark! !
  39751.  
  39752. !Parser methodsFor: 'temps'!
  39753. bindTemp: name
  39754.  
  39755.     ^name! !
  39756.  
  39757. !Parser methodsFor: 'error handling'!
  39758. expected: aString 
  39759.     "Notify a problem at token 'here'."
  39760.  
  39761.     tokenType == #doIt ifTrue: [hereMark _ hereMark + 1].
  39762.     hereType == #doIt ifTrue: [hereMark _ hereMark + 1].
  39763.     ^self notify: aString , ' expected' at: hereMark + requestorOffset!
  39764. fail
  39765.  
  39766.     | exitBlock |
  39767.     encoder == nil
  39768.         ifFalse: [encoder release. encoder _ nil]. "break cycle"
  39769.     exitBlock _ failBlock.
  39770.     failBlock _ nil.
  39771.     ^exitBlock value!
  39772. interactive
  39773.  
  39774.     ^ (requestor == nil or: [requestor isKindOf: SyntaxError]) not!
  39775. notify: aString 
  39776.     "Notify problem at token before 'here'."
  39777.  
  39778.     ^self notify: aString at: prevMark + requestorOffset!
  39779. notify: string at: location
  39780.     requestor isNil
  39781.         ifTrue: [SyntaxError 
  39782.                     errorInClass: encoder classEncoding
  39783.                     withCode: 
  39784.                         (source contents
  39785.                             copyReplaceFrom: location
  39786.                             to: location - 1
  39787.                             with: string , ' ->')]
  39788.         ifFalse: [requestor
  39789.                     notify: string , ' ->'
  39790.                     at: location
  39791.                     in: source].
  39792.     ^self fail
  39793. !
  39794. offEnd: aString 
  39795.     "Notify a problem beyond 'here' (in lookAhead token). Don't be offEnded!!"
  39796.  
  39797.     requestorOffset == nil
  39798.         ifTrue: [^self notify: aString at: 1]
  39799.         ifFalse: [^self notify: aString at: mark + requestorOffset]
  39800. ! !
  39801.  
  39802. !Parser methodsFor: 'error correction'!
  39803. breakIfLikely: proposedKeyword intoSel1Sel2Break: successBlock
  39804.     "If the selector has multiple keywords and there is a place to split where each half is a known selector, then evaluate the successBlock with the two selectors and the index of the keyword after which to split."
  39805.     | keys strm |
  39806.     keys _ proposedKeyword keywords.
  39807.     keys size < 2 ifTrue: [^ nil].
  39808.     "Try every possible split"
  39809.     strm _ WriteStream on: (String new: 30).
  39810.     1 to: keys size-1 do: [:index | 
  39811.         strm reset.
  39812.         1 to: index do: [:i | strm nextPutAll: (keys at: i)].
  39813.         Symbol hasInterned: strm contents ifTrue:
  39814.             [:sel1 | 
  39815.             strm reset.
  39816.             index+1 to: keys size do:
  39817.                 [:i | strm nextPutAll: (keys at: i)].
  39818.                 Symbol hasInterned: strm contents ifTrue:
  39819.                     [:sel2 |  "We have a winnah!!"
  39820.                     successBlock value: sel1 value: sel2 value: index]]].
  39821.     ^ nil  "just a new or misspelled selector"!
  39822. correctSelector: proposedKeyword wordIntervals: spots exprInterval: expInt ifAbort: abortAction
  39823.     ^ self correctSelector: proposedKeyword
  39824.             wordIntervals: spots
  39825.             exprInterval: expInt
  39826.             ifAbort: abortAction
  39827.             fullSearch: false!
  39828. correctSelector: proposedKeyword wordIntervals: spots exprInterval: expInt ifAbort: abortAction fullSearch: tryHard 
  39829.     "Correct the proposedKeyword to some selector symbol, correcting the original text if such action is indicated.  abortAction is invoked if the user the proposedKeyword couldn't be converted into a valid selector.  Spots is an ordered collection of intervals within the test stream of the for each of the keyword parts."
  39830.  
  39831.     | alternatives aStream choice correctSelector userSelection lines maybePeriod maybeDblKeyword firstLine i |
  39832.  
  39833.     "If we can't ask the user, assume that the keyword will be defined later"
  39834.     self interactive ifFalse: [ ^ proposedKeyword asSymbol ].
  39835.  
  39836.     userSelection _ requestor selectionInterval.
  39837.     requestor selectFrom: spots first first to: spots last last.
  39838.     requestor select.
  39839.  
  39840.     alternatives _ tryHard
  39841.         ifFalse: [ Symbol possibleSelectorsFor: proposedKeyword ]
  39842.         ifTrue: [ Symbol morePossibleSelectorsFor: proposedKeyword ].
  39843.  
  39844.     aStream _ WriteStream on: (String new: 200).
  39845.     aStream nextPutAll: (proposedKeyword contractTo: 35); cr.
  39846.      maybePeriod _ maybeDblKeyword _ false.
  39847.     firstLine _ 1.
  39848.     proposedKeyword numArgs = 0 ifTrue:
  39849.         ["Unary selector may be a variable after missing period."
  39850.          maybePeriod _ true.  firstLine _ 2.
  39851.         aStream nextPutAll: 'insert missing period'; cr]
  39852.         ifFalse:
  39853.         [self breakIfLikely: proposedKeyword intoSel1Sel2Break:
  39854.             [:sel1 :sel2 :break |
  39855.             maybeDblKeyword _ true.  firstLine _ 3.
  39856.             aStream nextPutAll: '(' , sel1 , ') ' , sel2; cr.
  39857.             aStream nextPutAll: sel1 , ' (' , sel2 , ')'; cr]].
  39858.      alternatives do:
  39859.         [:sel | aStream nextPutAll: (sel contractTo: 35); nextPut: Character cr].
  39860.     aStream nextPutAll: 'cancel'.
  39861.     lines _ Array with: firstLine with: (alternatives size + firstLine).
  39862.     tryHard ifFalse:
  39863.         [aStream cr; nextPutAll: 'try harder'.
  39864.         lines _ lines copyWith: (alternatives size + firstLine + 1)].
  39865.     
  39866.     choice _ (PopUpMenu labels: aStream contents lines: lines)
  39867.         startUpWithCaption: 
  39868. 'Unknown selector, please 
  39869. confirm, correct, or cancel'.
  39870.  
  39871.     (maybePeriod and: [choice = 2]) ifTrue:
  39872.         [i _ requestor nextTokenFrom: spots first first direction: -1.
  39873.         self substituteWord: '.' wordInterval: (i+1 to: i) offset: 0.
  39874.         ^ self restart].
  39875.     (maybeDblKeyword and: [choice between: 2 and: 3]) ifTrue:
  39876.         [choice = 2 ifTrue: 
  39877.             [i _ requestor nextTokenFrom: (spots at: break+1) first direction: -1.
  39878.             self substituteSelector: #( '(' ')' )
  39879.                 wordIntervals: (Array with: (expInt first-2 to: expInt first-3)
  39880.                                 with: (i+1 to: i))]
  39881.             ifFalse:
  39882.             [i _ requestor nextTokenFrom: (spots at: break) last direction: 1.
  39883.             self substituteSelector: #( '(' ')' )
  39884.                 wordIntervals: (Array with: (i to: i-1)
  39885.                                 with: (expInt last+1 to: expInt last))].
  39886.         ^ self restart].
  39887.     tryHard not & (choice > lines last) ifTrue:
  39888.         [^ self correctSelector: proposedKeyword wordIntervals: spots
  39889.                 exprInterval: expInt ifAbort: abortAction fullSearch: true ]. 
  39890.  
  39891.     (choice = 0) | (choice > (lines at: 2))
  39892.         ifTrue: [ ^ abortAction value ].
  39893.  
  39894.     requestor deselect.
  39895.     requestor selectInvisiblyFrom: userSelection first to: userSelection last.
  39896.  
  39897.     (choice = 1)
  39898.         ifTrue: [ ^ proposedKeyword asSymbol ].
  39899.  
  39900.     correctSelector _ alternatives at: 
  39901.         (maybeDblKeyword
  39902.             ifTrue: [choice - 3]
  39903.             ifFalse: [maybePeriod
  39904.                     ifTrue: [choice - 2]
  39905.                     ifFalse: [choice - 1]]).
  39906.     self substituteSelector: correctSelector keywords wordIntervals: spots.
  39907.     ^ correctSelector.
  39908. !
  39909. correctVariable: proposedVariable interval: spot
  39910.     "Correct the proposedVariable to a known variable, or declare it as a new
  39911.     variable if such action is requested.  We support declaring lowercase
  39912.     variables as temps, and uppercase variables as Globals or ClassVars,
  39913.     depending on whether the context is nil (class=UndefinedObject).
  39914.     Spot is the interval within the test stream of the variable."
  39915.  
  39916.     | alternatives aStream choice userSelection temp binding globalToo |
  39917.     "If we can't ask the user for correction, make it undeclared"
  39918.     self interactive ifFalse: [ ^ encoder undeclared: proposedVariable ].
  39919.  
  39920.     temp _ proposedVariable first isLowercase.
  39921.     "First check to see if the requestor knows anything about the variable"
  39922.     (temp and: [(binding _ requestor bindingOf: proposedVariable) notNil])
  39923.         ifTrue: [^encoder global: binding name: proposedVariable].
  39924.     userSelection _ requestor selectionInterval.
  39925.     requestor selectFrom: spot first to: spot last.
  39926.     requestor select.
  39927.  
  39928.     alternatives _ encoder possibleVariablesFor: proposedVariable.
  39929.  
  39930.     aStream _ WriteStream on: (String new: 200).
  39931.     globalToo _ 0.
  39932.     aStream nextPutAll: 'declare ' ,
  39933.         (temp ifTrue: ['temp']
  39934.             ifFalse: [encoder classEncoding == UndefinedObject
  39935.                     ifTrue: ['Global']
  39936.                     ifFalse: [globalToo _ 1.  'Class Variable']]); cr.
  39937.     globalToo = 1 ifTrue: [aStream nextPutAll: 'Global'; cr].
  39938.     alternatives do:
  39939.         [:sel | aStream nextPutAll: sel; cr].
  39940.     aStream nextPutAll: 'cancel'.
  39941.  
  39942.     choice _ (PopUpMenu
  39943.                 labels: aStream contents
  39944.                 lines: (Array with: 1 with: alternatives size+1) )
  39945.         startUpWithCaption:
  39946. (('Unknown variable: ' , proposedVariable , '
  39947. please correct, or cancel:') asText makeBoldFrom: 19 to: 19+proposedVariable size).
  39948.     (choice = 0) | (choice > (alternatives size+1))
  39949.         ifTrue: [ ^ self fail ].
  39950.  
  39951.     requestor deselect.
  39952.     requestor selectInvisiblyFrom: userSelection first to: userSelection last.
  39953.     choice =1 ifTrue:
  39954.             [temp ifTrue: [^ self declareTempAndPaste: proposedVariable]
  39955.                 ifFalse: [encoder classEncoding == UndefinedObject
  39956.                     ifTrue: [^ self declareGlobal: proposedVariable]
  39957.                     ifFalse: [^ self declareClassVar: proposedVariable]]].
  39958.     (choice = 2) & (globalToo = 1) ifTrue: [^ self declareGlobal: proposedVariable].
  39959.     "Spelling correction"
  39960.     self substituteWord: (alternatives at: choice-1-globalToo)
  39961.             wordInterval: spot
  39962.             offset: 0.
  39963.     ^ encoder encodeVariable: (alternatives at: choice-1-globalToo)!
  39964. declareClassVar: name
  39965.     | sym class |
  39966.     sym _ name asSymbol.
  39967.     class _ encoder classEncoding.
  39968.     class _ class theNonMetaClass.        "not the metaclass"
  39969.     class addClassVarName: name.
  39970.     ^ encoder global: (class classPool associationAt: sym)
  39971.             name: sym!
  39972. declareGlobal: name
  39973.     | sym |
  39974.     sym _ name asSymbol.
  39975.     Smalltalk at: sym put: nil.
  39976.     ^ encoder global: (Smalltalk associationAt: sym) name: sym!
  39977. declareTempAndPaste: name
  39978.     | insertion tabbed |
  39979.     (requestor text string at: tempsMark) = $|
  39980.                 ifTrue:  "Paste it before the second vertical bar"
  39981.                     [tempsMark _ tempsMark +
  39982.                         (self substituteWord: name , ' '
  39983.                             wordInterval: (tempsMark to: tempsMark-1)
  39984.                             offset: 0)]
  39985.                 ifFalse:  "No bars - insert some with CR, tab"
  39986.                     [insertion _ '| ' , name , ' |
  39987. '.
  39988.                     tabbed _ tempsMark > 1
  39989.                         and: [(requestor text string at: tempsMark-1) = Character tab].
  39990.                     tabbed
  39991.                         ifTrue: [insertion _ insertion , (String with: Character tab)].
  39992.                     tempsMark _ tempsMark +
  39993.                         (self substituteWord: insertion
  39994.                             wordInterval: (tempsMark to: tempsMark-1)
  39995.                             offset: 0)
  39996.                         - (tabbed ifTrue: [3] ifFalse: [2])].
  39997.             ^ encoder reallyBind: name!
  39998. placeToBreak: proposedKeyword
  39999.     "If the selector has multiple keywords and there is a place to split where each half is a known selector, then return the index of the keyword after which to break, else zero."
  40000.     | keys strm |
  40001.     keys _ proposedKeyword keywords.
  40002.     keys size < 2 ifTrue: [^ 0].
  40003.     "Try every possible split"
  40004.     strm _ WriteStream on: (String new: 30).
  40005.     1 to: keys size-1 do: [:index | 
  40006.         strm reset.
  40007.         1 to: index do: [:one | strm nextPutAll: (keys at: one)].
  40008.         Symbol hasInterned: strm contents ifTrue:
  40009.             [:aSymbol | 
  40010.             strm reset.
  40011.             index+1 to: keys size do:
  40012.                 [:one | strm nextPutAll: (keys at: one)].
  40013.                 Symbol hasInterned: strm contents ifTrue:
  40014.                     [:another | ^ index "We have a winnah!!"]]].
  40015.     ^ 0  "just a new or misspelled selector"!
  40016. restart
  40017.     "This SHOULD restart compilation, but since the parser
  40018.     doesnt have access to the corrected text, we have to ask 
  40019.     the user to restart.  Sigh."
  40020.     PopUpMenu notify: 'I was able to make the correction,
  40021. but I need you to re-accept -- thanks'.
  40022.     self fail!
  40023. substituteSelector: selectorParts wordIntervals: spots
  40024.     "Substitute the correctSelector into the (presuamed interactive) receiver."
  40025.     | offset |
  40026.     offset _ 0.
  40027.     selectorParts with: spots do:
  40028.         [ :word :interval |
  40029.         offset _ self substituteWord: word wordInterval: interval offset: offset ]
  40030. !
  40031. substituteWord: correctWord wordInterval: spot offset: o
  40032.     "Substitute the correctSelector into the (presuamed interactive) receiver."
  40033.  
  40034.     requestor correctFrom: (spot first + o)
  40035.                     to: (spot last + o)
  40036.                     with: correctWord.
  40037.  
  40038.     requestorOffset _ requestorOffset + correctWord size - spot size.
  40039.     ^ o + correctWord size - spot size! !
  40040.  
  40041. !Parser methodsFor: 'private'!
  40042. addComment
  40043.  
  40044.     parseNode ~~ nil
  40045.         ifTrue: 
  40046.             [parseNode comment: currentComment.
  40047.             currentComment _ nil]!
  40048. init: sourceStream notifying: req failBlock: aBlock
  40049.  
  40050.     requestor _ req.
  40051.     failBlock _ aBlock.
  40052.     super scan: sourceStream.
  40053.     prevMark _ hereMark _ mark.
  40054.     requestorOffset _ 0.
  40055.     self advance!
  40056. initPattern: aString notifying: req return: aBlock
  40057.  
  40058.     | result |
  40059.     self
  40060.         init: (ReadStream on: aString asString)
  40061.         notifying: req
  40062.         failBlock: [^nil].
  40063.     encoder _ self.
  40064.     result _ aBlock value: (self pattern: false inContext: nil).
  40065.     encoder _ failBlock _ nil.  "break cycles"
  40066.     ^result! !
  40067.  
  40068. !Parser methodsFor: 'primitives'!
  40069. allocateLiteral: lit
  40070.     encoder litIndex: lit!
  40071. primitive
  40072.     | n |
  40073.     (self matchToken: #<) ifFalse: [^ 0].
  40074.     n _ self primitiveDeclarations.
  40075.     (self matchToken: #>) ifFalse: [^ self expected: '>'].
  40076.     ^ n!
  40077. primitiveDeclarations
  40078.     | prim |
  40079.     (self matchToken: 'primitive:') ifTrue:
  40080.         [prim _ here.
  40081.         (self match: #number) ifFalse: [^self expected: 'Integer']].
  40082.     ^ prim! !Object subclass: #ParseStack
  40083.     instanceVariableNames: 'position length '
  40084.     classVariableNames: ''
  40085.     poolDictionaries: ''
  40086.     category: 'System-Compiler'!
  40087. ParseStack comment:
  40088. 'I keep track of the current and high position of the stack that will be needed by code being compiled.'!
  40089.  
  40090. !ParseStack methodsFor: 'initialize-release'!
  40091. init
  40092.  
  40093.     length _ position _ 0! !
  40094.  
  40095. !ParseStack methodsFor: 'accessing'!
  40096. pop: n
  40097.  
  40098.     (position _ position - n) < 0 
  40099.         ifTrue: [self error: 'Parse stack underflow']!
  40100. push: n
  40101.  
  40102.     (position _ position + n) > length 
  40103.         ifTrue: [length _ position]!
  40104. size
  40105.  
  40106.     ^length! !
  40107.  
  40108. !ParseStack methodsFor: 'results'!
  40109. position
  40110.  
  40111.     ^position! !
  40112.  
  40113. !ParseStack methodsFor: 'printing'!
  40114. printOn: aStream
  40115.     
  40116.     super printOn: aStream.
  40117.     aStream nextPutAll: ' at '; print: position; nextPutAll: ' of '; print: length! !DisplayObject subclass: #Path
  40118.     instanceVariableNames: 'form collectionOfPoints '
  40119.     classVariableNames: ''
  40120.     poolDictionaries: ''
  40121.     category: 'Graphics-Display Objects'!
  40122. Path comment:
  40123. 'I am the abstract superclass of the Graphic spatial primitives. I represent an ordered sequence of Points. Spatial primitives are used to generate "trajectories" such as lines and circles.'!
  40124.  
  40125. !Path methodsFor: 'accessing'!
  40126. at: index 
  40127.     "Answer the point on the receiver's path at position index."
  40128.  
  40129.     ^collectionOfPoints at: index!
  40130. at: index put: aPoint 
  40131.     "Store the argument, aPoint, as the point on the receiver's path at position
  40132.     index."
  40133.  
  40134.     ^collectionOfPoints at: index put: aPoint!
  40135. atPin: index 
  40136.     "Answer the point on the receiver's path at position index."
  40137.  
  40138.     ^collectionOfPoints atPin: index!
  40139. atWrap: index 
  40140.     "Answer the point on the receiver's path at position index."
  40141.  
  40142.     ^collectionOfPoints atWrap: index!
  40143. first
  40144.     "Answer the first point on the receiver's path; included to correspond to 
  40145.     OrderedCollection protocol."
  40146.  
  40147.     ^collectionOfPoints first!
  40148. firstPoint
  40149.     "Answer the first point on the receiver's path."
  40150.  
  40151.     ^collectionOfPoints first!
  40152. firstPoint: aPoint 
  40153.     "Replace the first element of the receiver with the new value aPoint. 
  40154.     Answer the argument aPoint."
  40155.  
  40156.     collectionOfPoints at: 1 put: aPoint.
  40157.     ^aPoint!
  40158. form
  40159.     "Answer the receiver's form, or, if form is nil, then answer a 1 x 1 black 
  40160.     form (a black dot)."
  40161.  
  40162.     | aForm |
  40163.     form == nil
  40164.         ifTrue: 
  40165.             [aForm _ Form extent: 1 @ 1.
  40166.             aForm fillBlack.
  40167.             ^aForm]
  40168.         ifFalse: 
  40169.             [^form]!
  40170. form: aForm 
  40171.     "Make the argument, aForm, be the receiver's form."
  40172.  
  40173.     form _ aForm!
  40174. last
  40175.     "Answer the last point on the receiver's path; included to correspond to 
  40176.     OrderedCollection protocol."
  40177.  
  40178.     ^collectionOfPoints last!
  40179. offset
  40180.     "There are basically two kinds of display objects in the system: those
  40181.     that, when asked to transform themselves, create a new object; and those
  40182.     that side effect themselves by maintaining a record of the transformation
  40183.     request (typically an offset). Path, like Rectangle and Point, is a display
  40184.     object of the first kind."
  40185.  
  40186.     self shouldNotImplement!
  40187. secondPoint
  40188.     "Answer the second element of the receiver."
  40189.  
  40190.     ^collectionOfPoints at: 2!
  40191. secondPoint: aPoint 
  40192.     "Replace the second element of the receiver with the new value aPoint. 
  40193.     Answer the argument aPoint."
  40194.  
  40195.     collectionOfPoints at: 2 put: aPoint.
  40196.     ^aPoint!
  40197. size
  40198.     "Answer the length of the receiver."
  40199.  
  40200.     ^collectionOfPoints size!
  40201. thirdPoint
  40202.     "Answer the third element of the receiver."
  40203.  
  40204.     ^collectionOfPoints at: 3!
  40205. thirdPoint: aPoint 
  40206.     "Replace the third element of the receiver with the new value aPoint. 
  40207.     Answer the argument aPoint."
  40208.  
  40209.     collectionOfPoints at: 3 put: aPoint.
  40210.     ^aPoint! !
  40211.  
  40212. !Path methodsFor: 'testing'!
  40213. isEmpty
  40214.  
  40215.     ^collectionOfPoints isEmpty! !
  40216.  
  40217. !Path methodsFor: 'displaying'!
  40218. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm 
  40219.     "Display this Path--offset by aPoint, clipped by clipRect and the form 
  40220.     associated with this Path will be displayedr according to one of the sixteen 
  40221.     functions of two logical variables (rule). Also the source form will be first 
  40222.     anded with aForm as a mask. Does not effect the state of the Path"
  40223.  
  40224.     collectionOfPoints do: 
  40225.         [:element | 
  40226.         self form
  40227.             displayOn: aDisplayMedium
  40228.             at: element + aDisplayPoint
  40229.             clippingBox: clipRectangle
  40230.             rule: ruleInteger
  40231.             fillColor: aForm]!
  40232. displayOn: aDisplayMedium transformation: displayTransformation clippingBox: clipRectangle rule: ruleInteger fillColor: aForm 
  40233.     "Displays this path, translated and scaled by aTransformation. Get the
  40234.     scaled and translated Path."
  40235.  
  40236.     | newPath transformedPath |
  40237.     transformedPath _ displayTransformation applyTo: self.
  40238.     newPath _ Path new.
  40239.     transformedPath do: [:point | newPath add: point].
  40240.     newPath form: self form.
  40241.     newPath
  40242.         displayOn: aDisplayMedium
  40243.         at: 0 @ 0
  40244.         clippingBox: clipRectangle
  40245.         rule: ruleInteger
  40246.         fillColor: aForm! !
  40247.  
  40248. !Path methodsFor: 'display box access'!
  40249. computeBoundingBox 
  40250.     "Refer to the comment in DisplayObject|computeBoundingBox."
  40251.  
  40252.     | box |
  40253.     box _ Rectangle origin: (self at: 1) extent: 0 @ 0.
  40254.     collectionOfPoints do: 
  40255.         [:aPoint | box _ box merge: (Rectangle origin: aPoint extent: 0 @ 0)].
  40256.     ^box! !
  40257.  
  40258. !Path methodsFor: 'transforming'!
  40259. scaleBy: aPoint 
  40260.     "Answers a new Path scaled by aPoint. Does not affect the current data in 
  40261.     this Path."
  40262.  
  40263.     | newPath |
  40264.     newPath _ Path new: self size.
  40265.     newPath form: self form.
  40266.     collectionOfPoints do: 
  40267.         [:element | 
  40268.         newPath add: 
  40269.                 (aPoint x * element x) asInteger @ (aPoint y * element y) asInteger].
  40270.     ^newPath!
  40271. translateBy: aPoint 
  40272.     "Answers a new Path whose elements are translated by aPoint. Does not
  40273.     affect the elements of this Path."
  40274.  
  40275.     | newPath |
  40276.     newPath _ Path new: self size.
  40277.     newPath form: self form.
  40278.     collectionOfPoints do: 
  40279.         [:element | 
  40280.         newPath add: 
  40281.             (element x + aPoint x) asInteger @ (element y + aPoint y) asInteger].
  40282.     ^newPath! !
  40283.  
  40284. !Path methodsFor: 'adding'!
  40285. add: aPoint 
  40286.     "Include aPoint as one of the receiver's elements."
  40287.  
  40288.     collectionOfPoints add: aPoint! !
  40289.  
  40290. !Path methodsFor: 'removing'!
  40291. removeAllSuchThat: aBlock 
  40292.     "Evaluate aBlock for each element of the receiver. Remove each element 
  40293.     for which aBlock evaluates to true."
  40294.  
  40295.     | newCollection |
  40296.     newCollection _ collectionOfPoints removeAllSuchThat: aBlock.
  40297.     newCollection form: self form.
  40298.     ^newCollection! !
  40299.  
  40300. !Path methodsFor: 'enumerating'!
  40301. collect: aBlock 
  40302.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  40303.     Collect the resulting values into a path that is like the receiver. Answer 
  40304.     the new path."
  40305.  
  40306.     | newCollection |
  40307.     newCollection _ collectionOfPoints collect: aBlock.
  40308.     newCollection form: self form.
  40309.     ^newCollection!
  40310. select: aBlock 
  40311.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  40312.     Collect into a new path like the receiver only those elements for which 
  40313.     aBlock evaluates to true. Answer the new path."
  40314.  
  40315.     | newCollection |
  40316.     newCollection _ collectionOfPoints select: aBlock.
  40317.     newCollection form: self form.
  40318.     ^newCollection! !
  40319.  
  40320. !Path methodsFor: 'private'!
  40321. initializeCollectionOfPoints
  40322.  
  40323.     collectionOfPoints _ OrderedCollection new!
  40324. initializeCollectionOfPoints: anInteger
  40325.  
  40326.     collectionOfPoints _ OrderedCollection new: anInteger! !
  40327. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  40328.  
  40329. Path class
  40330.     instanceVariableNames: ''!
  40331.  
  40332. !Path class methodsFor: 'instance creation'!
  40333. new
  40334.  
  40335.     ^self basicNew initializeCollectionOfPoints!
  40336. new: anInteger
  40337.  
  40338.     ^self basicNew initializeCollectionOfPoints: anInteger! !
  40339.  
  40340. !Path class methodsFor: 'examples'!
  40341. example
  40342.     "Creates a Path from mousePoints and displays it several ways on the display screen. Messes up the display. For learning about class Path, just select the code below and execute it to create a path and see it redisplayed in another place on the screen. Each path displays using a different form. A path is indicated by pressing the red mouse button in a sequence; press any other mouse button to terminate. "
  40343.  
  40344.     | aPath aForm pl fl flag |
  40345.     aForm _ Form extent: 2 @ 40.        "creates a form one inch long"
  40346.     aForm fillBlack.                            "turns it black"
  40347.     aPath _ Path new.
  40348.     aPath form: aForm.                        "use the long black form for displaying"
  40349.     flag _ true.
  40350.     [flag]
  40351.         whileTrue: 
  40352.             [Sensor waitButton.
  40353.             Sensor redButtonPressed
  40354.                 ifTrue: 
  40355.                     [aPath add: Sensor waitButton.
  40356.                     Sensor waitNoButton.
  40357.                     aForm displayOn: Display at: aPath last]
  40358.                 ifFalse: [flag _ false]].
  40359.     Display fillWhite.
  40360.     aPath displayOn: Display.            "the original path"
  40361.     pl _ aPath translateBy: 0 @ 100.
  40362.     fl _ Form extent: 40 @ 40.
  40363.     fl fillGray.
  40364.     pl form: fl.
  40365.     pl displayOn: Display.                "the translated path"
  40366.     Sensor waitNoButton
  40367.  
  40368.     "Path example"! !Form subclass: #Pattern
  40369.     instanceVariableNames: 'colorArray2D '
  40370.     classVariableNames: ''
  40371.     poolDictionaries: ''
  40372.     category: 'Graphics-Display Objects'!
  40373. Pattern comment:
  40374. 'A pattern is a halftone of Colors.  It is a 2-D array of Colors that is used to get an in-between color by dithering.  An Array2D holds a tile of colors that is repeated over and over when filling a Form.  Just store one repeat of the tile.  A Patterns is used instead of a single Color as the fillColor parameter of BitBlt for filling forms.  A Pattern is used either for texture or when no single color looks like the color you want in a low-depth Form.  (See InfiniteForm for larger textures.)
  40375.     Normally a pattern is 2x2 or 4x4 colors.
  40376.     A Pattern is essentially immutable.  Once you set the array of Colors, you should not change them.  Instead, create a new Pattern and use it.
  40377.     Ignore the fact that Pattern is a subclass of Form.  (width, height, and bits are used internally to cache the encoded pattern for BitBlt.  Don''t use them like you would in a Form.) 
  40378.     pattern        an Array2D of Colors to be used as a dither.
  40379.     depth        a cache for the depth this pattern was last displayed at.
  40380.  
  40381. Messages:
  40382.     setExtent: x@y colors: anArray        Set up a pattern using data in a 1-D array.
  40383.     colorArray    returns an Array2D of colors.
  40384.     depth: d        recompute the raw bits based on the depth of the destination Form we are about to fill.  BitBlt will automatically send this just before using a pattern.
  40385.     
  40386.     (When a Pattern is displayed, there are restrictions:  The number of colors across in X, times the depth must be 32 or less.  You can display a 4x4 pattern of colors at 8 bits deep.  You can display a 32x32 pattern at 1 bit deep.  For 32 bits deep, you should use a single color instead.  You can store fewer colors than the max allowed in X, such as a 2x2 pattern at 8 bits deep.  If you store more colors than is allowed at the display depth, pattern pixels on the right hand side will not show up.)
  40387.  
  40388. Further details you don''t need to know:
  40389.     The raw halftone supplied to BitBlt is basically an array of 32-bit values.  BitBlt aligns the first element of this array with the top scanline of the destinationForm, the second with the second, and so on, cycling through the color array as necessary.  Within each scan line the 32-bit value is repeated from left to right across the form.  The value will produce a halftone that repeats on N-pixel boundaries, N = 32 // depth.'!
  40390.  
  40391. !Pattern methodsFor: 'access'!
  40392. asColor
  40393.     "Treat the whole pattern as its average color.  The result loses information.  6/20/96 tk"
  40394.  
  40395.     ^ Color r: self red g: self green b: self blue!
  40396. asInfiniteForm
  40397.     "Convert me into a normal Form, but one that knows to repeat when used as a source.  Call after sending depth: d.  Lose information about the true abstract Colors I have, and only keep information for the current depth.  6/20/96 tk"
  40398.  
  40399.     depth == nil ifTrue: [^ self error: 'Must specify a depth'].
  40400.     ^ InfiniteForm with: (self as: Form)!
  40401. blue
  40402.     "Find the average blue of this pattern.  6/20/96 tk"
  40403.  
  40404.     | sum |
  40405.     sum _ 0.
  40406.     colorArray2D do: [:each | sum _ sum + each blue].
  40407.     ^ sum / (colorArray2D width * colorArray2D height)!
  40408. colorArray
  40409.     "returns my Array2D of colors.  6/20/96 tk"
  40410.  
  40411.     ^ colorArray2D!
  40412. green
  40413.     "Find the average green of this pattern.  6/20/96 tk"
  40414.  
  40415.     | sum |
  40416.     sum _ 0.
  40417.     colorArray2D do: [:each | sum _ sum + each green].
  40418.     ^ sum / (colorArray2D width * colorArray2D height)!
  40419. originate: aPoint on: destForm
  40420.     "Answer a new Color whose bits have been wrapped around
  40421.     so that, if they represent a stipple, it will appear at aPoint the
  40422.     same as THIS color appears at 0@0.  6/24/96 tk"
  40423.  
  40424.     | newArray |
  40425.     newArray _ Array2D new extent: colorArray2D extent.
  40426.     1 to: newArray width do: [:i |
  40427.         1 to: newArray height do: [:j |
  40428.             newArray at: (i-1 + aPoint x \\ self width + 1) 
  40429.                 at: (j-1 + aPoint y \\ self height + 1) 
  40430.                 put: (colorArray2D at: i at: j)]].
  40431.     ^ self class array2D: newArray
  40432.  
  40433. "    1 to: self size do:
  40434.         [:i | newColor at: i-1 + aPoint y \\ self size + 1
  40435.                     put: (self originateWord: (self at: i)
  40436.                                 to: aPoint x on: destForm)].
  40437. "
  40438. !
  40439. patHeight
  40440.     "The number of colors in Y in the array.  6/20/96 tk"
  40441.  
  40442.     ^ colorArray2D height!
  40443. patWidth
  40444.     "The number of colors in X.  Differs from the 'width', which is what the bit cache is using.  6/20/96 tk"
  40445.  
  40446.     ^ colorArray2D width!
  40447. red
  40448.     "Find the average red of this pattern.  6/20/96 tk"
  40449.  
  40450.     | sum |
  40451.     sum _ 0.
  40452.     colorArray2D do: [:each | sum _ sum + each red].
  40453.     ^ sum / (colorArray2D width * colorArray2D height)! !
  40454.  
  40455. !Pattern methodsFor: 'cached bits'!
  40456. bitPatternForDepth: newDepth
  40457.     "The raw call on BitBlt needs a Bitmap to represent this pattern of colors.  I already am Bitmap like.  See if my cached bits are at the right depth already.  If not, recompute.  Interpret me as an array of (32/depth) Color pixelValues.  BitBlt aligns the first element of this array with the top scanline of the destinationForm, the second with the second, and so on, cycling through the color array as necessary.  See BitBlt class comment.  6/20/96 tk"
  40458.  
  40459.     newDepth = depth ifTrue: [^ self].    "cache is good"
  40460.     self depth: newDepth.
  40461.     ^ self!
  40462. cacheBits
  40463.     "Actual bits must be recomputed and cached for the display depth.  Width, that is (extent x), is limited to 32/depth.  If shown at a depth that is too wide, right hand side colors will not show.
  40464.     If you reach in and change a color in colorArray2D, then call this to update the pattern.  6/20/96 tk"
  40465.  
  40466. | word row |
  40467. depth == nil ifTrue: [self error: 'for what depth?'].
  40468. width _ 32//depth.
  40469. height _ colorArray2D height.
  40470. bits _ Bitmap new: height.    "always 32 bits across"
  40471.  
  40472. 1 to: height do: [:j |
  40473.     word _ 0.
  40474.     row _ colorArray2D atRow: j.
  40475.     1 to: 32//depth do: [:pix | 
  40476.         word _ (word bitShift: depth) bitOr: 
  40477.             ((row atWrap: pix) pixelValueForDepth: depth)].
  40478.     bits at: j put: word].!
  40479. depth: d
  40480.     "Set the depth at which this Pattern of Colors will be rendered.  The results are cached in depth, width, height, and bits.  6/20/96 tk"
  40481.  
  40482.     d = depth ifTrue: [^ self].    "trust the cache"
  40483.     super depth: d.
  40484.     self cacheBits.    "Computer the rendering Bitmap"! !
  40485.  
  40486. !Pattern methodsFor: 'private'!
  40487. setArray2D: anArray2D
  40488.     "A grid of Colors that can be used to fill a Form.  Actual bits are recomputed for the display depth (and cached).  Width is limited to (32/depth).  If shown at a depth that is too wide, right hand side colors will not show.  6/20/96 tk"
  40489.  
  40490.     colorArray2D == nil ifFalse: [
  40491.         ^ self error: 'Can''t change a Pattern.  Please make a new one'].
  40492.     "anArray2D width > 32 ifTrue: [
  40493.         self error: 'Too wide. Some colors won''t show']."
  40494.         "OK to use as a route from a big Array of Colors to a Form?" 
  40495.     colorArray2D _ anArray2D.
  40496.     depth == nil ifFalse: [self cacheBits].!
  40497. setExtent: extent colors: anArray
  40498.     "A grid of Colors that can be used to fill a Form.  Initialized from an Array of Colors (x across first row, then second row).  Actual bits are recomputed for the display depth (and cached).  Width, that is (extent x), is limited to 32/depth.  If shown at a depth that is too wide, right hand side colors will not show.  6/20/96 tk"
  40499.  
  40500.     colorArray2D == nil ifFalse: [
  40501.         ^ self error: 'Can''t change a Pattern.  Please make a new one'].
  40502.     "extent x > 32 ifTrue: [
  40503.         self error: 'Too wide. Some colors won''t show']."
  40504.         "Use as a route from a big array of Colors to a Form?" 
  40505.     colorArray2D _ Array2D new extent: extent fromArray: anArray.
  40506.     depth == nil ifFalse: [self cacheBits].! !
  40507. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  40508.  
  40509. Pattern class
  40510.     instanceVariableNames: ''!
  40511.  
  40512. !Pattern class methodsFor: 'as yet unclassified'!
  40513. array2D: anArray2D
  40514.     "Create a new pattern.  A grid of Colors that can be used to fill a Form.  Actual bits recomputed for the display depth (and cached).  Width, that is (extent x), is limited to 32/depth.  If shown at a depth that is too wide, right hand side colors will not show.  6/20/96 tk"
  40515.  
  40516.     ^ self new setArray2D: anArray2D!
  40517. extent: extent colors: anArray
  40518.     "A grid of Colors that can be used to fill a Form.  Initialized from an Array of Colors (x across first row, then second row).  Actual bits are recomputed for the display depth (and cached).  Width, that is (extent x), is limited to 32/depth.  If shown at a depth that is too wide, right hand side colors will not show.  6/20/96 tk"
  40519.  
  40520.     ^ self new setExtent: extent colors: anArray
  40521.  
  40522. "
  40523. ((Form extent: 50@50 depth: 8) fillColor:
  40524. (Pattern extent: 2@2 colors: (Array
  40525.     with: Color green with: Color white
  40526.     with: Color white with: Color green))) display
  40527. "! !BitBlt subclass: #Pen
  40528.     instanceVariableNames: 'frame location direction penDown '
  40529.     classVariableNames: 'Colors '
  40530.     poolDictionaries: ''
  40531.     category: 'Graphics-Primitives'!
  40532. Pen comment:
  40533. 'My instances can scribble on the screen, drawing and printing at any angle. Since I am a BitBlt, scribbling can be done with different source forms.'!
  40534.  
  40535. !Pen methodsFor: 'initialize-release'!
  40536. defaultNib: widthInteger 
  40537.     "Nib is the tip of a pen. This sets up the pen, with a nib of width
  40538.     widthInteger. Alternatively, try
  40539.         roundNib: widthInteger, or
  40540.         sourceForm: aForm
  40541.     to set the shape of the tip. For example, try:
  40542.         | bic | bic _ Pen new sourceForm: Cursor normal.
  40543.         bic combinationRule: Form paint; turn: 90.
  40544.         10 timesRepeat: [bic down; go: 10; up; go: 20].
  40545. "
  40546.     self color: destForm black.
  40547.     self squareNib: widthInteger!
  40548. roundNib: widthInteger 
  40549.     "Nib is the tip of a pen. This sets up the pen, with the source form
  40550.      set to a round dot of diameter widthInteger."
  40551.  
  40552.     self sourceForm: (Form dotOfSize: widthInteger).
  40553.     combinationRule _ Form paint!
  40554. squareNib: widthInteger 
  40555.     "Sets this pen to draw with a square tip of width widthInteger."
  40556.  
  40557.     self sourceForm: (Form extent: widthInteger @widthInteger) fillBlack.
  40558.     self combinationRule: Form over.  "A bit faster than paint mode"! !
  40559.  
  40560. !Pen methodsFor: 'accessing'!
  40561. direction
  40562.     "Answer the receiver's current direction. 0 is towards the top of the
  40563.     screen."
  40564.  
  40565.     ^direction!
  40566. location
  40567.     "Answer where the receiver is currently located."
  40568.  
  40569.     ^location! !
  40570.  
  40571. !Pen methodsFor: 'coloring'!
  40572. black
  40573.     "Set the receiver's mask to the black form."
  40574.  
  40575.     self fillColor: destForm black!
  40576. color: colorSpec
  40577.     "Set the pen to the Nth color (wraps), or to an explicit color.  6/18/96 tk"
  40578.     colorSpec isInteger
  40579.         ifTrue: [destForm depth=1 ifTrue: [^ self fillColor: destForm black].
  40580.                 "spread colors out in randomish fashion"
  40581.                 self fillColor: (Colors atWrap: colorSpec*9)]
  40582.         ifFalse: [self fillColor: colorSpec].    "arg must be a color already"!
  40583. white 
  40584.     "Set the receiver's mask to the white form."
  40585.  
  40586.     self fillColor: destForm white! !
  40587.  
  40588. !Pen methodsFor: 'moving'!
  40589. down
  40590.     "Set the state of the receiver's pen to down (drawing)."
  40591.  
  40592.     penDown _ true!
  40593. fillIn: aBlock
  40594.     "The argument, aBlock, should create a closed outline which is then 
  40595.     filled in with the current source form. Pen's just evaluate the block; 
  40596.     subclasses can carry out the full method."
  40597.  
  40598.     ^ aBlock value!
  40599. fillInAndFrame: aBlock
  40600.     "The argument, aBlock, should create a closed outline which is then 
  40601.     filled in with the current source form. Pens just evaluate the block; 
  40602.     subclasses can carry out the full method."
  40603.  
  40604.     ^ aBlock value!
  40605. go: distance 
  40606.     "Move the pen in its current direction a number of bits equal to the 
  40607.     argument, distance. If the pen is down, a line will be drawn using the 
  40608.     receiver's form source as the shape of the drawing brush."
  40609.  
  40610.     self goto: (direction degreeCos @ direction degreeSin) * distance + location!
  40611. goto: aPoint 
  40612.     "Move the receiver to position aPoint. If the pen is down, a line will be 
  40613.     drawn from the current position to the new one using the receiver's 
  40614.     form source as the shape of the drawing brush. The receiver's set 
  40615.     direction does not change."
  40616.  
  40617.     | old |
  40618.     old _ location.
  40619.     location _ aPoint.
  40620.     penDown ifTrue: [self drawFrom: old to: location]!
  40621. home
  40622.     "Place the receiver at the center of its frame."
  40623.     location _ destForm boundingBox center!
  40624. north
  40625.     "Set the receiver's direction to facing toward the top of the display screen."
  40626.  
  40627.     direction _ 270!
  40628. place: aPoint 
  40629.     "Set the receiver at position aPoint. No lines are drawn."
  40630.  
  40631.     location _ aPoint!
  40632. print: str withFont: font
  40633.     "Print the given string in the given font at the current heading"
  40634.     | lineStart form charStart rowStart scale wasDown bb pix |
  40635.     scale _ sourceForm width.
  40636.     wasDown _ penDown.
  40637.     lineStart _ location.
  40638.     str do:
  40639.         [:char |
  40640.         char = Character cr ifTrue:
  40641.             [self place: lineStart; up; turn: 90; go: font height*scale; turn: -90; down]
  40642.         ifFalse:
  40643.             [form _ font characterFormAt: char.
  40644.             charStart _ location.
  40645. wasDown ifTrue: [
  40646.             self up; turn: -90; go: font descent*scale; turn: 90; down.
  40647.             0 to: form height-1 do:
  40648.                 [:y |
  40649.                 rowStart _ location.
  40650.                 bb _ BitBlt bitPeekerFromForm: form.
  40651.                 pix _ RunArray newFrom:
  40652.                     ((0 to: form width-1) collect: [:x | bb pixelAt: x@y]).
  40653.                 pix runs with: pix values do:
  40654.                     [:run :value |
  40655.                     value = 0
  40656.                         ifTrue: [self up; go: run*scale; down]
  40657.                         ifFalse: [self go: run*scale]].
  40658.                 self place: rowStart; up; turn: 90; go: scale; turn: -90; down].
  40659. ].
  40660.             self place: charStart; up; go: form width*scale; down].
  40661.             ].
  40662.     wasDown ifFalse: [self up]
  40663. "
  40664. Display restoreAfter:
  40665. [Pen new squareNib: 2; color: Color red; turn: 45;
  40666.     print: 'The owl and the pussycat went to sea
  40667. in a beautiful pea green boat.' withFont: (TextStyle default fontAt: 1)]
  40668. "!
  40669. turn: degrees 
  40670.     "Change the direction that the receiver faces by an amount equal to the 
  40671.     argument, degrees."
  40672.  
  40673.     direction _ direction + degrees!
  40674. up
  40675.     "Set the state of the receiver's pen to up (no drawing)."
  40676.  
  40677.     penDown _ false! !
  40678.  
  40679. !Pen methodsFor: 'geometric designs'!
  40680. dragon: n  "Display restoreAfter: [Display fillWhite. 1 to: 4 do:
  40681.     [:i | Pen new color: i; turn: 90*i; dragon: 10]]"
  40682.     "Draw a dragon curve of order n in the center of the screen."
  40683.     n = 0
  40684.         ifTrue: [self go: 5]
  40685.         ifFalse: [n > 0
  40686.                 ifTrue: [self dragon: n - 1; turn: 90; dragon: 1 - n]
  40687.                 ifFalse: [self dragon: -1 - n; turn: -90; dragon: 1 + n]]!
  40688. filberts: n side: s 
  40689.     "Two Hilbert curve fragments form a Hilbert tile. Draw four interlocking 
  40690.     tiles of order n and sides length s."
  40691.     | n2 |
  40692.     Display fillWhite.
  40693.     n2 _ 1 bitShift: n - 1.
  40694.     self up; go: 0 - n2 * s; down.
  40695.     1 to: 4 do: 
  40696.         [:i | 
  40697.         self color: i - 1 * 40.
  40698.         self
  40699.             fillInAndFrame: 
  40700.                 [self hilbert: n side: s.
  40701.                 self go: s.
  40702.                 self hilbert: n side: s.
  40703.                 self go: s].
  40704.         self up.
  40705.         self go: n2 - 1 * s.
  40706.         self turn: -90.
  40707.         self go: n2 * s.
  40708.         self turn: 180.
  40709.         self down]!
  40710. hilbert: n side: s 
  40711.     "Draw an nth level Hilbert curve with side length s in the center of the 
  40712.     screen. Write directly into the display's bitmap only. A Hilbert curve is 
  40713.     a space-filling curve."
  40714.  
  40715.     | a m |
  40716.     n = 0 ifTrue: [^self turn: 180].
  40717.     n > 0
  40718.         ifTrue: 
  40719.             [a _ 90.
  40720.             m _ n - 1]
  40721.         ifFalse: 
  40722.             [a _ -90.
  40723.             m _ n + 1].
  40724.     self turn: a.
  40725.     self hilbert: 0 - m side: s.
  40726.     self turn: a; go: s.
  40727.     self hilbert: m side: s.
  40728.     self turn: 0 - a; go: s; turn: 0 - a.
  40729.     self hilbert: m side: s.
  40730.     self go: s; turn: a.
  40731.     self hilbert: 0 - m side: s.
  40732.     self turn: a
  40733.     " 
  40734.     (Pen new) hilbert: 3 side: 8. 
  40735.     (Pen new sourceForm: Cursor wait) combinationRule: Form under; 
  40736.     hilbert: 3 side: 25.
  40737.     "!
  40738. hilberts: n   "Display restoreAfter: [Display fillWhite.  Pen new hilberts: 5]"
  40739.     "Draws n levels of nested Hilbert curves"
  40740.     | s |
  40741.     self up; turn: 90; go: 128; down.
  40742.     1 to: n do: 
  40743.         [:i | 
  40744.         s _ 256 bitShift: 0 - i.
  40745.         self defaultNib: n - i * 2 + 1.
  40746.         self color: i+1.
  40747.         self up; go: 0 - s / 2; turn: -90; go: s / 2; turn: 90; down.
  40748.         self hilbert: i side: s.
  40749.         self go: s.
  40750.         self hilbert: i side: s.
  40751.         self go: s]!
  40752. mandala: npoints diameter: d
  40753.     "Display restoreAfter: [Pen new mandala: 30 diameter: Display height-100]"
  40754.     "On a circle of diameter d, place npoints number of points. Draw all     possible connecting lines between the circumferential points."
  40755.     | l points |
  40756.     Display fillWhite.
  40757.     l _ 3.14 * d / npoints.
  40758.     self home; up; turn: -90; go: d // 2; turn: 90; go: 0 - l / 2; down.
  40759.     points _ Array new: npoints.
  40760.     1 to: npoints do: 
  40761.         [:i | 
  40762.         points at: i put: location rounded.
  40763.         self go: l; turn: 360.0 / npoints].
  40764.     npoints // 2
  40765.         to: 1
  40766.         by: -1
  40767.         do: 
  40768.             [:i | 
  40769.             self color: i.
  40770.             1 to: npoints do: 
  40771.                 [:j | 
  40772.                 self place: (points at: j).
  40773.                 self goto: (points at: j + i - 1 \\ npoints + 1)]]
  40774. !
  40775. spiral: n angle: a 
  40776.     "Draw a double squiral (see Papert, MindStorms), where each design is made
  40777.     by moving the receiver a distance of n after turning the amount + or -a."
  40778.  
  40779.     1 to: n do: 
  40780.         [:i | 
  40781.         self color: i * 2.
  40782.         self go: i; turn: a]
  40783. "
  40784.     Display fillWhite. Pen new spiral: 200 angle: 89; home; spiral: 200 angle: -89.
  40785. "!
  40786. web   "Display restoreAfter: [Pen new web]"
  40787.     "Draw pretty web-like patterns from the mouse movement on the screen.
  40788.     Press the mouse button to draw, option-click to exit.
  40789.     By Dan Ingalls and Mark Lentczner. "
  40790.     | history newPoint ancientPoint lastPoint filter color |
  40791.     "self erase."
  40792.     color _ 1.
  40793.     [ true ] whileTrue:
  40794.         [ history _ SharedQueue new.
  40795.         Sensor waitButton.
  40796.         Sensor yellowButtonPressed ifTrue: [^ self].
  40797.         filter _ lastPoint _ Sensor mousePoint.
  40798.         20 timesRepeat: [ history nextPut: lastPoint ].
  40799.         self color: (color _ color + 1).
  40800.         [ Sensor redButtonPressed ] whileTrue: 
  40801.             [ newPoint _ Sensor mousePoint.
  40802.             (newPoint = lastPoint) ifFalse:
  40803.                 [ ancientPoint _ history next.
  40804.                 filter _ filter * 4 + newPoint // 5.
  40805.                 self place: filter.
  40806.                 self goto: ancientPoint.
  40807.                 lastPoint _ newPoint.
  40808.                 history nextPut: filter ] ] ]! !
  40809.  
  40810. !Pen methodsFor: 'private'!
  40811. sourceForm: aForm
  40812.     (aForm depth = 1 and: [destForm depth > 1])
  40813.         ifTrue: ["Map 1-bit source to all ones for color mask"
  40814.                 colorMap _ Bitmap with: 0 with: 16rFFFFFFFF]
  40815.         ifFalse: [colorMap _ nil].
  40816.     ^ super sourceForm: aForm! !
  40817. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  40818.  
  40819. Pen class
  40820.     instanceVariableNames: ''!
  40821.  
  40822. !Pen class methodsFor: 'instance creation'!
  40823. new
  40824.     ^ self newOnForm: Display!
  40825. newOnForm: aForm
  40826.     | pen |
  40827.     pen _ super new.
  40828.     pen setDestForm: aForm.
  40829.     pen sourceOrigin: 0@0.
  40830.     pen home.
  40831.     pen defaultNib: 1.
  40832.     pen north.
  40833.     pen down.
  40834.     ^ pen! !
  40835.  
  40836. !Pen class methodsFor: 'class initialization'!
  40837. initialize  "Pen initialize"
  40838.     Colors _ Color red wheel: 20.! !
  40839.  
  40840. !Pen class methodsFor: 'examples'!
  40841. example
  40842.     "Draw a spiral in gray with a pen that is 4 pixels wide."
  40843.  
  40844.     | bic |  
  40845.     bic _ self new. 
  40846.     bic defaultNib: 4.
  40847.     bic combinationRule: Form under.
  40848.     1 to: 50 do: [:i | bic go: i*4. bic turn: 89]
  40849.  
  40850.     "Pen example"! !
  40851.  
  40852. Pen initialize!
  40853. AbstractSound subclass: #PluckedSound
  40854.     instanceVariableNames: 'initialCount count amplitude ring ringSize ringIndx '
  40855.     classVariableNames: ''
  40856.     poolDictionaries: ''
  40857.     category: 'Sound'!
  40858.  
  40859. !PluckedSound methodsFor: 'initialization'!
  40860. setPitch: p dur: d loudness: l
  40861.  
  40862.     amplitude _ l rounded.
  40863.     ring _ SoundBuffer new: (((2.0 * self samplingRate asFloat) / p asFloat) asInteger max: 2).
  40864.     ringSize _ ring size.
  40865.     initialCount _ (d * self samplingRate asFloat) asInteger.
  40866.     self reset.
  40867. ! !
  40868.  
  40869. !PluckedSound methodsFor: 'sound generation'!
  40870. mixSampleCount: n into: aSoundBuffer startingAt: startIndex pan: pan
  40871.     "The Karplus-Strong plucked string algorithm: start with a buffer full of random noise and repeatedly play the contents of that buffer while averaging adjacent samples. High harmonics damp out more quickly, transfering their energy to lower ones. The length of the buffer corresponds to the length of the string. It may be out of tune for higher pitches because the buffer length must be an integral number of samples and the nearest integer may not result in the exact pitch desired."
  40872.     "(PluckedSound pitch: 220.0 dur: 3.0 loudness: 1000) play"
  40873.  
  40874.     | lastIndex thisIndex i nextIndex mySample channelIndex sample |
  40875.     <primitive: 178>
  40876.     self var: #aSoundBuffer declareC: 'short int *aSoundBuffer'.
  40877.     self var: #ring declareC: 'short int *ring'.
  40878.  
  40879.     lastIndex _ (startIndex + n) - 1.
  40880.     thisIndex _ ringIndx.
  40881.     startIndex to: lastIndex do: [ :i |
  40882.         nextIndex _ (thisIndex \\ ringSize) + 1.
  40883.         mySample _ ((ring at: thisIndex) + (ring at: nextIndex)) // 2.
  40884.         ring at: thisIndex put: mySample.
  40885.         thisIndex _ nextIndex.
  40886.  
  40887.         pan > 0 ifTrue: [
  40888.             channelIndex _ 2 * i.
  40889.             sample _ (aSoundBuffer at: channelIndex) + ((mySample * pan) // 1000).
  40890.             sample >  32767 ifTrue: [ sample _  32767 ].  "clipping!!"
  40891.             sample < -32767 ifTrue: [ sample _ -32767 ].  "clipping!!"
  40892.             aSoundBuffer at: channelIndex put: sample.
  40893.         ].
  40894.         pan < 1000 ifTrue: [
  40895.             channelIndex _ (2 * i) - 1.
  40896.             sample _ (aSoundBuffer at: channelIndex) + ((mySample * (1000 - pan)) // 1000).
  40897.             sample >  32767 ifTrue: [ sample _  32767 ].  "clipping!!"
  40898.             sample < -32767 ifTrue: [ sample _ -32767 ].  "clipping!!"
  40899.             aSoundBuffer at: channelIndex put: sample.
  40900.         ].
  40901.     ].
  40902.     ringIndx _ nextIndex.
  40903.     count _ count - n.
  40904. !
  40905. reset
  40906.     "Fill the ring with random noise."
  40907.  
  40908.     | seed |
  40909.     super reset.
  40910.     seed _ Time millisecondClockValue bitAnd: 65535.
  40911.     1 to: ringSize do: [ :i |
  40912.         seed _ ((seed * 1309) + 13849) bitAnd: 65535.
  40913.         ring at: i put: (((seed - 32768) * amplitude) bitShift: -10).
  40914.     ].
  40915.     count _ initialCount.
  40916.     ringIndx _ 1.
  40917. !
  40918. samplesRemaining
  40919.  
  40920.     ^ count! !Object subclass: #Point
  40921.     instanceVariableNames: 'x y '
  40922.     classVariableNames: ''
  40923.     poolDictionaries: ''
  40924.     category: 'Graphics-Primitives'!
  40925. Point comment:
  40926. 'I represent an x-y pair of numbers usually designating a location on the screen.'!
  40927.  
  40928. !Point methodsFor: 'accessing'!
  40929. x
  40930.     "Answer the x coordinate."
  40931.  
  40932.     ^x!
  40933. x: xInteger 
  40934.     "Set the x coordinate."
  40935.  
  40936.     x _ xInteger!
  40937. y
  40938.     "Answer the y coordinate."
  40939.  
  40940.     ^y!
  40941. y: yInteger 
  40942.     "Set the y coordinate."
  40943.  
  40944.     y _ yInteger! !
  40945.  
  40946. !Point methodsFor: 'comparing'!
  40947. < aPoint 
  40948.     "Answer whether the receiver is above and to the left of aPoint."
  40949.  
  40950.     ^x < aPoint x and: [y < aPoint y]!
  40951. <= aPoint 
  40952.     "Answer whether the receiver is neither below nor to the right of aPoint."
  40953.  
  40954.     ^x <= aPoint x and: [y <= aPoint y]!
  40955. = aPoint
  40956.  
  40957.     self species = aPoint species
  40958.         ifTrue: [^x = aPoint 
  40959.     "Refer to the comment in Object|=." x and: [y = aPoint y]]
  40960.         ifFalse: [^false]!
  40961. > aPoint 
  40962.     "Answer whether the receiver is below and to the right of aPoint."
  40963.  
  40964.     ^x > aPoint x and: [y > aPoint y]!
  40965. >= aPoint 
  40966.     "Answer whether the receiver is neither above nor to the left of aPoint."
  40967.  
  40968.     ^x >= aPoint x and: [y >= aPoint y]!
  40969. farFrom: aPoint by: distance
  40970.     | pt delta |
  40971.     pt _ (self - aPoint) abs.
  40972.     delta _ distance asPoint.
  40973.     ^ pt x > delta x or: [pt y > delta y]!
  40974. hash
  40975.     "Hash is reimplemented because = is implemented."
  40976.  
  40977.     ^(x hash bitShift: 2) bitXor: y hash!
  40978. hashMappedBy: map
  40979.     "My hash is independent of my oop."
  40980.  
  40981.     ^self hash!
  40982. isAllZero
  40983.  
  40984.     ^ (x = 0) & (y = 0)
  40985. !
  40986. isZeroPt
  40987.  
  40988.     ^ x = 0 and: [y = 0]
  40989. !
  40990. max: aPoint 
  40991.     "Answer the lower right corner of the rectangle uniquely defined by the 
  40992.     receiver and the argument, aPoint."
  40993.  
  40994.     ^ (x max: aPoint x) @ (y max: aPoint y)!
  40995. min: aPoint 
  40996.     "Answer the upper left corner of the rectangle uniquely defined by the 
  40997.     receiver and the argument, aPoint."
  40998.  
  40999.     ^ (x min: aPoint x) @ (y min: aPoint y)!
  41000. min: aMin max: aMax 
  41001.  
  41002.     ^ (self min: aMin) max: aMax! !
  41003.  
  41004. !Point methodsFor: 'arithmetic'!
  41005. * scale 
  41006.     "Answer a Point that is the product of the receiver and scale (which is a 
  41007.     Point or Number)."
  41008.  
  41009.     | scalePoint |
  41010.     scalePoint _ scale asPoint.
  41011.     ^x * scalePoint x @ (y * scalePoint y)!
  41012. + delta 
  41013.     "Answer a Point that is the sum of the receiver and delta (which is a 
  41014.     Point or Number)."
  41015.  
  41016.     | deltaPoint |
  41017.     deltaPoint _ delta asPoint.
  41018.     ^x + deltaPoint x @ (y + deltaPoint y)!
  41019. - delta 
  41020.     "Answer a Point that is the difference of the receiver and delta (which is 
  41021.     a Point or Number)."
  41022.  
  41023.     | deltaPoint |
  41024.     deltaPoint _ delta asPoint.
  41025.     ^x - deltaPoint x @ (y - deltaPoint y)!
  41026. / scale 
  41027.     "Answer a Point that is the quotient of the receiver and scale (which is a 
  41028.     Point or Number)."
  41029.  
  41030.     | scalePoint |
  41031.     scalePoint _ scale asPoint.
  41032.     ^x / scalePoint x @ (y / scalePoint y)!
  41033. // scale 
  41034.     "Answer a Point that is the quotient of the receiver and scale (which is a 
  41035.     Point or Number)."
  41036.  
  41037.     | scalePoint |
  41038.     scalePoint _ scale asPoint.
  41039.     ^x // scalePoint x @ (y // scalePoint y)!
  41040. abs
  41041.     "Answer a Point whose x and y are the absolute values of the receiver's x 
  41042.     and y."
  41043.  
  41044.     ^ x abs @ y abs! !
  41045.  
  41046. !Point methodsFor: 'truncation and round off'!
  41047. rounded
  41048.     "Answer a Point that is the receiver's x and y rounded."
  41049.  
  41050.     ^x rounded @ y rounded!
  41051. truncated
  41052.     "Answer a Point that is the receiver's x and y truncated by removing the fractional part."
  41053.  
  41054.     ^(x truncated) @ (y truncated)!
  41055. truncateTo: grid
  41056.     "Answer a Point that is the receiver's x and y truncated to grid x and 
  41057.     grid y."
  41058.     | gridPoint |
  41059.     gridPoint _ grid asPoint.
  41060.     ^(x truncateTo: gridPoint x) @ (y truncateTo: gridPoint y)! !
  41061.  
  41062. !Point methodsFor: 'polar coordinates'!
  41063. r
  41064.     "Answer the receiver's radius in polar coordinate system."
  41065.  
  41066.     ^(self dotProduct: self) sqrt!
  41067. theta
  41068.     "Answer the angle the receiver makes with origin in radians. right is 0; 
  41069.     down is 90."
  41070.  
  41071.     | tan theta |
  41072.     x = 0
  41073.         ifTrue: [y >= 0
  41074.                 ifTrue: [^1.5708"90.0 degreesToRadians"]
  41075.                 ifFalse: [^4.71239"270.0 degreesToRadians"]]
  41076.         ifFalse: 
  41077.             [tan _ y asFloat / x asFloat.
  41078.             theta _ tan arcTan.
  41079.             x >= 0
  41080.                 ifTrue: [y >= 0
  41081.                         ifTrue: [^theta]
  41082.                         ifFalse: [^360.0 degreesToRadians + theta]]
  41083.                 ifFalse: [^180.0 degreesToRadians + theta]]! !
  41084.  
  41085. !Point methodsFor: 'point functions'!
  41086. dist: aPoint 
  41087.     "Answer the distance between aPoint and the receiver."
  41088.  
  41089.     ^(aPoint - self) r!
  41090. dotProduct: aPoint 
  41091.     "Answer a number that is the dot product of the receiver and the 
  41092.     argument, aPoint. That is, the two points are multipled and the 
  41093.     coordinates of the result summed."
  41094.  
  41095.     | temp |
  41096.     temp _ self * aPoint.
  41097.     ^temp x abs + temp y abs!
  41098. eightNeighbors
  41099.     ^ (Array with: self + (1@0)
  41100.         with: self + (1@1)
  41101.         with: self + (0@1)
  41102.         with: self + (-1@1)) ,
  41103.     (Array with: self + (-1@0)
  41104.         with: self + (-1@-1)
  41105.         with: self + (0@-1)
  41106.         with: self + (1@-1))
  41107. !
  41108. flipBy: direction centerAt: c
  41109.     "Answer a Point which is receiver flipped according to the direction, either #vertical or #horizontal, center at point c"
  41110.     ^ direction == #vertical 
  41111.         ifTrue: [x @ (c y * 2 - y)]
  41112.         ifFalse: [(c x * 2 - x) @ y]!
  41113. fourNeighbors
  41114.     ^ Array with: self + (1@0)
  41115.         with: self + (0@1)
  41116.         with: self + (-1@0)
  41117.         with: self + (0@-1)
  41118. !
  41119. grid: aPoint 
  41120.     "Answer a Point to the nearest rounded grid modules specified by aPoint."
  41121.  
  41122.     | newX newY |
  41123.     newX _ x + (aPoint x // 2) truncateTo: aPoint x.
  41124.     newY _ y + (aPoint y // 2) truncateTo: aPoint y.
  41125.     ^newX @ newY!
  41126. isRectilinear: aPoint
  41127.  
  41128.     "Answer true if a line between the receiver and aPoint is either vertical or horizontal, else false"
  41129.  
  41130.     ^ (x == aPoint x) | (y == aPoint y)!
  41131. nearestPointAlongLineFrom: p1 to: p2
  41132.     "Note this will give points beyond the endpoints!!"
  41133.     "There may be a simpler way; I just followed algebra - Dan I."
  41134.     | x1 y1 x2 y2 x21 y21 xx yy y4 x4 |
  41135.     p1 x = p2 x ifTrue: [^ p1 x @ y].  "vertical line"
  41136.     p1 y = p2 y ifTrue: [^ x @ p1 y].  "horizontal line"
  41137.     x1 _ p1 x asFloat.  y1 _ p1 y asFloat.
  41138.     x2 _ p2 x asFloat.  y2 _ p2 y asFloat.
  41139.     x21 _ x2 - x1.
  41140.     y21 _ y2 - y1.
  41141.     xx _ x21 * x21.
  41142.     yy _ y21 * y21.
  41143.     y4 _ ((y2*xx) + (y*yy) - ((x2-x) * y21 * x21))/(xx + yy).
  41144.     x4 _ x - ((y4-y) * y21 / x21).
  41145.     ^ x4 @ y4
  41146. "
  41147.     | p |
  41148.     Pen new place: 0@0; goto: 500@300.
  41149.     [Sensor anyButtonPressed] whileFalse:
  41150.         [p _ Sensor cursorPoint nearestPointAlongLineFrom: 0@0 to: 500@300.
  41151.         2 timesRepeat: [Display reverse: (p extent: 10@10)]]
  41152. "
  41153. !
  41154. normal
  41155.     "Answer a Point representing the unit vector rotated 90 deg clockwise."
  41156.  
  41157.     | n |
  41158.     n _ y negated @ x.
  41159.     ^n / (n x * n x + (n y * n y)) sqrt!
  41160. octantOf: otherPoint
  41161.     "Return 1..8 indicating relative direction to otherPoint.
  41162.     1=ESE, 2=SSE, ... etc. clockwise to 8=ENE"
  41163.     | quad moreHoriz |
  41164.     (x = otherPoint x and: [y > otherPoint y]) ifTrue: [^ 6].    "special case"
  41165.     (y = otherPoint y and: [x < otherPoint x]) ifTrue: [^ 8].
  41166.  
  41167.     quad _ self quadrantOf: otherPoint.
  41168.     moreHoriz _ (x - otherPoint x) abs >= (y - otherPoint y) abs.
  41169.     (quad even eqv: moreHoriz)
  41170.         ifTrue: [^ quad*2]
  41171.         ifFalse: [^ quad*2 - 1]!
  41172. onLineFrom: p1 to: p2
  41173.  
  41174.     "Answer true if the receiver is on the line between p1 and p2 within a small epsilon. P1 is assumed to be to the left of p2."
  41175.  
  41176.     | origin corner normalizedP2 normalizedPt computed |
  41177.  
  41178.     "test if receiver is within the bounding box"
  41179.     p1 y > p2 y
  41180.         ifTrue: [origin _ p1 x @ p2 y.
  41181.                 corner _ p2 x @ p1 y]
  41182.         ifFalse: [origin _ p1.
  41183.                 corner _ p2.].
  41184.     (((origin corner: corner) insetBy: -3) containsPoint: self) ifFalse: [^ false].
  41185.  
  41186.     "its in the box, is it on the line?"
  41187.     (origin isRectilinear: corner) ifTrue: [^ true].
  41188.  
  41189.     normalizedP2 _ p2 - p1.
  41190.     normalizedPt _ self - p1.
  41191.     normalizedP2 x abs < normalizedP2 y abs
  41192.         ifTrue: [computed _ normalizedP2 x * normalizedPt y / normalizedP2 y asInteger.
  41193.                 ^ (normalizedPt x < (computed + 3)) & (normalizedPt x > (computed - 3))]
  41194.         ifFalse: [computed _ normalizedP2 y * normalizedPt x / normalizedP2 x asInteger.
  41195.                 ^ (normalizedPt y < (computed + 3)) & (normalizedPt y > (computed - 3))]!
  41196. quadrantOf: otherPoint
  41197.     "Return 1..4 indicating relative direction to otherPoint.
  41198.     1 is downRight, 2=downLeft, 3=upLeft, 4=upRight"
  41199.     ^ x <= otherPoint x
  41200.         ifTrue: [y <= otherPoint y ifTrue: [1] ifFalse: [4]]
  41201.         ifFalse: [y <= otherPoint y ifTrue: [2] ifFalse: [3]]
  41202. !
  41203. rotateBy: direction centerAt: c
  41204.     "Answer a Point which is receiver rotated according to the direction, either #right or #left, center at point c"
  41205.     | offset |
  41206.     offset _ self - c.
  41207.     ^ direction == #right 
  41208.         ifTrue: [offset y negated @ offset x + c]
  41209.         ifFalse: [offset y @ offset x negated + c]!
  41210. transpose
  41211.     "Answer a Point whose x is the receiver's y and whose y is the receiver's 
  41212.     x."
  41213.  
  41214.     ^y @ x!
  41215. truncatedGrid: aPoint 
  41216.     "Answer a Point to the nearest truncated grid modules specified by 
  41217.     aPoint."
  41218.  
  41219.     ^(x truncateTo: aPoint x) @ (y truncateTo: aPoint y)! !
  41220.  
  41221. !Point methodsFor: 'converting'!
  41222. asHeading
  41223.     "Treating the receiver as a velocity (with negative y meaning up for the time being), return the heading, in degrees,  represented.  Returns an integer result in the range [0, 359]
  41224.     5/13/96 sw"
  41225.     
  41226.     | ans |
  41227.     x == 0 ifTrue:
  41228.         [^ y > 0 ifTrue: [180] ifFalse: [0]]. 
  41229.      ans _ (90 + ((y asFloat / x) arcTan radiansToDegrees rounded)) \\ 360.
  41230.     ^ x > 0
  41231.         ifTrue:
  41232.             [ans]
  41233.         ifFalse:
  41234.             [ans + 180]
  41235.  
  41236.  
  41237. "  Array with:
  41238.         (10 @ 10) asHeading
  41239.     with:
  41240.         (10 @ -10) asHeading
  41241.     with:
  41242.         (-10 @ 10) asHeading
  41243.     with:
  41244.         (-10 @ -10) asHeading"!
  41245. asIntegerPoint
  41246.     ^ x asInteger @ y asInteger!
  41247. asPoint
  41248.     "Answer the receiver itself."
  41249.  
  41250.     ^self!
  41251. corner: aPoint 
  41252.     "Answer a Rectangle whose origin is the receiver and whose corner is 
  41253.     aPoint. This is one of the infix ways of expressing the creation of a 
  41254.     rectangle."
  41255.  
  41256.     ^Rectangle origin: self corner: aPoint!
  41257. extent: aPoint 
  41258.     "Answer a Rectangle whose origin is the receiver and whose extent is 
  41259.     aPoint. This is one of the infix ways of expressing the creation of a 
  41260.     rectangle."
  41261.  
  41262.     ^Rectangle origin: self extent: aPoint! !
  41263.  
  41264. !Point methodsFor: 'transforming'!
  41265. adhereTo: aRectangle
  41266.     "If the receiver lies outside aRectangle, it is mapped to the nearest point on the boundary of the rectangle"
  41267.  
  41268. (aRectangle containsPoint: self)
  41269.     ifFalse: [x _ x max: (aRectangle origin x).
  41270.             x _ x min: (aRectangle corner x).
  41271.             y _ y max: (aRectangle origin y).
  41272.             y _ y min: (aRectangle corner y)]
  41273. "Redo this more efficiently"
  41274.                 !
  41275. negated
  41276.     "Answer a point whose x and y coordinates are the negatives of those of the receiver.  6/6/96 sw"
  41277.  
  41278.     ^ x negated @ y negated!
  41279. rotateBy: angle about: center
  41280.     "Even though Point.theta is measured CW, this rotates with the more conventional CCW interpretateion of angle"
  41281.     | p r th |
  41282.     p _ self-center.
  41283.     r _ p r.
  41284.     th _ p theta negated.
  41285.     ^ center + ((r * (th+angle) cos) @ (r * (th+angle) sin negated))!
  41286. scaleBy: factor 
  41287.     "Answer a Point scaled by factor (an instance of Point)."
  41288.  
  41289.     ^(factor x * x) @ (factor y * y)!
  41290. translateBy: delta 
  41291.     "Answer a Point translated by delta (an instance of Point)."
  41292.  
  41293.     ^(delta x + x) @ (delta y + y)! !
  41294.  
  41295. !Point methodsFor: 'copying'!
  41296. copy
  41297.     "Implemented here for better performance."
  41298.  
  41299.     ^ x @ y!
  41300. deepCopy
  41301.     "Implemented here for better performance."
  41302.  
  41303.     ^x deepCopy @ y deepCopy!
  41304. shallowCopy
  41305.     "Implemented here for better performance."
  41306.  
  41307.     ^ x @ y! !
  41308.  
  41309. !Point methodsFor: 'printing'!
  41310. printOn: aStream 
  41311.     "The receiver prints on aStream in terms of infix notation."
  41312.  
  41313.     x printOn: aStream.
  41314.     aStream nextPut: $@.
  41315.     y printOn: aStream!
  41316. storeOn: aStream 
  41317.     "x@y printed form is good for storing too"
  41318.     self printOn: aStream! !
  41319.  
  41320. !Point methodsFor: 'private'!
  41321. setX: xPoint setY: yPoint
  41322.  
  41323.     x _ xPoint.
  41324.     y _ yPoint! !
  41325.  
  41326. !Point methodsFor: 'MacApp'!
  41327. at: aCoordSymbol put: value
  41328.  
  41329.     (aCoordSymbol == #y or: [aCoordSymbol == #v]) ifTrue: [^y _ value]. 
  41330.     (aCoordSymbol == #x or: [aCoordSymbol == #h]) ifTrue: [^x _ value].
  41331.     ^self error: 'Unknown coordinate symbol: ', aCoordSymbol printString
  41332. !
  41333. h
  41334.     ^x
  41335. !
  41336. h: h
  41337.     self x: h
  41338. !
  41339. v
  41340.     ^y
  41341. !
  41342. v: v
  41343.     self y: v
  41344. ! !
  41345. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  41346.  
  41347. Point class
  41348.     instanceVariableNames: ''!
  41349.  
  41350. !Point class methodsFor: 'instance creation'!
  41351. x: xInteger y: yInteger 
  41352.     "Answer an instance of me with coordinates xInteger and yInteger."
  41353.  
  41354.     ^self new setX: xInteger setY: yInteger! !Object subclass: #PopUpMenu
  41355.     instanceVariableNames: 'labelString font lineArray frame form marker selection '
  41356.     classVariableNames: ''
  41357.     poolDictionaries: ''
  41358.     category: 'Interface-Menus'!
  41359. PopUpMenu comment:
  41360. 'I represent a list of items. My instances are presented on the display screen in a rectangular area. The user points to an item, pressing a mouse button; the item is highlighted. When the button is released, the highlighted item indicates the selection.'!
  41361.  
  41362. !PopUpMenu methodsFor: 'basic control sequence'!
  41363. startUp
  41364.     "Display and make a selection from the receiver as long as the button 
  41365.     is pressed. Answer the current selection."
  41366.     
  41367.     ^ self startUpWithCaption: nil!
  41368. startUpCenteredWithCaption: captionOrNil
  41369.     "Differs from startUpWithCaption: by appearing with cursor in the menu,
  41370.     and thus ready to act on mouseUp, without requiring user tweak to confirm"
  41371.     
  41372.     Cursor normal showWhile:
  41373.         [self displayAt: Sensor cursorPoint - (frame width//2@0)
  41374.             withCaption: captionOrNil
  41375.             during: [[Sensor anyButtonPressed] whileFalse: [].
  41376.                     [Sensor anyButtonPressed] whileTrue: [self manageMarker]]].
  41377.     ^selection!
  41378. startUpWithCaption: captionOrNil
  41379.     "Wait for the mouse button to go down.
  41380.     Display the menu, with caption if supplied.
  41381.     Track the selection as long as the button is pressed.
  41382.     When the button is released, answer the current selection."
  41383.     
  41384.     Cursor normal showWhile:
  41385.         [self displayAt: Sensor cursorPoint 
  41386.             withCaption: captionOrNil
  41387.             during: [Sensor cursorPoint: marker center.
  41388.                     [Sensor anyButtonPressed] whileFalse: [].
  41389.                     [Sensor anyButtonPressed] whileTrue: [self manageMarker]]].
  41390.     ^selection! !
  41391.  
  41392. !PopUpMenu methodsFor: 'displaying'!
  41393. displayAt: aPoint withCaption: captionOrNil during: aBlock 
  41394.     "Display the receiver just to the right of aPoint while aBlock is evaluated.  If the receiver is forced off screen, display it just to the right."
  41395.     | delta savedArea captionView captionSave outerFrame captionText tFrame frameSaveLoc |
  41396.     frame _ frame align: marker leftCenter with: aPoint + (2@0).
  41397.     outerFrame _ frame.
  41398.     captionOrNil notNil ifTrue:
  41399.         [captionText _ DisplayText
  41400.                 text: captionOrNil asText
  41401.                 textStyle: (TextStyle default copy alignment: 2).
  41402.         tFrame _ captionText boundingBox insetBy: -2.
  41403.         outerFrame _ frame merge: (tFrame align: tFrame bottomCenter
  41404.                     with: frame topCenter + (0@2))].
  41405.     delta _ outerFrame amountToTranslateWithin: Display boundingBox.
  41406.     frame moveBy: delta.
  41407.     captionOrNil notNil ifTrue:
  41408.         [captionView _ DisplayTextView new model: captionText.
  41409.         captionView align: captionView boundingBox bottomCenter
  41410.                     with: frame topCenter + (0@2).
  41411.         captionView insideColor: Display white.
  41412.         captionView borderWidth: 2.
  41413.         captionSave _ Form fromDisplay: captionView displayBox.
  41414.         captionView unlock; display; release].
  41415.     marker _ marker align: marker leftCenter with: aPoint + delta +  (2@0).
  41416.     savedArea _ Form fromDisplay: frame.
  41417.     form displayOn: Display at: (frameSaveLoc _ frame topLeft).
  41418.     selection ~= 0 ifTrue: [Display reverse: marker].
  41419.     aBlock value.
  41420.     savedArea displayOn: Display at: frameSaveLoc.
  41421.     captionOrNil notNil ifTrue:
  41422.         [captionSave displayOn: Display at: captionView displayBox topLeft]! !
  41423.  
  41424. !PopUpMenu methodsFor: 'accessing'!
  41425. center
  41426.     "Answer the point at the center of the receiver's rectangular area."
  41427.  
  41428.     ^frame center!
  41429. labelString
  41430.  
  41431.     ^ labelString!
  41432. lineArray
  41433.  
  41434.     ^ lineArray! !
  41435.  
  41436. !PopUpMenu methodsFor: 'marker adjustment'!
  41437. manageMarker
  41438.     "If the cursor is inside the receiver's frame, then highlight the marked 
  41439.     item. Otherwise no item is to be marked."
  41440.     | pt |
  41441.     pt _ Sensor cursorPoint.
  41442.     (frame inside containsPoint: pt)
  41443.         ifTrue: [(Display boundingBox containsPoint: pt)
  41444.                     ifFalse: [pt _ pt - (self scrollIntoView: pt)].
  41445.                 self markerOn: pt]
  41446.         ifFalse: [self markerOff]!
  41447. markerOff
  41448.     "No item is selected. Reverse the highlight if any item has been marked 
  41449.     as selected."
  41450.  
  41451.     selection ~= 0
  41452.         ifTrue: 
  41453.             [Display reverse: marker.
  41454.             selection _ 0]!
  41455. markerOn: aPoint 
  41456.     "The item whose bounding area contains aPoint should be marked as 
  41457.     selected. Highlight its area and set the selection to its index."
  41458.  
  41459.     selection = 0 | (marker containsPoint: aPoint) not 
  41460.         ifTrue: [selection = 0 & (marker containsPoint: aPoint)
  41461.                     ifTrue: [Display reverse: marker]
  41462.                     ifFalse: 
  41463.                         [selection ~= 0 ifTrue: [Display reverse: marker].
  41464.                         marker _ 
  41465.                             marker 
  41466.                                 align: marker topLeft 
  41467.                                 with: marker left @ (self markerTop: aPoint).
  41468.                         Display reverse: marker]].
  41469.     selection _ marker top - frame top // marker height + 1!
  41470. markerTop: aPoint 
  41471.     "Answer aPoint, gridded to lines in the receiver."
  41472.  
  41473.     ^(aPoint y - frame inside top truncateTo: font height) + frame inside top!
  41474. scrollIntoView: cursorLoc
  41475.     | dy |
  41476.     dy _ 0.
  41477.     cursorLoc y < 0 ifTrue: [dy _ font height].
  41478.     cursorLoc y > Display height ifTrue: [dy _ font height negated].
  41479.     dy = 0 ifTrue: [^ 0@0].
  41480.     self markerOff.
  41481.     frame moveBy: 0@dy.
  41482.     marker moveBy: 0@dy.
  41483.     form displayOn: Display at: frame topLeft.
  41484.     ^ 0@dy! !
  41485.  
  41486. !PopUpMenu methodsFor: 'selecting'!
  41487. selection
  41488.     "Answer the current selection."
  41489.  
  41490.     ^selection!
  41491. setSelection: index
  41492.     | lineHeight newSelection |
  41493.     lineHeight _ font height.
  41494.     newSelection _ (0 max: index) min: frame height // lineHeight.
  41495.     marker _ marker translateBy:
  41496.          0 @ (lineHeight * (newSelection - selection)).
  41497.     selection _ newSelection! !
  41498.  
  41499. !PopUpMenu methodsFor: 'controlling'!
  41500. startUpBlueButton
  41501.     "Display and make a selection from the receiver as long as any button is pressed."
  41502.  
  41503.     ^self startUp!
  41504. startUpRedButton
  41505.     "Display and make a selection from the receiver as long as the red button 
  41506.     is pressed."
  41507.  
  41508.     ^self startUp!
  41509. startUpYellowButton
  41510.     "Display and make a selection from the receiver as long as the yellow 
  41511.     button is pressed."
  41512.  
  41513.     ^self startUp! !
  41514.  
  41515. !PopUpMenu methodsFor: 'private'!
  41516. labels: aString font: aFont lines: anArray
  41517.     "PopUpMenu allInstancesDo: [:x | x rescan]"
  41518.     | style paraForm inside labelPara |
  41519.     labelString _ aString.
  41520.     font _ aFont.
  41521.     style _ TextStyle fontArray: (Array with: font).
  41522.     style alignment: 2.  "centered"
  41523.     style gridForFont: 1 withLead: 0.
  41524.     lineArray _ anArray.
  41525.     labelPara _ Paragraph withText: aString asText style: style.
  41526.     paraForm _ labelPara asForm.
  41527.     form _ Form extent: paraForm extent + (4@4).
  41528.     form fillBlack.
  41529.     frame _ Quadrangle new.
  41530.     frame region: form boundingBox.
  41531.     frame borderWidth: 2.
  41532.     "Cheap drop shadow mask"
  41533.     "frame borderWidthLeft: 1 right: 3 top: 1 bottom: 3."
  41534.     paraForm displayOn: form at: frame inside topLeft.
  41535.     inside _ frame inside.
  41536.     lineArray == nil
  41537.       ifFalse:
  41538.         [lineArray do:
  41539.             [:line |
  41540.             form fillBlack: (0 @ ((line * font height) + inside top) extent: (frame width @ 1))]].
  41541.     marker _ inside topLeft extent:
  41542.                 inside width @ labelPara lineGrid.
  41543.     selection _ 1!
  41544. rescan
  41545.     "Cause me to be recreated for system changes like fonts."
  41546.  
  41547.     labelString == nil 
  41548.         ifFalse: [self labels: labelString font: font lines: lineArray]
  41549.  
  41550.     "PopUpMenu allInstancesDo: [:x | x rescan]"! !
  41551. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  41552.  
  41553. PopUpMenu class
  41554.     instanceVariableNames: ''!
  41555.  
  41556. !PopUpMenu class methodsFor: 'instance creation'!
  41557. labelArray: labelArray lines: lineArray
  41558.     "Answer an instance of me whose items are in anArray, with lines drawn  after each item indexed by anArray.  2/1/96 sw"
  41559.  
  41560.     | aStream |
  41561.     labelArray size == 0 ifTrue:
  41562.         [self error: 'Menu must not be zero size'].
  41563.     aStream _ WriteStream on: (String new: 40).
  41564.     labelArray doWithIndex: [:anitem :anIndex | 
  41565.         aStream nextPutAll: anitem.
  41566.         anIndex ~~ labelArray size
  41567.             ifTrue: [aStream cr]].
  41568.     ^ self labels: aStream contents lines: lineArray
  41569.  
  41570. "(PopUpMenu labelArray: #('frog' 'and' 'toad') lines: #()) startUp"!
  41571. labels: aString
  41572.     "Answer an instance of me whose items are in aString."
  41573.  
  41574.     ^self labels: aString lines: nil!
  41575. labels: aString lines: anArray
  41576.     "Answer an instance of me whose items are in aString, with lines drawn 
  41577.     after each item indexed by anArray."
  41578.  
  41579.     ^self new
  41580.         labels: aString
  41581.         font: (TextStyle default fontAt: 7)
  41582.         lines: anArray!
  41583. notify: message
  41584.     ^ (self labels: ' OK ') startUpWithCaption: message! !Stream subclass: #PositionableStream
  41585.     instanceVariableNames: 'collection position readLimit '
  41586.     classVariableNames: ''
  41587.     poolDictionaries: ''
  41588.     category: 'Collections-Streams'!
  41589. PositionableStream comment:
  41590. 'I represent an accessor for a sequence of objects (a collection) that are externally named by indices so that the point of access can be repositioned. I am abstract in that I do not implement the messages next and nextPut: which are inherited from my superclass Stream.'!
  41591.  
  41592. !PositionableStream methodsFor: 'accessing'!
  41593. contents
  41594.     "Answer with a copy of my collection from 1 to readLimit."
  41595.  
  41596.     ^collection copyFrom: 1 to: readLimit!
  41597. last
  41598.     "Return the final element in the receiver.  Put in at Alan's request.  2/2/96 sw"
  41599.  
  41600.     ^ collection at: (position - 1)!
  41601. next: anInteger 
  41602.     "Answer the next anInteger elements of the receiver."
  41603.  
  41604.     | newArray |
  41605.     newArray _ self contents species new: anInteger.
  41606.     1 to: anInteger do: [:index | newArray at: index put: self next].
  41607.     ^newArray!
  41608. originalContents
  41609.     "Answer the receiver's actual contents collection, NOT a copy.  1/29/96 sw"
  41610.  
  41611.     ^ collection!
  41612. peek
  41613.     "Answer what would be returned if the message next were sent to the 
  41614.     receiver. If the receiver is at the end, answer nil."
  41615.  
  41616.     | nextObject |
  41617.     self atEnd ifTrue: [^nil].
  41618.     nextObject _ self next.
  41619.     position _ position - 1.
  41620.     ^nextObject!
  41621. peekFor: anObject 
  41622.     "Answer false and do not move over the next element if it is not equal to 
  41623.     the argument, anObject, or if the receiver is at the end. Answer true 
  41624.     and increment the position for accessing elements, if the next element is 
  41625.     equal to anObject."
  41626.  
  41627.     | nextObject |
  41628.     self atEnd ifTrue: [^false].
  41629.     nextObject _ self next.
  41630.     "peek for matching element"
  41631.     anObject = nextObject ifTrue: [^true].
  41632.     "gobble it if found"
  41633.     position _ position - 1.
  41634.     ^false!
  41635. reverseContents
  41636.     "Answer a copy of the receiver's contents, in reverse order."
  41637.  
  41638.     | size j newCollection |
  41639.     size _ j _ collection size.
  41640.     newCollection _ collection species new: size.
  41641.     1 to: size do: [:i | newCollection at: i put: (collection at: j). j _ j - 1].
  41642.     ^newCollection!
  41643. upTo: anObject 
  41644.     "Answer a subcollection from the current access position to the 
  41645.     occurrence (if any, but not inclusive) of anObject in the receiver. If 
  41646.     anObject is not in the collection, answer the entire rest of the receiver."
  41647.     | newStream element |
  41648.     newStream _ WriteStream on: (collection species new: 100).
  41649.     [self atEnd or: [(element _ self next) = anObject]]
  41650.         whileFalse: [newStream nextPut: element].
  41651.     ^newStream contents! !
  41652.  
  41653. !PositionableStream methodsFor: 'testing'!
  41654. atEnd
  41655.     "Primitive. Answer whether the receiver can access any more objects.
  41656.     Optional. See Object documentation whatIsAPrimitive."
  41657.  
  41658.     <primitive: 67>
  41659.     ^position >= readLimit!
  41660. isEmpty
  41661.     "Answer whether the receiver's contents has no elements."
  41662.  
  41663.     ^position = 0! !
  41664.  
  41665. !PositionableStream methodsFor: 'positioning'!
  41666. position
  41667.     "Answer the current position of accessing the sequence of objects."
  41668.  
  41669.     ^position!
  41670. position: anInteger 
  41671.     "Set the current position for accessing the objects to be anInteger, as long 
  41672.     as anInteger is within the bounds of the receiver's contents. If it is not, 
  41673.     create an error notification."
  41674.  
  41675.     anInteger >= 0 & (anInteger <= readLimit)
  41676.         ifTrue: [position _ anInteger]
  41677.         ifFalse: [self positionError]!
  41678. reset
  41679.     "Set the receiver's position to the beginning of the sequence of objects."
  41680.  
  41681.     position _ 0!
  41682. setToEnd
  41683.     "Set the position of the receiver to the end of the sequence of objects."
  41684.  
  41685.     position _ readLimit!
  41686. skip: anInteger 
  41687.     "Set the receiver's position to be the current position+anInteger. A 
  41688.     subclass might choose to be more helpful and select the minimum of the 
  41689.     receiver's size and position+anInteger, or the maximum of 1 and 
  41690.     position+anInteger for the repositioning."
  41691.  
  41692.     self position: position + anInteger!
  41693. skipTo: anObject 
  41694.     "Set the access position of the receiver to be past the next occurrence of 
  41695.     anObject. Answer whether anObject is found."
  41696.  
  41697.     [self atEnd]
  41698.         whileFalse: [self next = anObject ifTrue: [^true]].
  41699.     ^false! !
  41700.  
  41701. !PositionableStream methodsFor: 'fileIn/Out'!
  41702. command: aString
  41703.     "Overridden by HtmlFileStream to append commands directly without translation.  4/5/96 tk"
  41704.     "We ignore any HTML commands.  Do nothing"!
  41705. copyChunkTo: aWriteStream
  41706.     "Copy the next chunk onto aWriteStream (must be different from the receiver).  If HTML, bold the selector in a cheating way. 
  41707.     4/11/96 tk"
  41708.     | terminator text parser where start sel |
  41709.     terminator _ $!!.
  41710.     self skipSeparators.
  41711.     start _ self position.
  41712.     sel _ self upTo: Character cr.
  41713.     self position: start.
  41714.     text _ self upTo: terminator.
  41715.     text size < sel size 
  41716.         ifTrue: ["oops!! no cr"
  41717.             aWriteStream nextPutAll: text; nextPut: terminator]
  41718.         ifFalse: ["bold the method header"
  41719.             aWriteStream command: 'b'.
  41720.             aWriteStream nextPutAll: sel.
  41721.             aWriteStream command: '/b'.
  41722.             aWriteStream nextPutAll: 
  41723.                 (text copyFrom: sel size + 1 to: text size).
  41724.             aWriteStream nextPut: terminator].
  41725.     [self peekFor: terminator] whileTrue:   "case of imbedded (doubled) terminator"
  41726.             [aWriteStream nextPut: terminator;
  41727.                 nextPutAll: (self upTo: terminator);
  41728.                 nextPut: terminator].!
  41729. header
  41730.     "If the stream requires a standard header, override this message.  See HtmlFileStream"!
  41731. nextChunk
  41732.     "Answer the contents of the receiver, up to the next terminator character.
  41733.     Imbedded terminators are doubled."
  41734.     | terminator segment |
  41735.     terminator _ $!!.
  41736.     self skipSeparators.
  41737.     segment _ self upTo: terminator.
  41738.     [self peekFor: terminator] whileTrue:   "case of imbedded (doubled) terminator"
  41739.             [segment _ (segment copyWith: terminator) , (self upTo: terminator)].
  41740.     ^ segment!
  41741. skipSeparators
  41742.     [self atEnd == false and: [self peek isSeparator]]
  41743.         whileTrue: [self next]!
  41744. trailer
  41745.     "If the stream requires a standard trailer, override this message.  See HtmlFileStream"!
  41746. unCommand
  41747.     "If this read stream is at a <, then skip up to just after the next >.  For removing html commands."
  41748.     | char |
  41749.     [self peek = $<] whileTrue: ["begin a block"
  41750.         [self atEnd == false and: [self next ~= $>]] whileTrue.
  41751.         "absorb characters"
  41752.         ].
  41753.  !
  41754. verbatim: aString
  41755.     "Do not attempt to translate the characters.  Use to override nextPutAll:"
  41756.     ^ self nextPutAll: aString! !
  41757.  
  41758. !PositionableStream methodsFor: 'private'!
  41759. on: aCollection
  41760.  
  41761.     collection _ aCollection.
  41762.     readLimit _ aCollection size.
  41763.     position _ 0.
  41764.     self reset!
  41765. positionError
  41766.     "Since I am not necessarily writable, it is up to my subclasses to override 
  41767.     position: if expanding the collection is preferrable to giving this error."
  41768.  
  41769.     self error: 'Attempt to set the position of a PositionableStream out of bounds'!
  41770. setFrom: newStart to: newStop
  41771.  
  41772.     position _ newStart - 1.
  41773.     readLimit _ newStop! !
  41774. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  41775.  
  41776. PositionableStream class
  41777.     instanceVariableNames: ''!
  41778.  
  41779. !PositionableStream class methodsFor: 'instance creation'!
  41780. on: aCollection 
  41781.     "Answer an instance of me, streaming over the elements of aCollection."
  41782.  
  41783.     ^self basicNew on: aCollection!
  41784. on: aCollection from: firstIndex to: lastIndex 
  41785.     "Answer an instance of me, streaming over the elements of aCollection 
  41786.     starting with the element at firstIndex and ending with the one at 
  41787.     lastIndex."
  41788.  
  41789.     ^self basicNew on: (aCollection copyFrom: firstIndex to: lastIndex)! !Object subclass: #Preferences
  41790.     instanceVariableNames: ''
  41791.     classVariableNames: 'FlagDictionary '
  41792.     poolDictionaries: ''
  41793.     category: 'System-Support'!
  41794.  
  41795. !Preferences methodsFor: 'no messages'! !
  41796. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  41797.  
  41798. Preferences class
  41799.     instanceVariableNames: ''!
  41800. Preferences class comment:
  41801. 'A general mechanism to store preference choices.  The default setup treats any symbol as a potential boolean flag; flags unknown to the preference dictionary are always returned as false.  It is also possible to store non-boolean data in the preference table.  sw 8/91'!
  41802.  
  41803. !Preferences class methodsFor: 'hard-coded prefs'!
  41804. startLoggingUserScripts
  41805.     "Execute this to set the system to start logging user scripts to the changes log.  7/18/96 sw"
  41806.     "Preferences startLoggingUserScripts"
  41807.  
  41808.     Preferences class compile:
  41809. 'logUserScripts
  41810.     "Set to true if you want user scripts logged; later, we will maybe have a better way to specify this, or do something better altogether"
  41811.  
  41812.     ^ true' classified: 'logging'!
  41813. stopLoggingUserScripts
  41814.     "Execute this to set the system to stop logging user scripts to the changes log.  7/18/96 sw"
  41815.     "Preferences stopLoggingUserScripts"
  41816.  
  41817.     Preferences class compile:
  41818. 'logUserScripts
  41819.     "Set to true if you want user scripts logged; later, we will maybe have a better way to specify this, or do something better altogether"
  41820.  
  41821.     ^ false' classified: 'logging'! !
  41822.  
  41823. !Preferences class methodsFor: 'general'!
  41824. chooseInitialSettings
  41825.     "Set up the initial choices for Preferences.  2/7/96 sw
  41826.      5/2/96 sw: added init for uniformWindowColors
  41827.      5/22/96 sw: init reverseWindowStagger, clear out old window parms"
  41828.  
  41829.     "Preferences chooseInitialSettings"
  41830.  
  41831.     self setPreference: #uniformWindowColors toValue: false.
  41832.     self setPreference: #reverseWindowStagger toValue: false.
  41833.     self setPreference: #programmerMode toValue: false.
  41834.     
  41835. !
  41836. doesNotUnderstand: aMessage
  41837.     ^ self valueOfFlag: aMessage selector!
  41838. initialize
  41839.     "5/22/96 sw: Included within a 22 May96 fileout to trigger reinitialization"
  41840.  
  41841.     FlagDictionary _ Dictionary new.
  41842.     self chooseInitialSettings
  41843.  
  41844.     "Preferences initialize"!
  41845. openPreferencesInspector
  41846.     "Open a window on the current Preferences, allowing the user to see current settings and to change them.  2/7/96 sw"
  41847.     "Preferences openPreferencesInspector"
  41848.  
  41849.     FlagDictionary inspectWithLabel: 'Preferences'!
  41850. setPreference: preferenceNameSymbol toValue: aBoolean
  41851.     FlagDictionary at: preferenceNameSymbol put: aBoolean!
  41852. valueOfFlag: aFlagName
  41853.     ^ FlagDictionary at: aFlagName ifAbsent: [false]! !
  41854.  
  41855. !Preferences class methodsFor: 'logging'!
  41856. logUserScripts
  41857.     "Set to true if you want user scripts logged; later, we will maybe have a better way to specify this, or do something better altogether"
  41858.  
  41859.     ^ false! !
  41860.  
  41861. Preferences initialize!
  41862. Link subclass: #Process
  41863.     instanceVariableNames: 'suspendedContext priority myList errorHandler '
  41864.     classVariableNames: ''
  41865.     poolDictionaries: ''
  41866.     category: 'Kernel-Processes'!
  41867. Process comment:
  41868. 'I represent an independent path of control in the system. This path of control may be stopped (by sending the message suspend) in such a way that it can later be restarted (by sending the message resume). When any one of several paths of control can be advanced, the single instance of ProcessorScheduler named Processor determines which one will actually be advanced partly using the value of priority.'!
  41869.  
  41870. !Process methodsFor: 'changing process state'!
  41871. resume
  41872.     "Primitive. Allow the process that the receiver represents to continue. Put 
  41873.     the receiver in line to become the activeProcess. Fail if the receiver is 
  41874.     already waiting in a queue (in a Semaphore or ProcessScheduler). 
  41875.     Essential. See Object documentation whatIsAPrimitive."
  41876.  
  41877.     <primitive: 87>
  41878.     self primitiveFailed!
  41879. suspend
  41880.     "Primitive. Stop the process that the receiver represents in such a way 
  41881.     that it can be restarted at a later time (by sending the receiver the 
  41882.     message resume). If the receiver represents the activeProcess, suspend it. 
  41883.     Otherwise fail and the code below will remove the receiver from the list 
  41884.     of waiting processes. Essential. See Object documentation 
  41885.     whatIsAPrimitive."
  41886.  
  41887.     <primitive: 88>
  41888.     Processor activeProcess == self
  41889.         ifTrue: [self primitiveFailed]
  41890.         ifFalse: 
  41891.             [Processor remove: self ifAbsent: [self error: 'This process was not active'].
  41892.             myList _ nil]!
  41893. terminate 
  41894.     "Stop the process that the receiver represents forever."
  41895.  
  41896.     | context |
  41897.     Processor activeProcess == self
  41898.         ifTrue: 
  41899.             [thisContext sender == nil ifFalse:
  41900.                 [thisContext sender release].
  41901.             thisContext removeSelf suspend]
  41902.         ifFalse: 
  41903.             [myList == nil
  41904.                 ifFalse: 
  41905.                     [myList remove: self ifAbsent: [].
  41906.                     myList _ nil].
  41907.             context _ suspendedContext.
  41908.             suspendedContext _ nil.
  41909.             (context ~~ nil and: [context sender ~~ nil])
  41910.                 ifTrue: [context sender release]]! !
  41911.  
  41912. !Process methodsFor: 'changing suspended state'!
  41913. install: aContext 
  41914.     "Replace the suspendedContext with aContext."
  41915.  
  41916.     self == Processor activeProcess
  41917.         ifTrue: [^self error: 'The active process cannot install contexts'].
  41918.     suspendedContext _ aContext!
  41919. popTo: aContext 
  41920.     "Replace the suspendedContext with aContext, releasing all contexts 
  41921.     between the currently suspendedContext and it."
  41922.  
  41923.     self == Processor activeProcess
  41924.         ifTrue: [^self error: 'The active process cannot pop contexts'].
  41925.     suspendedContext releaseTo: aContext.
  41926.     suspendedContext _ aContext! !
  41927.  
  41928. !Process methodsFor: 'accessing'!
  41929. offList
  41930.     "Inform the receiver that it has been taken off a list that it was 
  41931.     suspended on. This is to break a backpointer."
  41932.  
  41933.     myList _ nil!
  41934. priority
  41935.     "Answer the priority of the receiver."
  41936.  
  41937.     ^priority!
  41938. priority: anInteger 
  41939.     "Set the receiver's priority to anInteger."
  41940.  
  41941.     anInteger<=Processor highestPriority
  41942.         ifTrue: [priority _ anInteger]
  41943.         ifFalse: [self error: 'priority too high']!
  41944. suspendedContext
  41945.     "Answer the context the receiver has suspended."
  41946.  
  41947.     ^suspendedContext!
  41948. suspendingList
  41949.     "Answer the list on which the receiver has been suspended."
  41950.  
  41951.     ^myList! !
  41952.  
  41953. !Process methodsFor: 'printing'!
  41954. printOn: aStream
  41955.  
  41956.     super printOn: aStream.
  41957.     aStream nextPutAll: ' in '.
  41958.     suspendedContext printOn: aStream! !
  41959.  
  41960. !Process methodsFor: 'private'!
  41961. suspendedContext: aContext
  41962.  
  41963.     suspendedContext _ aContext! !
  41964.  
  41965. !Process methodsFor: 'error handling'!
  41966. errorHandler
  41967.     ^ errorHandler!
  41968. errorHandler: aBlock
  41969.     errorHandler _ aBlock!
  41970. isErrorHandled
  41971.     ^ errorHandler notNil! !
  41972. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  41973.  
  41974. Process class
  41975.     instanceVariableNames: ''!
  41976.  
  41977. !Process class methodsFor: 'instance creation'!
  41978. forContext: aContext priority: anInteger 
  41979.     "Answer an instance of me that has suspended aContext at priority 
  41980.     anInteger."
  41981.  
  41982.     | newProcess |
  41983.     newProcess _ self new.
  41984.     newProcess suspendedContext: aContext.
  41985.     newProcess priority: anInteger.
  41986.     ^newProcess! !Object subclass: #ProcessorScheduler
  41987.     instanceVariableNames: 'quiescentProcessLists activeProcess '
  41988.     classVariableNames: 'UserBackgroundPriority UserSchedulingPriority TimingPriority SystemBackgroundPriority BackgroundProcess SystemRockBottomPriority HighIOPriority LowIOPriority UserInterruptPriority '
  41989.     poolDictionaries: ''
  41990.     category: 'Kernel-Processes'!
  41991. ProcessorScheduler comment:
  41992. 'My single instance, named Processor, coordinates the use of the physical processor by all Processes requiring service.'!
  41993.  
  41994. !ProcessorScheduler methodsFor: 'accessing'!
  41995. activePriority
  41996.     "Answer the priority level of the currently running Process."
  41997.  
  41998.     ^activeProcess priority!
  41999. activeProcess
  42000.     "Answer the currently running Process."
  42001.  
  42002.     ^activeProcess!
  42003. highestPriority
  42004.     "Answer the number of priority levels currently available for use."
  42005.  
  42006.     ^quiescentProcessLists size!
  42007. highestPriority: newHighestPriority
  42008.     "Change the number of priority levels currently available for use."
  42009.  
  42010.     | continue newProcessLists |
  42011.     (quiescentProcessLists size > newHighestPriority
  42012.         and: [self anyProcessesAbove: newHighestPriority])
  42013.             ifTrue: [self error: 'There are processes with priority higher than '
  42014.                                                     ,newHighestPriority printString].
  42015.     newProcessLists _ Array new: newHighestPriority.
  42016.     1 to: ((quiescentProcessLists size) min: (newProcessLists size)) do: 
  42017.         [:priority | newProcessLists at: priority put: (quiescentProcessLists at: priority)].
  42018.     quiescentProcessLists size to: newProcessLists size do: 
  42019.         [:priority | newProcessLists at: priority put: LinkedList new].
  42020.     quiescentProcessLists _ newProcessLists! !
  42021.  
  42022. !ProcessorScheduler methodsFor: 'removing'!
  42023. remove: aProcess ifAbsent: aBlock 
  42024.     "Remove aProcess from the list on which it is waiting for the processor 
  42025.     and answer aProcess. If it is not waiting, evaluate aBlock."
  42026.  
  42027.     (quiescentProcessLists at: aProcess priority)
  42028.         remove: aProcess ifAbsent: aBlock.
  42029.     ^aProcess! !
  42030.  
  42031. !ProcessorScheduler methodsFor: 'process state change'!
  42032. suspendFirstAt: aPriority 
  42033.     "Suspend the first Process that is waiting to run with priority aPriority."
  42034.  
  42035.     ^self suspendFirstAt: aPriority
  42036.           ifNone: [self error: 'No Process to suspend']!
  42037. suspendFirstAt: aPriority ifNone: noneBlock 
  42038.     "Suspend the first Process that is waiting to run with priority aPriority. If 
  42039.     no Process is waiting, evaluate the argument, noneBlock."
  42040.  
  42041.     | aList |
  42042.     aList _ quiescentProcessLists at: aPriority.
  42043.     aList isEmpty
  42044.         ifTrue: [^noneBlock value]
  42045.         ifFalse: [^aList first suspend]!
  42046. terminateActive
  42047.     "Terminate the process that is currently running."
  42048.  
  42049.     activeProcess terminate!
  42050. yield
  42051.     "Give other Processes at the current priority a chance to run."
  42052.  
  42053.     | semaphore |
  42054.     semaphore _ Semaphore new.
  42055.     [semaphore signal] fork.
  42056.     semaphore wait! !
  42057.  
  42058. !ProcessorScheduler methodsFor: 'timing'!
  42059. signal: aSemaphore atTime: signalTime 
  42060.     "Signal aSemaphore when the system's millisecond clock reaches 
  42061.     the given time (an Integer)."
  42062.  
  42063.     ^self signal: aSemaphore atMilliseconds: signalTime! !
  42064.  
  42065. !ProcessorScheduler methodsFor: 'priority names'!
  42066. highIOPriority
  42067.     "Answer the priority at which the most time critical input/output 
  42068.     processes should run. An example is the process handling input from a 
  42069.     network."
  42070.  
  42071.     ^HighIOPriority!
  42072. lowIOPriority
  42073.     "Answer the priority at which most input/output processes should run. 
  42074.     Examples are the process handling input from the user (keyboard, 
  42075.     pointing device, etc.) and the process distributing input from a network."
  42076.  
  42077.     ^LowIOPriority!
  42078. systemBackgroundPriority
  42079.     "Answer the priority at which system background processes should run. 
  42080.     Examples are an incremental garbage collector or status checker."
  42081.  
  42082.     ^SystemBackgroundPriority!
  42083. timingPriority
  42084.     "Answer the priority at which the system processes keeping track of real 
  42085.     time should run."
  42086.  
  42087.     ^TimingPriority!
  42088. userBackgroundPriority
  42089.     "Answer the priority at which user background processes should run."
  42090.  
  42091.     ^UserBackgroundPriority!
  42092. userInterruptPriority
  42093.     "Answer the priority at which user processes desiring immediate service 
  42094.     should run. Processes run at this level will preempt the window 
  42095.     scheduler and should, therefore, not consume the processor forever."
  42096.  
  42097.     ^UserInterruptPriority!
  42098. userSchedulingPriority
  42099.     "Answer the priority at which the window scheduler should run."
  42100.  
  42101.     ^UserSchedulingPriority! !
  42102.  
  42103. !ProcessorScheduler methodsFor: 'private'!
  42104. anyProcessesAbove: highestPriority 
  42105.     "Do any instances of Process exist with higher priorities?"
  42106.  
  42107.     ^(Process allInstances select: [:aProcess | aProcess priority > highestPriority]) isEmpty!
  42108. signal: aSemaphore atMilliseconds: milliseconds
  42109.     "Signal the semaphore when the millisecond clock reaches the value of 
  42110.     the second argument. Fail if the first argument is neither a Semaphore
  42111.     nor nil.  Essential.  See Object documentation whatIsAPrimitive."
  42112.  
  42113.     <primitive: 136>
  42114.     self primitiveFailed! !
  42115. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  42116.  
  42117. ProcessorScheduler class
  42118.     instanceVariableNames: ''!
  42119.  
  42120. !ProcessorScheduler class methodsFor: 'class initialization'!
  42121. initialize
  42122.      
  42123.     SystemRockBottomPriority _ 1.
  42124.     SystemBackgroundPriority _ 2.
  42125.     UserBackgroundPriority _ 3.
  42126.     UserSchedulingPriority _ 4.
  42127.     UserInterruptPriority _ 5.
  42128.     LowIOPriority _ 6.
  42129.     HighIOPriority _ 7.
  42130.     TimingPriority _ 8
  42131.  
  42132.     "ProcessorScheduler initialize."! !
  42133.  
  42134. !ProcessorScheduler class methodsFor: 'instance creation'!
  42135. new
  42136.     "New instances of ProcessorScheduler should not be created."
  42137.  
  42138.     self error:
  42139. 'New ProcessSchedulers should not be created since
  42140. the integrity of the system depends on a unique scheduler'! !
  42141.  
  42142. !ProcessorScheduler class methodsFor: 'background process'!
  42143. background: aBlock 
  42144.     "Replace the background process with a process running the code in 
  42145.     aBlock."
  42146.  
  42147.     BackgroundProcess == nil ifFalse: [BackgroundProcess terminate].
  42148.     BackgroundProcess _ aBlock newProcess.
  42149.     BackgroundProcess priority: SystemRockBottomPriority.
  42150.     BackgroundProcess resume!
  42151. hiddenBackgroundProcess
  42152.     "Install a default background process which is invisible."
  42153.  
  42154.     self background:
  42155.         [[true] whileTrue: []]!
  42156. sweepHandBackgroundProcess
  42157.     "Install a default background process which shows a sweeping circle of 
  42158.     XOR-ed bits on the screen."
  42159.  
  42160.     | sweepHand |
  42161.     sweepHand _ Pen new.
  42162.     sweepHand defaultNib: 2.
  42163.     sweepHand combinationRule: 6.
  42164.     self background:
  42165.         [[true]
  42166.             whileTrue: [2 timesRepeat: 
  42167.                             [sweepHand north.
  42168.                             36 timesRepeat: 
  42169.                                 [sweepHand place: Display boundingBox topRight + (-25@25).
  42170.                                 sweepHand go: 20.
  42171.                                 sweepHand turn: 10]]]]! !
  42172.  
  42173. ProcessorScheduler initialize!
  42174. Model subclass: #Project
  42175.     instanceVariableNames: 'projectWindows projectChangeSet projectTranscript projectHolder displayDepth '
  42176.     classVariableNames: 'CurrentProject '
  42177.     poolDictionaries: ''
  42178.     category: 'Interface-Projects'!
  42179. Project comment:
  42180. 'Each screen is a manifestation of a project. Each project manages the scheduled views in it. While the user is working in the project, the changes made to classes are collected; a system-wide set of changes is the collection of all project changes. As a StringHolder, the string to be viewed is a description of the project.'!
  42181.  
  42182. !Project methodsFor: 'initialization'!
  42183. defaultBackgroundColor
  42184.     ^ #lightOrange!
  42185. initialExtent
  42186.     ^ (Display extent // 6) + (0@17)!
  42187. initialProject
  42188.     self saveState.
  42189.     projectHolder _ self!
  42190. setChangeSet: aChangeSet
  42191.  
  42192.     projectChangeSet _ aChangeSet
  42193. !
  42194. setProjectHolder: aProject
  42195.  
  42196.     projectWindows _ ControlManager new.
  42197.     projectChangeSet _ ChangeSet new initialize.
  42198.     projectTranscript _ TextCollector new.
  42199.     displayDepth _ Display depth.
  42200.     projectHolder _ aProject! !
  42201.  
  42202. !Project methodsFor: 'accessing'!
  42203. isTopProject
  42204.     "Return true only of this is the top project (its own holder)"
  42205.     ^ projectHolder == self!
  42206. name
  42207.     ^ projectChangeSet name!
  42208. projectChangeSet
  42209.     ^ projectChangeSet!
  42210. views
  42211.     | sc |
  42212.     sc _ projectWindows screenController.
  42213.     ^ projectWindows scheduledControllers 
  42214.         select: [:c | c ~~ sc]
  42215.         thenCollect: [:c | c view]! !
  42216.  
  42217. !Project methodsFor: 'menu messages'!
  42218. enter
  42219.     "The user has chosen to change the context of the workspace to be that of 
  42220.     the receiver. Change the ChangeSet, Transcript, and collection of 
  42221.     scheduled views accordingly."
  42222.  
  42223.     CurrentProject saveState.
  42224.     CurrentProject _ self.
  42225.     Smalltalk newChanges: projectChangeSet.
  42226.     TextCollector newTranscript: projectTranscript.
  42227.     displayDepth == nil ifTrue: [displayDepth _ Display depth].
  42228.     Display newDepthNoRestore: displayDepth.
  42229.     ControlManager newScheduler: projectWindows!
  42230. exit
  42231.     "Leave the current project and return to the project
  42232.     in which this one was created."
  42233.  
  42234.     projectHolder enter!
  42235. fileOut
  42236.     projectChangeSet fileOut!
  42237. saveState
  42238.     "Save the current state in me prior to switching projects"
  42239.  
  42240.     projectWindows _ ScheduledControllers.
  42241.     projectChangeSet _ Smalltalk changes.
  42242.     projectTranscript _ Transcript.
  42243.     displayDepth _ Display depth.
  42244. ! !
  42245.  
  42246. !Project methodsFor: 'release'!
  42247. okToChange
  42248.     ^ PopUpMenu confirm: 'Are you sure you have saved
  42249. all changes that you care about
  42250. in ' , self name printString!
  42251. release
  42252.     projectWindows == nil ifFalse:
  42253.         [projectWindows release.
  42254.         projectWindows _ nil].
  42255.     ^ super release!
  42256. removeDependent: aDependent
  42257.     super removeDependent: aDependent.
  42258.     self dependents isEmpty ifTrue: [self release]! !
  42259.  
  42260. !Project methodsFor: 'lock access'! !
  42261. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  42262.  
  42263. Project class
  42264.     instanceVariableNames: ''!
  42265.  
  42266. !Project class methodsFor: 'class initialization'!
  42267. initialize
  42268.     "This is the Top Project."   
  42269.  
  42270.     CurrentProject _ super new initialProject
  42271.  
  42272.     "Project initialize"! !
  42273.  
  42274. !Project class methodsFor: 'instance creation'!
  42275. new
  42276.  
  42277.     ^ super new setProjectHolder: CurrentProject!
  42278. newWithChangeSet: changeSet
  42279.  
  42280.     ^ self new setChangeSet: changeSet! !
  42281.  
  42282. !Project class methodsFor: 'constants'!
  42283. current
  42284.     "Answer the project that is currently being used."
  42285.  
  42286.     ^CurrentProject! !
  42287.  
  42288. Project initialize!
  42289. StandardSystemController subclass: #ProjectController
  42290.     instanceVariableNames: ''
  42291.     classVariableNames: ''
  42292.     poolDictionaries: ''
  42293.     category: 'Interface-Projects'!
  42294.  
  42295. !ProjectController methodsFor: 'control activity'!
  42296. redButtonActivity
  42297.     | index |
  42298.     view isCollapsed ifTrue: [^ super redButtonActivity].
  42299.     (view insetDisplayBox containsPoint: Sensor cursorPoint)
  42300.         ifFalse: [^ super redButtonActivity].
  42301.     index _ (PopUpMenu labelArray: #('enter' 'fileOut') lines: #(1)) 
  42302.         startUpCenteredWithCaption: nil.
  42303.     index = 1 ifTrue: [^ model enter].
  42304.     index = 2 ifTrue: [^ model fileOut].
  42305. ! !StandardSystemView subclass: #ProjectView
  42306.     instanceVariableNames: ''
  42307.     classVariableNames: ''
  42308.     poolDictionaries: ''
  42309.     category: 'Interface-Projects'!
  42310.  
  42311. !ProjectView methodsFor: 'initialization'!
  42312. defaultControllerClass
  42313.     ^ ProjectController!
  42314. relabel: newLabel
  42315.     (newLabel isEmpty or: [newLabel = self label])
  42316.         ifTrue: [^ self].
  42317.     (ChangeSorter changeSetNamed: newLabel) == nil
  42318.         ifFalse: [self inform: 'Sorry that name is already used'.
  42319.                 ^ self].
  42320.     model projectChangeSet name: newLabel.
  42321.     super relabel: newLabel! !
  42322.  
  42323. !ProjectView methodsFor: 'displaying'!
  42324. cacheBitsAsTwoTone
  42325.     ^ false!
  42326. displayView
  42327.     | scale rect topLeft |
  42328.     super displayView.
  42329.     self label = model name
  42330.         ifFalse: [super relabel: model name].
  42331.     self isCollapsed ifTrue: [^ self].
  42332.     Display fill: self insetDisplayBox fillColor: Color lightGray.
  42333.     scale _ self insetDisplayBox extent / Display extent.
  42334.     topLeft _ self insetDisplayBox topLeft.
  42335.     model views reverseDo:
  42336.         [:v | rect _ (v displayBox scaleBy: scale) rounded
  42337.                 translateBy: topLeft.
  42338.         Display fill: rect fillColor: v backgroundColor;
  42339.             border: rect width: 1;
  42340.             border: (rect topLeft extent: rect width@3) width: 1.
  42341.         ]! !
  42342. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  42343.  
  42344. ProjectView class
  42345.     instanceVariableNames: ''!
  42346.  
  42347. !ProjectView class methodsFor: 'as yet unclassified'!
  42348. open: aProject 
  42349.     "Answer an instance of me for the argument, aProject. It is created on the
  42350.     display screen."
  42351.     | topView |
  42352.     topView _ self new model: aProject.
  42353.     topView minimumSize: 50 @ 30.
  42354.     topView borderWidth: 2.
  42355.     topView controller open! !Rectangle subclass: #Quadrangle
  42356.     instanceVariableNames: 'borderWidth borderColor insideColor '
  42357.     classVariableNames: ''
  42358.     poolDictionaries: ''
  42359.     category: 'Graphics-Primitives'!
  42360. Quadrangle comment:
  42361. 'I represent a particular kind of Rectangle that has a border and inside color.'!
  42362.  
  42363. !Quadrangle methodsFor: 'initialize-release'!
  42364. initialize
  42365.     "Initialize the region to a null Rectangle, the borderWidth to 1, the 
  42366.     borderColor to black, and the insideColor to white."
  42367.  
  42368.     origin _ 0 @ 0.
  42369.     corner _ 0 @ 0.
  42370.     borderWidth _ 1.
  42371.     borderColor _ Display black.
  42372.     insideColor _ Display white! !
  42373.  
  42374. !Quadrangle methodsFor: 'bordering'!
  42375. borderColor
  42376.     "Answer the form that is the borderColor of the receiver."
  42377.  
  42378.     ^borderColor!
  42379. borderColor: aColor 
  42380.     "Set the borderColor of the receiver to aColor, a Form."
  42381.  
  42382.     borderColor _ aColor!
  42383. borderWidth
  42384.     "Answer the borderWidth of the receiver."
  42385.  
  42386.     ^borderWidth!
  42387. borderWidth: anInteger 
  42388.     "Set the borderWidth of the receiver to anInteger."
  42389.  
  42390.     borderWidth _ anInteger!
  42391. borderWidthLeft: anInteger1 right: anInteger2 top: anInteger3 bottom: anInteger4
  42392.     "Set the border width of the receiver to a Rectangle that represents the 
  42393.     left, right, top, and bottom border widths."
  42394.  
  42395.     borderWidth _ anInteger1 @ anInteger3 corner: anInteger2 @ anInteger4!
  42396. inside
  42397.     "Answer a Rectangle that is the receiver inset by the borderWidth."
  42398.  
  42399.     ^self insetBy: borderWidth!
  42400. insideColor
  42401.     "Answer the form that is the insideColor of the receiver."
  42402.  
  42403.     ^insideColor!
  42404. insideColor: aColor 
  42405.     "Set the insideColor of the receiver to aColor, a Form."
  42406.  
  42407.     insideColor _ aColor!
  42408. region
  42409.     "Answer a Rectangle that defines the area of the receiver."
  42410.  
  42411.     ^origin corner: corner!
  42412. region: aRectangle 
  42413.     "Set the rectangular area of the receiver to aRectangle."
  42414.  
  42415.     origin _ aRectangle origin.
  42416.     corner _ aRectangle corner! !
  42417.  
  42418. !Quadrangle methodsFor: 'rectangle functions'!
  42419. intersect: aRectangle 
  42420.     "Answer a new Quadrangle whose region is the intersection of the 
  42421.     receiver's area and aRectangle.
  42422.      5/24/96 sw: removed hard-coded class name so subclasses can gain same functionality."
  42423.  
  42424.     ^ self class
  42425.          region: (super intersect: aRectangle)
  42426.         borderWidth: borderWidth
  42427.         borderColor: borderColor
  42428.         insideColor: insideColor! !
  42429.  
  42430. !Quadrangle methodsFor: 'transforming'!
  42431. align: aPoint1 with: aPoint2 
  42432.     "Answer a new Quadrangle translated by aPoint2 - aPoint1.
  42433.      5/24/96 sw: removed hard-coded class name so subclasses can gain same functionality."
  42434.  
  42435.     ^ self class
  42436.         region: (super translateBy: aPoint2 - aPoint1)
  42437.         borderWidth: borderWidth
  42438.         borderColor: borderColor
  42439.         insideColor: insideColor!
  42440. alignedTo: alignPointSelector
  42441.     "Return a copy with offset according to alignPointSelector which is one of...
  42442.     #(topLeft, topCenter, topRight, leftCenter, center, etc)
  42443.      5/24/96 sw: removed hard-coded class name so subclasses can gain same functionality."
  42444.  
  42445.     ^ self class
  42446.         region: (super translateBy: (0@0) - (self perform: alignPointSelector))
  42447.         borderWidth: borderWidth
  42448.         borderColor: borderColor
  42449.         insideColor: insideColor!
  42450. scaleBy: aPoint 
  42451.     "Answer a new Quadrangle scaled by aPoint.
  42452.      5/24/96 sw: removed hard-coded class name so subclasses can gain same functionality."
  42453.  
  42454.     ^ self class
  42455.         region: (super scaleBy: aPoint)
  42456.         borderWidth: borderWidth
  42457.         borderColor: borderColor
  42458.         insideColor: insideColor!
  42459. translateBy: aPoint 
  42460.     "Answer a new Quadrangle translated by aPoint.
  42461.      5/24/96 sw: removed hard-coded class name so subclasses can gain same functionality."
  42462.  
  42463.     ^ self class
  42464.         region: (super translateBy: aPoint)
  42465.         borderWidth: borderWidth
  42466.         borderColor: borderColor
  42467.         insideColor: insideColor! !
  42468.  
  42469. !Quadrangle methodsFor: 'displaying-generic'!
  42470. displayOn: aDisplayMedium
  42471.     "Display the border and insideRegion of the receiver."
  42472.  
  42473.     borderWidth ~~ 0
  42474.         ifTrue:    [aDisplayMedium
  42475.                 border: self region
  42476.                 widthRectangle: borderWidth
  42477.                 rule: Form over
  42478.                 fillColor: borderColor].
  42479.     insideColor ~~ nil
  42480.         ifTrue:    [aDisplayMedium fill: self inside fillColor: insideColor]!
  42481. displayOn: aDisplayMedium align: aPoint1 with: aPoint2 clippingBox: aRectangle
  42482.     "Display the border and region of the receiver so that its position at 
  42483.     aPoint1 is aligned with position aPoint2. The displayed information 
  42484.     should be clipped so that only information with the area determined by 
  42485.     aRectangle is displayed."
  42486.  
  42487.     | savedRegion |
  42488.     savedRegion _ self region.
  42489.     self region: ((savedRegion align: aPoint1 with: aPoint2) intersect: aRectangle).
  42490.     self displayOn: aDisplayMedium.
  42491.     self region: savedRegion!
  42492. displayOn: aDisplayMedium transformation: aWindowingTransformation clippingBox: aRectangle
  42493.     "Display the border and region of the receiver so that it is scaled and 
  42494.     translated with respect to aWindowingTransformation. The displayed 
  42495.     information should be clipped so that only information with the area 
  42496.     determined by aRectangle is displayed."
  42497.  
  42498.     | screenRectangle |
  42499.     screenRectangle _ 
  42500.         (aWindowingTransformation applyTo: self) intersect: aRectangle.
  42501.     borderWidth ~~ 0 & (insideColor ~~ nil)
  42502.         ifTrue: 
  42503.             [aDisplayMedium fill: screenRectangle fillColor: Display black "borderColor".
  42504.             aDisplayMedium
  42505.                 fill: (screenRectangle insetBy: borderWidth)
  42506.                 fillColor: insideColor]!
  42507. displayOnPort: aPort at: p
  42508.     "Display the border and insideRegion of the receiver."
  42509.  
  42510.     (insideColor == nil or: [borderWidth <= 0])
  42511.         ifFalse: [aPort fill: (self region translateBy: p) 
  42512.             fillColor: borderColor rule: Form over].
  42513.     insideColor == nil
  42514.         ifFalse: [aPort fill: (self inside translateBy: p) 
  42515.             fillColor: insideColor rule: Form over]! !
  42516.  
  42517. !Quadrangle methodsFor: 'displaying-Display'!
  42518. display 
  42519.     "Display the border and insideRegion of the receiver on the Display."
  42520.  
  42521.     self displayOn: Display!
  42522. displayAlign: aPoint1 with: aPoint2 clippingBox: aRectangle 
  42523.     "Display the border and region of the receiver on the Display so that its 
  42524.     position at aPoint1 is aligned with position aPoint2. The displayed 
  42525.     information should be clipped so that only information with the area 
  42526.     determined by aRectangle is displayed." 
  42527.  
  42528.     self displayOn: Display align: aPoint1 with: aPoint2 clippingBox: aRectangle!
  42529. displayTransformation: aWindowingTransformation clippingBox: aRectangle 
  42530.     "Display the border and region of the receiver on the Display so that it 
  42531.     is scaled and translated with respect to aWindowingTransformation. The 
  42532.     displayed information should be clipped so that only information with 
  42533.     the area determined by aRectangle is displayed." 
  42534.  
  42535.     self displayOn: Display transformation: aWindowingTransformation clippingBox: aRectangle! !
  42536.  
  42537. !Quadrangle methodsFor: 'private'!
  42538. region: aRectangle borderWidth: anInteger borderColor: aMask1 insideColor: aMask2
  42539.  
  42540.     origin _ aRectangle origin.
  42541.     corner _ aRectangle corner.
  42542.     borderWidth _ anInteger.
  42543.     borderColor _ aMask1.
  42544.     insideColor _ aMask2! !
  42545. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  42546.  
  42547. Quadrangle class
  42548.     instanceVariableNames: ''!
  42549.  
  42550. !Quadrangle class methodsFor: 'instance creation'!
  42551. extent: extent color: aMask2
  42552.     "Answer an instance of me with no border."
  42553.     ^ self extent: extent color: aMask2 borderWidth: 0 borderColor: nil!
  42554. extent: extent color: aMask2 borderWidth: anInteger borderColor: aMask1
  42555.     "Answer an instance of me with rectangle, border width and color, and 
  42556.     inside color determined by the arguments."
  42557.  
  42558.     ^super new
  42559.         region: (0@0 corner: extent)
  42560.         borderWidth: anInteger
  42561.         borderColor: aMask1
  42562.         insideColor: aMask2!
  42563. new
  42564.     "Answer an instance of me, initialized to a null Rectangle, 
  42565.     with borderWidth of 1, borderColor of black, and insideColor of white."
  42566.  
  42567.     ^super new initialize!
  42568. region: aRectangle borderWidth: anInteger borderColor: aMask1 insideColor: aMask2
  42569.     "Answer an instance of me with rectangle, border width and color, and 
  42570.     inside color determined by the arguments."
  42571.  
  42572.     ^super new
  42573.         region: aRectangle
  42574.         borderWidth: anInteger
  42575.         borderColor: aMask1
  42576.         insideColor: aMask2! !Stream subclass: #Random
  42577.     instanceVariableNames: 'seed '
  42578.     classVariableNames: ''
  42579.     poolDictionaries: ''
  42580.     category: 'Numeric-Numbers'!
  42581. Random comment:
  42582. 'My instances are simple random number generators.'!
  42583.  
  42584. !Random methodsFor: 'accessing'!
  42585. contents
  42586.     ^self shouldNotImplement!
  42587. next
  42588.     "Answer with the next random number."
  42589.  
  42590.     | temp |
  42591.     [seed _ 13849 + (27181 * seed) bitAnd: 65535.
  42592.     0 = (temp _ seed / 65536.0)] whileTrue.
  42593.     ^temp!
  42594. nextPut: anObject
  42595.     ^self shouldNotImplement!
  42596. setSeed: data
  42597.     seed _ data! !
  42598.  
  42599. !Random methodsFor: 'testing'!
  42600. atEnd 
  42601.     "Refer to the comment in Stream|atEnd."
  42602.     ^false! !
  42603.  
  42604. !Random methodsFor: 'private'!
  42605. setSeed
  42606.     seed _ Time millisecondClockValue bitAnd: 65535
  42607.         "Time millisecondClockValue gives a large integer;  I only want the lower 16 bits."! !
  42608. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  42609.  
  42610. Random class
  42611.     instanceVariableNames: ''!
  42612.  
  42613. !Random class methodsFor: 'instance creation'!
  42614. new
  42615.     "Answer a new random number generator."
  42616.     ^self basicNew setSeed! !
  42617.  
  42618. !Random class methodsFor: 'examples'!
  42619. example
  42620.     "If you just want a quick random integer, use:
  42621.         10 atRandom
  42622.     Every integer interval can give a random number:
  42623.         (6 to: 12) atRandom
  42624.     Most Collections can give randomly selected elements:
  42625.         'pick one of these letters randomly' atRandom
  42626.  
  42627.     The correct way to use class Random is to store one in 
  42628.     an instance or class variable:
  42629.         myGenerator _ Random new.
  42630.     Then use it every time you need another number between 0.0 and 1.0
  42631.         myGenerator next
  42632.  
  42633.     "! !PositionableStream subclass: #ReadStream
  42634.     instanceVariableNames: ''
  42635.     classVariableNames: ''
  42636.     poolDictionaries: ''
  42637.     category: 'Collections-Streams'!
  42638. ReadStream comment:
  42639. 'I represent an accessor for a sequence of objects that can only read objects from the sequence.'!
  42640.  
  42641. !ReadStream methodsFor: 'accessing'!
  42642. next
  42643.     "Primitive. Answer the next object in the Stream represented by the
  42644.     receiver. Fail if the collection of this stream is not an Array or a String.
  42645.     Fail if the stream is positioned at its end, or if the position is out of
  42646.     bounds in the collection. Optional. See Object documentation
  42647.     whatIsAPrimitive."
  42648.  
  42649.     <primitive: 65>
  42650.     position >= readLimit
  42651.         ifTrue: [^nil]
  42652.         ifFalse: [^collection at: (position _ position + 1)]!
  42653. nextPut: anObject
  42654.  
  42655.     self shouldNotImplement! !
  42656.  
  42657. !ReadStream methodsFor: 'private'!
  42658. on: aCollection from: firstIndex to: lastIndex
  42659.  
  42660.     | len |
  42661.     collection _ aCollection.
  42662.     readLimit _  lastIndex > (len _ collection size)
  42663.                         ifTrue: [len]
  42664.                         ifFalse: [lastIndex].
  42665.     position _ firstIndex <= 1
  42666.                 ifTrue: [0]
  42667.                 ifFalse: [firstIndex - 1]! !
  42668. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  42669.  
  42670. ReadStream class
  42671.     instanceVariableNames: ''!
  42672.  
  42673. !ReadStream class methodsFor: 'instance creation'!
  42674. on: aCollection from: firstIndex to: lastIndex 
  42675.     "Answer with a new instance streaming over a copy of aCollection from
  42676.     firstIndex to lastIndex."
  42677.  
  42678.     ^self basicNew
  42679.         on: aCollection
  42680.         from: firstIndex
  42681.         to: lastIndex! !WriteStream subclass: #ReadWriteStream
  42682.     instanceVariableNames: ''
  42683.     classVariableNames: ''
  42684.     poolDictionaries: ''
  42685.     category: 'Collections-Streams'!
  42686. ReadWriteStream comment:
  42687. 'I represent an accessor for a sequence of objects. My instances can both read and store objects.'!
  42688.  
  42689. !ReadWriteStream methodsFor: 'accessing'!
  42690. contents
  42691.     "Answer with a copy of my collection from 1 to readLimit."
  42692.  
  42693.     readLimit _ readLimit max: position.
  42694.     ^collection copyFrom: 1 to: readLimit!
  42695. name
  42696.     ^ 'a stream'   "for fileIn compatibility"!
  42697. next
  42698.     "Primitive. Return the next object in the Stream represented by the
  42699.     receiver. Fail if the collection of this stream is not an Array or a String.
  42700.     Fail if the stream is positioned at its end, or if the position is out of
  42701.     bounds in the collection. Optional. See Object documentation
  42702.     whatIsAPrimitive."
  42703.  
  42704.     <primitive: 65>
  42705.     "treat me as a FIFO"
  42706.     position >= readLimit
  42707.         ifTrue: [^nil]
  42708.         ifFalse: [^collection at: (position _ position + 1)]! !
  42709.  
  42710. !ReadWriteStream methodsFor: 'file status'!
  42711. close
  42712.     "Presumably sets the status of the receiver to be closed. This message does 
  42713.     nothing at this level, but is included for FileStream compatibility."
  42714.  
  42715.     ^self!
  42716. closed
  42717.     "If you have close (for FileStream compatibility), you must respond to closed.  The result in nonsense here.  TK 29 May 96"
  42718.  
  42719.     ^ false! !
  42720.  
  42721. !ReadWriteStream methodsFor: 'fileIn/Out'!
  42722. fileIn
  42723.     "This is special for reading expressions from text that has been formatted 
  42724.     with exclamation delimitors. The expressions are read and passed to the 
  42725.     Compiler. Answer the result of compilation."
  42726.     | val |
  42727.     'Reading ' , self name
  42728.         displayProgressAt: Sensor cursorPoint
  42729.         from: 0 to: self size
  42730.         during:
  42731.         [:bar |
  42732.         [self atEnd]
  42733.             whileFalse: 
  42734.                 [bar value: self position.
  42735.                 self skipSeparators.
  42736.                 val _ (self peekFor: $!!)
  42737.                             ifTrue: [(Compiler evaluate: self nextChunk logged: false)
  42738.                                     scanFrom: self]
  42739.                             ifFalse: [Compiler evaluate: self nextChunk logged: true]].
  42740.         self close].
  42741.     ^ val!
  42742. fileNameEndsWith: aString
  42743.     "See comment in FileStream fileNameEndsWith:"
  42744.  
  42745.     ^false!
  42746. fileOutChanges
  42747.     "Append to the receiver a description of all class changes."
  42748.     Cursor write showWhile:
  42749.         [self header; timeStamp.
  42750.         Smalltalk changes fileOutOn: self.
  42751.         self trailer; close]!
  42752. fileOutChangesFor: class
  42753.     "Append to the receiver a description of the changes to the class."
  42754.     Cursor write showWhile:
  42755.         [self header; timeStamp.
  42756.         Smalltalk changes fileOutChangesFor: class on: self;
  42757.             fileOutPSFor: class on: self.
  42758.         (class inheritsFrom: Class)
  42759.             ifFalse: [Smalltalk changes fileOutChangesFor: class class on: self;
  42760.                         fileOutPSFor: class class on: self].
  42761.         self trailer; close]!
  42762. timeStamp
  42763.     "Append the current time to the receiver."
  42764.  
  42765.     | aStream |
  42766.     aStream _ WriteStream on: (String new: 16).
  42767.     Smalltalk timeStamp: aStream.
  42768.     self command: 'H2'.
  42769.     self nextChunkPut: aStream contents printString.    "double quotes and !!s"
  42770.     self command: '/H2'.
  42771.     self cr; cr! !Object subclass: #RealEstateAgent
  42772.     instanceVariableNames: ''
  42773.     classVariableNames: 'ReverseStaggerOffset StaggerOffset ScrollBarSetback ScreenTopSetback StaggerOrigin StandardWindowOrigins '
  42774.     poolDictionaries: ''
  42775.     category: 'Interface-Support'!
  42776. RealEstateAgent comment:
  42777. 'Responsible for real-estate management on the screen, which is to say, controlling where new windows appear, with what sizes, etc.  5/20/96 sw'!
  42778.  
  42779. !RealEstateAgent methodsFor: 'no messages'! !
  42780. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  42781.  
  42782. RealEstateAgent class
  42783.     instanceVariableNames: ''!
  42784.  
  42785. !RealEstateAgent class methodsFor: 'as yet unclassified'!
  42786. initialFrameFor: aView
  42787.     "Find a plausible initial screen area for the supplied view, which should be a StandardSystemView, taking into account the 'reverseWindowStagger' Preference, the size needed, and other windows currently on the screen.  5/22/96 sw"
  42788.  
  42789.     | allOrigins screenRight screenBottom initialExtent putativeOrigin putativeFrame allowedArea staggerOrigin |
  42790.  
  42791.     Preferences reverseWindowStagger ifTrue:
  42792.         [^ self strictlyStaggeredInitialFrameFor: aView].
  42793.  
  42794.     allowedArea _ Display usableArea.
  42795.     screenRight _ allowedArea right.
  42796.     screenBottom _ allowedArea bottom.
  42797.     initialExtent _ aView initialExtent.
  42798.  
  42799.     allOrigins _ ScheduledControllers windowOriginsInUse.
  42800.     self standardPositions do:  "First see if one of the standard positions is free"
  42801.         [:aPosition | (allOrigins includes: aPosition)
  42802.             ifFalse:
  42803.                 [^ (aPosition extent: initialExtent) squishedWithin: allowedArea]].
  42804.  
  42805.     staggerOrigin _ self standardPositions first.  "Fallback: try offsetting from top left"
  42806.     putativeOrigin _ staggerOrigin.
  42807.  
  42808.     [putativeOrigin _ putativeOrigin + StaggerOffset.
  42809.     putativeFrame _ putativeOrigin extent: initialExtent.
  42810.     (putativeFrame bottom < screenBottom) and:
  42811.                     [putativeFrame right < screenRight]]
  42812.                 whileTrue:
  42813.                     [(allOrigins includes: putativeOrigin)
  42814.                         ifFalse:
  42815.                             [^ (putativeOrigin extent: initialExtent) squishedWithin: allowedArea]].
  42816.     ^ (ScrollBarSetback @ ScreenTopSetback extent: initialExtent) squishedWithin: allowedArea!
  42817. initialize
  42818.     "Initialize the class variables in the receiver.  5/22/96 sw"
  42819.  
  42820.     "RealEstateAgent initialize"
  42821.  
  42822.     StaggerOffset _ 6 @ 20.
  42823.     ReverseStaggerOffset _ -6 @ 20.
  42824.     StaggerOrigin _ 200 @ 30.
  42825.     ScrollBarSetback _ 44.
  42826.     ScreenTopSetback _ 18!
  42827. standardPositions
  42828.     "Return a list of standard window positions -- this may have one, two, or four of them, depending on the size and shape of the display screen.  5/22/96 sw"
  42829.  
  42830.     | anArea aList  midX midY |
  42831.  
  42832.     anArea _ Display usableArea.
  42833.  
  42834.     midX _ ScrollBarSetback +   ((anArea width - ScrollBarSetback)  // 2).
  42835.     midY _ ScreenTopSetback + ((anArea height - ScreenTopSetback) // 2).
  42836.     aList _ OrderedCollection with: (ScrollBarSetback @ ScreenTopSetback).
  42837.     self windowColumnsDesired > 1
  42838.         ifTrue:
  42839.             [aList add: (midX @ ScreenTopSetback)].
  42840.     self windowRowsDesired > 1
  42841.         ifTrue:
  42842.             [aList add: (ScrollBarSetback @ midY).
  42843.             self windowColumnsDesired > 1 ifTrue:
  42844.                 [aList add: (midX @ midY)]].
  42845.     ^ aList!
  42846. standardWindowExtent
  42847.     "Answer the standard default extent for new windows.  5/23/96 sw"
  42848.  
  42849.     | effectiveExtent width strips height |
  42850.     effectiveExtent _ Display usableArea extent - (ScrollBarSetback @ ScreenTopSetback).
  42851.     width _ (strips _ self windowColumnsDesired) > 1
  42852.         ifTrue:
  42853.             [effectiveExtent x // strips]
  42854.         ifFalse:
  42855.             [(3 * effectiveExtent x) // 4].
  42856.     height _ (strips _ self windowRowsDesired) > 1
  42857.         ifTrue:
  42858.             [effectiveExtent y // strips]
  42859.         ifFalse:
  42860.             [(3 * effectiveExtent y) //4].
  42861.     ^ width @ height
  42862.  
  42863. "RealEstateAgent standardWindowExtent"!
  42864. strictlyStaggeredInitialFrameFor: aStandardSystemView
  42865.     "Find a plausible initial screen area for the supplied view, given that the 'strictlyStagger' strategy is in effect.  5/22/96 sw"
  42866.  
  42867.     | allOrigins screenRight screenBottom initialExtent putativeOrigin putativeFrame allowedArea staggerOrigin |
  42868.  
  42869.     allowedArea _ Display usableArea.
  42870.     screenRight _ allowedArea right.
  42871.     screenBottom _ allowedArea bottom.
  42872.     initialExtent _ aStandardSystemView initialExtent.
  42873.  
  42874.     allOrigins _ ScheduledControllers windowOriginsInUse.
  42875.  
  42876.     putativeOrigin _ self standardPositions first + ((10 * ReverseStaggerOffset x negated) @ 0).
  42877.     [(allOrigins includes: putativeOrigin)
  42878.         ifFalse:
  42879.             [^ (putativeOrigin extent: initialExtent) squishedWithin: allowedArea].
  42880.     putativeOrigin _ putativeOrigin + ReverseStaggerOffset.
  42881.     putativeFrame _ putativeOrigin extent: initialExtent.
  42882.     (putativeFrame bottom < screenBottom) and: [putativeFrame left > ScrollBarSetback]]
  42883.                 whileTrue.
  42884.     ^ (ScrollBarSetback @ ScreenTopSetback extent: initialExtent) squishedWithin: allowedArea!
  42885. windowColumnsDesired
  42886.     "Answer how many separate vertical columns of windows are wanted.  5/22/96 sw"
  42887.     ^ Preferences reverseWindowStagger
  42888.         ifTrue:
  42889.             [1]
  42890.         ifFalse:
  42891.             [(Display usableArea width > 640)
  42892.                 ifTrue:
  42893.                     [2]
  42894.                 ifFalse:
  42895.                     [1]]!
  42896. windowRowsDesired
  42897.     "Answer how many separate horizontal rows of windows are wanted.  5/22/96 sw"
  42898.     ^ Preferences reverseWindowStagger
  42899.         ifTrue:
  42900.             [1]
  42901.         ifFalse:
  42902.             [(Display usableArea height > 480)
  42903.                 ifTrue:
  42904.                     [2]
  42905.                 ifFalse:
  42906.                     [1]]! !
  42907.  
  42908. RealEstateAgent initialize!
  42909. Object subclass: #Rectangle
  42910.     instanceVariableNames: 'origin corner '
  42911.     classVariableNames: ''
  42912.     poolDictionaries: ''
  42913.     category: 'Graphics-Primitives'!
  42914. Rectangle comment:
  42915. 'I represent a rectangular area of the screen. Arithmetic functions take points as arguments and carry out scaling and translating operations to create new instances of me. Rectangle functions create new instances by determining intersections of rectangles with rectangles.'!
  42916.  
  42917. !Rectangle methodsFor: 'accessing'!
  42918. area
  42919.     "Answer the receiver's area, the product of width and height."
  42920.     | w |
  42921.     (w _ self width) < 0 ifTrue: [^ 0].
  42922.     ^ w * self height max: 0!
  42923. bottom
  42924.     "Answer the position of the receiver's bottom horizontal line."
  42925.  
  42926.     ^corner y!
  42927. bottom: anInteger 
  42928.     "Set the position of the bottom horizontal line of the receiver."
  42929.  
  42930.     corner y: anInteger!
  42931. bottomCenter
  42932.     "Answer the point at the center of the bottom horizontal line of the 
  42933.     receiver."
  42934.  
  42935.     ^self center x @ self bottom!
  42936. bottomLeft
  42937.     "Answer the point at the left edge of the bottom horizontal line of the 
  42938.     receiver."
  42939.  
  42940.     ^origin x @ corner y!
  42941. bottomLeft: aPoint
  42942.     "Set the point at the left edge of the bottom horizontal line of the 
  42943.     receiver."
  42944.  
  42945.     origin x: aPoint x.
  42946.     corner y: aPoint y.!
  42947. bottomRight
  42948.     "Answer the point at the right edge of the bottom horizontal line of the 
  42949.     receiver."
  42950.  
  42951.     ^corner!
  42952. bottomRight: bottomRightPoint 
  42953.     "Set the position of the right corner of the bottom horizontal line of the 
  42954.     receiver."
  42955.  
  42956.     corner _ bottomRightPoint!
  42957. boundingBox
  42958.     ^ self!
  42959. center
  42960.     "Answer the point at the center of the receiver."
  42961.  
  42962.     ^self topLeft + self bottomRight // 2!
  42963. center: aPoint
  42964.     "Set the point at the center of the receiver.  Leave extent the same."
  42965.  
  42966.     self moveBy: (aPoint - self center)!
  42967. corner
  42968.     "Answer the point at the bottom right corner of the receiver."
  42969.  
  42970.     ^corner!
  42971. corner: cornerPoint 
  42972.     "Set the point at the bottom right corner of the receiver."
  42973.  
  42974.     corner _ cornerPoint!
  42975. corners
  42976.     "Return an array of corner points in the order of a quadrilateral spec for WarpBlt"
  42977.     ^ Array with: self topLeft with: self bottomLeft with: self bottomRight with: self topRight!
  42978. extent
  42979.     "Answer with a rectangle with origin 0@0 and corner the receiver's 
  42980.     width @ the receiver's height."
  42981.  
  42982.     ^corner - origin!
  42983. extent: extentPoint 
  42984.     "Set the extent (width and height) of the receiver to be extentPoint."
  42985.  
  42986.     corner _ origin + extentPoint!
  42987. height
  42988.     "Answer the height of the receiver."
  42989.  
  42990.     ^corner y - origin y!
  42991. height: heightInteger 
  42992.     "Change the receiver's bottom y to make its height heightInteger."
  42993.  
  42994.     corner y: origin y + heightInteger!
  42995. left
  42996.     "Answer the position of the receiver's left vertical line."
  42997.  
  42998.     ^origin x!
  42999. left: anInteger 
  43000.     "Set the position of the receiver's left vertical line."
  43001.  
  43002.     origin x: anInteger!
  43003. leftCenter
  43004.     "Answer the point at the center of the receiver's left vertical line."
  43005.  
  43006.     ^self left @ self center y!
  43007. origin
  43008.     "Answer the point at the top left corner of the receiver."
  43009.  
  43010.     ^origin!
  43011. origin: originPoint 
  43012.     "Set the point at the top left corner of the receiver."
  43013.  
  43014.     origin _ originPoint!
  43015. origin: originPoint corner: cornerPoint
  43016.     "Set the points at the top left corner and the bottom right corner of the 
  43017.     receiver."
  43018.  
  43019.     origin _ originPoint.
  43020.     corner _ cornerPoint!
  43021. origin: originPoint extent: extentPoint
  43022.     "Set the point at the top left corner of the receiver to be originPoint and 
  43023.     set the width and height of the receiver to be extentPoint."
  43024.  
  43025.     origin _ originPoint.
  43026.     corner _ origin + extentPoint!
  43027. right
  43028.     "Answer the position of the receiver's right vertical line."
  43029.  
  43030.     ^corner x!
  43031. right: anInteger 
  43032.     "Set the position of the receiver's right vertical line."
  43033.  
  43034.     corner x: anInteger!
  43035. rightCenter
  43036.     "Answer the point at the center of the receiver's right vertical line."
  43037.  
  43038.     ^self right @ self center y!
  43039. top
  43040.     "Answer the position of the receiver's top horizontal line."
  43041.  
  43042.     ^origin y!
  43043. top: anInteger 
  43044.     "Set the position of the receiver's top horizontal line."
  43045.  
  43046.     origin y: anInteger!
  43047. topCenter
  43048.     "Answer the point at the center of the receiver's top horizontal line."
  43049.  
  43050.     ^self center x @ self top!
  43051. topLeft
  43052.     "Answer the point at the top left corner of the receiver's top horizontal line."
  43053.  
  43054.     ^origin
  43055. !
  43056. topLeft: topLeftPoint 
  43057.     "Set the point at the top left corner of the receiver's top horizontal line."
  43058.  
  43059.     origin _ topLeftPoint
  43060. !
  43061. topRight
  43062.     "Answer the point at the top right corner of the receiver's top horizontal 
  43063.     line."
  43064.  
  43065.     ^corner x @ origin y!
  43066. topRight: aPoint
  43067.     "Set the point at the top right corner of the receiver's top horizontal 
  43068.     line."
  43069.  
  43070.     corner x: aPoint x.
  43071.     origin y: aPoint y.!
  43072. width
  43073.     "Answer the width of the receiver."
  43074.  
  43075.     ^corner x - origin x!
  43076. width: widthInteger 
  43077.     "Change the receiver's right vertical line to make its width widthInteger."
  43078.  
  43079.     corner x: origin x + widthInteger! !
  43080.  
  43081. !Rectangle methodsFor: 'comparing'!
  43082. = aRectangle 
  43083.     "Answer true if the receiver's species, origin and corner match aRectangle's."
  43084.  
  43085.     self species = aRectangle species
  43086.         ifTrue: [^origin = aRectangle origin and: [corner = aRectangle corner]]
  43087.         ifFalse: [^false]!
  43088. hash
  43089.     "Hash is reimplemented because = is implemented."
  43090.  
  43091.     ^origin hash bitXor: corner hash!
  43092. hashMappedBy: map
  43093.     "My hash is independent of my oop."
  43094.  
  43095.     ^self hash! !
  43096.  
  43097. !Rectangle methodsFor: 'rectangle functions'!
  43098. amountToTranslateWithin: aRectangle
  43099.     "Answer a Point, delta, such that self + delta is forced within aRectangle."
  43100.     "Altered so as to prefer to keep self topLeft inside when all of self
  43101.     cannot be made to fit 7/27/96 di"
  43102.     | dx dy |
  43103.     dx _ 0.  dy _ 0.
  43104.     self right > aRectangle right ifTrue: [dx _ aRectangle right - self right].
  43105.     self bottom > aRectangle bottom ifTrue: [dy _ aRectangle bottom - self bottom].
  43106.     (self left + dx) < aRectangle left ifTrue: [dx _ aRectangle left - self left].
  43107.     (self top + dy) < aRectangle top ifTrue: [dy _ aRectangle top - self top].
  43108.     ^ dx@dy!
  43109. areasOutside: aRectangle
  43110.     "Answer an Array of Rectangles comprising the parts of the receiver not 
  43111.     intersecting aRectangle."
  43112.  
  43113.     | areas yOrigin yCorner |
  43114.     "Make sure the intersection is non-empty"
  43115.     (origin <= aRectangle corner and: [aRectangle origin <= corner])
  43116.         ifFalse: [^Array with: self].
  43117.     areas _ OrderedCollection new.
  43118.     aRectangle origin y > origin y
  43119.         ifTrue: [areas add: (origin corner: corner x @ (yOrigin _ aRectangle origin y))]
  43120.         ifFalse: [yOrigin _ origin y].
  43121.     aRectangle corner y < corner y
  43122.         ifTrue: [areas add: (origin x @ (yCorner _ aRectangle corner y) corner: corner)]
  43123.         ifFalse: [yCorner _ corner y].
  43124.     aRectangle origin x > origin x 
  43125.         ifTrue: [areas add: (origin x @ yOrigin corner: aRectangle origin x @ yCorner)].
  43126.     aRectangle corner x < corner x 
  43127.         ifTrue: [areas add: (aRectangle corner x @ yOrigin corner: corner x @ yCorner)].
  43128.     ^areas!
  43129. encompass: aPoint 
  43130.     "Answer a Rectangle that contains both the receiver and aPoint.  5/30/96 sw"
  43131.  
  43132.     ^ Rectangle 
  43133.         origin: (origin min: aPoint)
  43134.         corner: (corner max:  aPoint)!
  43135. expandBy: delta 
  43136.     "Answer a Rectangle that is outset from the receiver by delta. delta is a 
  43137.     Rectangle, Point, or scalar."
  43138.  
  43139.     (delta isKindOf: Rectangle)
  43140.         ifTrue: [^Rectangle 
  43141.                     origin: origin - delta origin 
  43142.                     corner: corner + delta corner]
  43143.         ifFalse: [^Rectangle 
  43144.                     origin: origin - delta 
  43145.                     corner: corner + delta]!
  43146. extendBy: delta 
  43147.     "Answer a Rectangle with the same origin as the receiver, but whose corner is offset by delta. delta is a 
  43148.     Rectangle, Point, or scalar."
  43149.  
  43150.     (delta isKindOf: Rectangle)
  43151.         ifTrue: [^Rectangle 
  43152.                     origin: origin
  43153.                     corner: corner + delta corner]
  43154.         ifFalse: [^Rectangle 
  43155.                     origin: origin
  43156.                     corner: corner + delta]!
  43157. insetBy: delta 
  43158.     "Answer a Rectangle that is inset from the receiver by delta. delta is a 
  43159.     Rectangle, Point, or scalar."
  43160.  
  43161.     (delta isKindOf: Rectangle)
  43162.         ifTrue: [^Rectangle 
  43163.                     origin: origin + delta origin 
  43164.                     corner: corner - delta corner]
  43165.         ifFalse: [^Rectangle 
  43166.                     origin: origin + delta 
  43167.                     corner: corner - delta]!
  43168. insetOriginBy: originDeltaPoint cornerBy: cornerDeltaPoint 
  43169.     "Answer a Rectangle that is inset from the receiver by a given amount in 
  43170.     the origin and corner."
  43171.  
  43172.     ^Rectangle
  43173.         origin: origin + originDeltaPoint
  43174.         corner: corner - cornerDeltaPoint!
  43175. intersect: aRectangle 
  43176.     "Answer a Rectangle that is the area in which the receiver overlaps with 
  43177.     aRectangle."
  43178.  
  43179.     ^Rectangle 
  43180.         origin: (origin max: aRectangle origin)
  43181.         corner: (corner min: aRectangle corner)!
  43182. merge: aRectangle 
  43183.     "Answer a Rectangle that contains both the receiver and aRectangle."
  43184.  
  43185.     ^Rectangle 
  43186.         origin: (origin min: aRectangle origin)
  43187.         corner: (corner max: aRectangle corner)!
  43188. pointNearestTo: aPoint
  43189.     "Return the point on my border closest to aPoint"
  43190.     | side |
  43191.     (self containsPoint: aPoint)
  43192.         ifTrue:
  43193.             [side _ self sideNearestTo: aPoint.
  43194.             side == #right ifTrue: [^ self right @ aPoint y].
  43195.             side == #left ifTrue: [^ self left @ aPoint y].
  43196.             side == #bottom ifTrue: [^ aPoint x @ self bottom].
  43197.             side == #top ifTrue: [^ aPoint x @ self top]]
  43198.         ifFalse:
  43199.             [^ ((aPoint x max: self left) min: self right) @
  43200.                 ((aPoint y max: self top) min: self bottom)]!
  43201. translatedToBeWithin: aRectangle
  43202.     "Answer a copy of the receiver that does not extend beyond aRectangle.  7/8/96 sw"
  43203.  
  43204.     ^ self translateBy: (self amountToTranslateWithin: aRectangle)!
  43205. withBottom: y
  43206.     "Copy the receiver with y as its bottom.  1/24/96 sw"
  43207.  
  43208.     ^  origin copy corner: corner x @ y!
  43209. withLeft: x
  43210.     "Copy the receiver with x as its left.  1/24/96 sw"
  43211.  
  43212.     ^ x @ origin y corner: corner copy!
  43213. withRight: x
  43214.     "Copy the receiver with x as its right.  1/24/96 sw"
  43215.  
  43216.     ^ origin copy corner: x @ corner y!
  43217. withTop: y
  43218.     "Copy the receiver with y as its top.  1/24/96 sw"
  43219.  
  43220.     ^  origin x @ y corner: corner copy! !
  43221.  
  43222. !Rectangle methodsFor: 'testing'!
  43223. contains: aRectangle 
  43224.     "Answer whether the receiver is equal to aRectangle or whether 
  43225.     aRectangle is contained within the receiver."
  43226.  
  43227.     ^aRectangle origin >= origin and: [aRectangle corner <= corner]!
  43228. containsPoint: aPoint 
  43229.     "Answer whether aPoint is within the receiver."
  43230.  
  43231.     ^origin <= aPoint and: [aPoint < corner]!
  43232. containsRect: aRect
  43233.     "Answer whether aRect is within the receiver (OK to coincide)."
  43234.  
  43235.     ^aRect origin <= origin and: [aRect corner <= corner]
  43236. !
  43237. cornerPoint: cornerName
  43238.     "Given the name of a corner of the rect, return the point.  Corner is named by symbol like either #bottomRight or #bottonRight:."
  43239.     cornerName last == $: 
  43240.         ifFalse: [^ self perform: cornerName]
  43241.         ifTrue: ["don't want to intern a symbol -- too slow!!"
  43242.             cornerName == #topLeft: ifTrue: [^ self topLeft].
  43243.             cornerName == #topRight: ifTrue: [^ self topRight].
  43244.             cornerName == #bottomLeft: ifTrue: [^ self bottomLeft].
  43245.             cornerName == #bottomRight: ifTrue: [^ self bottomRight].
  43246.             cornerName == #center: ifTrue: [^ self center]].
  43247.     self error: 'unknown corner name'.
  43248.  
  43249.     false ifTrue: ["Selectors Performed"
  43250.         "Please list all selectors that could be args to the 
  43251.         perform: in this method.  Do this so senders will find
  43252.         this method as one of the places the selector is sent from."
  43253.         self listPerformSelectorsHere.        "tells the parser its here"
  43254.  
  43255.         self bottomRight. self topRight.
  43256.         self bottomLeft. self topLeft.
  43257.         self center].!
  43258. cornerSetterFor: aPoint
  43259.     "Return the closest corner or center to aPoint.  For dragging its size or moving whole rectangle (like HyperCard button move)."
  43260.     | myCenter nearest nearPt |
  43261.     myCenter _ self center.
  43262.     nearest _ aPoint x > myCenter x
  43263.         ifTrue: [aPoint y > myCenter y 
  43264.             ifTrue: [3]
  43265.             ifFalse: [2]]
  43266.         ifFalse: [aPoint y > myCenter y 
  43267.             ifTrue: [4]
  43268.             ifFalse: [1]].
  43269.     nearPt _ self perform: 
  43270.         (#(topLeft topRight bottomRight bottomLeft) at: nearest).
  43271.     (aPoint dist: myCenter) < (aPoint dist: nearPt) 
  43272.         ifTrue: [^ #center:]
  43273.         ifFalse: [^ #(topLeft: topRight: bottomRight: bottomLeft:) at: nearest].
  43274.  
  43275.     false ifTrue: ["Selectors Performed"
  43276.         "Please list all selectors that could be args to the 
  43277.         perform: in this method.  Do this so senders will find
  43278.         this method as one of the places the selector is sent from."
  43279.         self listPerformSelectorsHere.        "tells the parser its here"
  43280.  
  43281.         self bottomRight. self topRight.
  43282.         self bottomLeft. self topLeft.
  43283.         self center.
  43284.         ].!
  43285. hasPositiveExtent
  43286.     ^ (corner x > origin x) and: [corner y > origin y]!
  43287. intersects: aRectangle 
  43288.     "Answer whether aRectangle intersects the receiver anywhere."
  43289.  
  43290.     ^(origin max: aRectangle origin) < (corner min: aRectangle corner)!
  43291. sideNearestTo: aPoint
  43292.     | distToLeft itsX distToRight distToTop itsY distToBottom horizontalChoice horizontalDistance verticalChoice verticalDistance |
  43293.     distToLeft _ (self left - (itsX _ aPoint x)) abs.
  43294.     distToRight _ (self right - itsX) abs.
  43295.     distToTop _ (self top - (itsY _ aPoint y)) abs.
  43296.     distToBottom _ (self bottom - itsY) abs.
  43297.     distToLeft < distToRight 
  43298.         ifTrue: 
  43299.             [horizontalChoice _ #left.  
  43300.             horizontalDistance _ distToLeft]
  43301.         ifFalse:
  43302.             [horizontalChoice _ #right.
  43303.             horizontalDistance _ distToRight].
  43304.     distToTop < distToBottom
  43305.         ifTrue: 
  43306.             [verticalChoice _ #top.  
  43307.             verticalDistance _ distToTop]
  43308.         ifFalse:
  43309.             [verticalChoice _ #bottom.
  43310.             verticalDistance _ distToBottom].
  43311.     horizontalDistance < verticalDistance
  43312.         ifTrue:
  43313.             [^ horizontalChoice]
  43314.         ifFalse:
  43315.             [^ verticalChoice]! !
  43316.  
  43317. !Rectangle methodsFor: 'truncation and round off'!
  43318. rounded
  43319.     "Answer a Rectangle whose origin and corner are rounded."
  43320.  
  43321.     ^Rectangle origin: origin rounded corner: corner rounded!
  43322. truncated
  43323.     "Answer a Rectangle whose origin and corner have any fractional parts removed."
  43324.  
  43325.     ^Rectangle origin: origin truncated corner: corner truncated!
  43326. truncateTo: grid
  43327.     "Answer a Rectangle whose origin and corner are truncated to grid x and grid y."
  43328.  
  43329.     ^Rectangle origin: (origin truncateTo: grid)
  43330.                 corner: (corner truncateTo: grid)! !
  43331.  
  43332. !Rectangle methodsFor: 'transforming'!
  43333. align: aPoint1 with: aPoint2 
  43334.     "Answer a Rectangle that is a translated by aPoint2 - aPoint1."
  43335.  
  43336.     ^self translateBy: aPoint2 - aPoint1!
  43337. asQuad
  43338.     "Return an array of corner points in the order of a quadrilateral spec for WarpBlt.  Note that this is inset by 1 pixel from 'corners', as each point must be an actual pixel location."
  43339.     ^ (self topLeft corner: self bottomRight-1) corners!
  43340. centeredBeneath: aRectangle
  43341.      "Move the reciever so that its top center point coincides with the bottom center point of aRectangle.  5/20/96 sw:"
  43342.  
  43343.     ^ self align: self topCenter with: aRectangle bottomCenter!
  43344. flipBy: direction centerAt: aPoint 
  43345.     "Return a copy flipped according to the direction, either #vertical or #horizontal, around aPoint."
  43346.     ^ Rectangle
  43347.         origin: ((direction == #vertical
  43348.                     ifTrue: [self bottomLeft]
  43349.                     ifFalse: [self topRight])
  43350.                 flipBy: direction centerAt: aPoint)
  43351.         extent: self extent!
  43352. forcedWithin: aRectangle
  43353.     "Force the receiver to fit within aRectangle.  1/12/96 sw
  43354.      2/5/96 sw: don't let top or left go outside requested area
  43355.  
  43356.     (50 @ 50 corner: 160 @ 100) forcedWithin:
  43357.            (20 @ 10 corner: 90 @ 85) 
  43358. "
  43359.     self moveBy: ((0 @ 0) min: (aRectangle corner) - corner).
  43360.     origin _ origin max: aRectangle origin!
  43361. moveBy: aPoint 
  43362.     "Change the corner positions of the receiver so that its area translates by 
  43363.     the amount defined by the argument, aPoint."
  43364.  
  43365.     origin _ origin + aPoint.
  43366.     corner _ corner + aPoint!
  43367. moveTo: aPoint 
  43368.     "Change the corners of the receiver so that its top left position is aPoint."
  43369.  
  43370.     corner _ corner + aPoint - origin.
  43371.     origin _ aPoint!
  43372. newRectFrom: newRectBlock
  43373.     "Track the outline of a new rectangle until mouse button changes.
  43374.     newFrameBlock produces each new rectangle from the previous"
  43375.     | rect newRect buttonStart buttonNow |
  43376.     buttonStart _ buttonNow _ Sensor anyButtonPressed.
  43377.     rect _ self.
  43378.     Display border: rect width: 2 rule: Form reverse fillColor: Color gray.
  43379.     [buttonNow == buttonStart] whileTrue: 
  43380.         [Processor yield.
  43381.         buttonNow _ Sensor anyButtonPressed.
  43382.         newRect _ newRectBlock value: rect.
  43383.         newRect = rect ifFalse:
  43384.             [Display border: rect width: 2 rule: Form reverse fillColor: Color gray.
  43385.             Display border: newRect width: 2 rule: Form reverse fillColor: Color gray.
  43386.             rect _ newRect]].
  43387.     Display border: rect width: 2 rule: Form reverse fillColor: Color gray.
  43388.     ^ rect!
  43389. rectified
  43390.     "Make the origin coordinates <= the corner coords, swapping where necessary.  7/16/96 sw"
  43391.     
  43392.     | oldOrigin oldCorner |
  43393.     oldOrigin _ origin.
  43394.     oldCorner _ corner.
  43395.     origin _ oldOrigin min: oldCorner.
  43396.     corner _ oldOrigin max: oldCorner
  43397.  
  43398.     " (100 @ 50 corner: 80 @ 25) rectified"!
  43399. rotateBy: direction centerAt: aPoint
  43400.     "Return a copy rotated either #right or #left around aPoint"
  43401.     ^ Rectangle origin: ((origin rotateBy: direction centerAt: aPoint) - (direction == #right ifTrue: [self height @ 0] 
  43402.     ifFalse: [0 @ self width])) extent: self extent transpose    
  43403.         "origin becomes new topRight then offset to origin"!
  43404. scaleBy: scale 
  43405.     "Answer a Rectangle scaled by scale, a Point or a scalar."
  43406.  
  43407.     ^Rectangle origin: origin * scale corner: corner * scale!
  43408. squishedWithin: aRectangle
  43409.     "Force the receiver to fit within aRectangle by reducing its size, not by changing its origin.  5/21/96 sw"
  43410.  
  43411.     self bottom: (self bottom min: aRectangle bottom).
  43412.     self right: (self right min: aRectangle right)
  43413.  
  43414. "(50 @ 50 corner: 160 @ 100) squishedWithin:  (20 @ 10 corner: 90 @ 85)"
  43415. !
  43416. translateBy: factor 
  43417.     "Answer a Rectangle translated by factor, a Point or a scalar."
  43418.  
  43419.     ^Rectangle origin: origin + factor corner: corner + factor! !
  43420.  
  43421. !Rectangle methodsFor: 'copying'!
  43422. copy 
  43423.     "Refer to the comment in Object|copy."
  43424.  
  43425.     ^self deepCopy! !
  43426.  
  43427. !Rectangle methodsFor: 'printing'!
  43428. display: c 
  43429.     "Display the receiver filling it with the given color; by Alan Kay.  Used by his mini painting system."
  43430.  
  43431.     | p |
  43432.     p _ Pen new.
  43433.     p color: c.
  43434.     p place: self origin.
  43435.     1 to: 4 do:
  43436.         [:i | p turn: 90; go: self width]
  43437.     !
  43438. printOn: aStream 
  43439.     "Refer to the comment in Object|printOn:."
  43440.  
  43441.     origin printOn: aStream.
  43442.     aStream nextPutAll: ' corner: '.
  43443.     corner printOn: aStream!
  43444. storeOn: aStream 
  43445.     "printed form is good for storing too"
  43446.     self printOn: aStream! !
  43447. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  43448.  
  43449. Rectangle class
  43450.     instanceVariableNames: ''!
  43451.  
  43452. !Rectangle class methodsFor: 'instance creation'!
  43453. fromUser
  43454.     "Answer an instance of me that is determined by having the user 
  43455.     designate the top left and bottom right corners. The gridding for user 
  43456.     selection is 1@1."
  43457.  
  43458.     ^self fromUser: 1 @ 1!
  43459. fromUser: gridPoint
  43460.     "Answer a Rectangle that is determined by having the user 
  43461.     designate the top left and bottom right corners. 
  43462.     The cursor reamins linked with the sensor, but
  43463.     the outline is kept gridded."
  43464.     | originRect |
  43465.     originRect _ Cursor origin showWhile: 
  43466.         [((Sensor cursorPoint grid: gridPoint) extent: 0@0) newRectFrom:
  43467.             [:f | (Sensor cursorPoint grid: gridPoint) extent: 0@0]].
  43468.     ^ Cursor corner showWhile:
  43469.         [originRect newRectFrom:
  43470.             [:f | f origin corner: (Sensor cursorPoint grid: gridPoint)]]!
  43471. left: leftNumber right: rightNumber top: topNumber bottom: bottomNumber 
  43472.     "Answer an instance of me whose left, right, top, and bottom coordinates 
  43473.     are determined by the arguments."
  43474.  
  43475.     ^self origin: leftNumber @ topNumber corner: rightNumber @ bottomNumber!
  43476. new 
  43477.     "Answer an instance of me whose corners (top left and bottom right) are 
  43478.     determined by the arguments."
  43479.  
  43480.     ^self basicNew origin: 0 @ 0 corner: 0 @ 0
  43481. !
  43482. origin: originPoint corner: cornerPoint 
  43483.     "Answer an instance of me whose corners (top left and bottom right) are 
  43484.     determined by the arguments."
  43485.  
  43486.     ^self new origin: originPoint corner: cornerPoint!
  43487. origin: originPoint extent: extentPoint 
  43488.     "Answer an instance of me whose top left corner is originPoint and width 
  43489.     by height is extentPoint."
  43490.  
  43491.     ^self new origin: originPoint extent: extentPoint!
  43492. originFromUser: extentPoint 
  43493.     "Answer an instance of me that is determined by having the user 
  43494.     designate the top left corner. The width and height are determined by 
  43495.     extentPoint. The gridding for user selection is 1@1."
  43496.  
  43497.     ^self originFromUser: extentPoint grid: 1 @ 1!
  43498. originFromUser: extentPoint grid: gridPoint 
  43499.     "Answer an instance of me that is determined by having the user 
  43500.     designate the top left corner. The width and height are determined by 
  43501.     extentPoint. The gridding for user selection is scaleFactor. Assumes that 
  43502.     the sender has determined an extent that is a proper multiple of 
  43503.     scaleFactor."
  43504.  
  43505.     ^ Cursor origin showWhile: 
  43506.         [((Sensor cursorPoint grid: gridPoint) extent: extentPoint) newRectFrom:
  43507.             [:f | (Sensor cursorPoint grid: gridPoint) extent: extentPoint]].
  43508. ! !DataStream subclass: #ReferenceStream
  43509.     instanceVariableNames: 'references objects currentReference fwdRefEnds transients '
  43510.     classVariableNames: 'RefTypes '
  43511.     poolDictionaries: ''
  43512.     category: 'Objects to Disk'!
  43513. ReferenceStream comment:
  43514. 'This is an interim save-to-disk facility. A ReferenceStream can store
  43515. one or more objects in a persistent form, including sharing and
  43516. cycles. Cf. DataStream.
  43517.  
  43518. Here is the way to use DataStream and ReferenceStream:
  43519.     rr _ ReferenceStream fileNamed: ''test.obj''.
  43520.     rr nextPut: <your object>.
  43521.     rr close.
  43522.  
  43523. To get it back:
  43524.     rr _ ReferenceStream fileNamed: ''test.obj''.
  43525.     <your object> _ rr next.
  43526.     rr close.
  43527.  
  43528. ReferenceStreams can now write "weak" references. nextPutWeak:
  43529. writes a "weak" reference to an object, which refers to that object
  43530. *if* it also gets written to the stream by a normal nextPut:.
  43531.  
  43532. Public messages:
  43533.     reset
  43534. Public inherited messages (see DataStream)
  43535.     (class) on:
  43536.     (class) fileNamed:
  43537.     (class) fileTypeCode
  43538.     atEnd
  43539.     beginInstance:size: (for use by storeDataOn: methods)
  43540.     beginReference: (for use by readDataFrom:size: methods)
  43541.     close
  43542.     next
  43543.     next:
  43544.     nextPut:
  43545.     nextPutAll:
  43546.     nextPutWeak:
  43547.     setType:
  43548.     shorten
  43549.     size
  43550.  
  43551. NOTE: A ReferenceStream should be treated as a read-stream *or* as a
  43552. write-stream, *not* as a read/write-stream. The reference-remembering
  43553. mechanism would probably do bad things if you tried to read and write
  43554. from the same ReferenceStream.
  43555.  
  43556. [TBD] Should we override "close" to do
  43557.     self forgetReferences. super close?
  43558.  
  43559. Instance variables
  43560.  references -- an IdentityDictionary mapping objects already written
  43561.     to their byteStream positions. If asked to write any object a
  43562.     second time, we just write a reference to its stream position.
  43563.     This handles shared objects and reference cycles between objects.
  43564.     To implement "weak references" (for Aliases), the references
  43565.     dictionary also maps objects not (yet?) written to a Collection
  43566.     of byteStream positions with hopeful weak-references to it. If
  43567.     asked to definitely write one of these objects, we''ll fixup those
  43568.     weak references.
  43569.  objects -- an IdentityDictionary mapping byte stream positions to
  43570.     objects already read in. If asked to follow a reference, we
  43571.     return the object already read.
  43572.     This handles shared objects and reference cycles between objects.
  43573.  currentReference -- the current reference position. This variable
  43574.     is used to help install each new object in "objects" as soon
  43575.     as it''s created, **before** we start reading its contents, in
  43576.     case any of its content objects reference it.
  43577.  fwdRefEnds -- A weak reference can be a forward reference, which
  43578.     requires advance-reading the referrent. When we later come to the
  43579.     object, we must get its value from "objects" and not re-read it so
  43580.     refs to it don''t become refs to copies. fwdRefEnds remembers the
  43581.     ending byte stream position of advance-read objects.
  43582.  transients -- an IdentitySet of byte stream positions corresponding
  43583.     to objects that we''ve started to read in (and already added to
  43584.     "objects" in case of reference cycles) but haven''t yet handed out
  43585.     OOPs for. If we hand out an OOP to one of these interim OOPs, and
  43586.     if internalizing it (comeFullyUpOnReload) returns a different OOP,
  43587.     then we must ask it to #become: the new OOP. Tracking the interim
  43588.     OOPs handed out lets us save most calls to (costly) #become:.
  43589. -- 11/17/92 jhm
  43590. '!
  43591.  
  43592. !ReferenceStream methodsFor: 'as yet unclassified'!
  43593. beginReference: anObject
  43594.     "Remember anObject as the object we read at the position recorded by
  43595.      noteCurrentReference:. This must be done after instantiating anObject but
  43596.      before reading any of its contents that might (directly or indirectly) refer to
  43597.      it. (It╒s ok to do this redundantly, which is convenient for #next.)
  43598.      Answer the reference position. -- jhm"
  43599.  
  43600.     objects at: currentReference put: anObject.
  43601.     ^ currentReference!
  43602. forgetReferences
  43603.     "PRIVATE -- Reset my internal state.
  43604.        11/15-17/92 jhm: Added transients and fwdRefEnds.
  43605.        7/11/93 sw: Give substantial initial sizes to avoid huge time spent growing.
  43606.        9/3/93 sw: monster version for Sasha"
  43607.  
  43608.     references _ IdentityDictionary new: 4096*4.
  43609.     objects _ IdentityDictionary new: 4096.
  43610.     fwdRefEnds _ IdentityDictionary new.
  43611.    " transients _ Set new.  never used?"!
  43612. getCurrentReference
  43613.     "PRIVATE -- Return the currentReference posn."
  43614.  
  43615.     ^ currentReference!
  43616. next
  43617.     "Answer the next object in the stream. If this object was already read by a
  43618.      forward ref, don't re-read it. Cf. class comment. -- 11/18-24/92 jhm"
  43619.     | curPosn skipToPosn |
  43620.  
  43621.     "Did we already read the next object? If not, use ordinary super next."
  43622.     skipToPosn _ fwdRefEnds removeKey: (curPosn _ byteStream position)
  43623.                              ifAbsent: [nil].
  43624.     skipToPosn == nil ifTrue: [^ super next].
  43625.         "Compared to ifAbsent: [^ super next], this saves 2 stack frames per cycle
  43626.          in the normal case of this deep recursion. This is mainly a debugging aid
  43627.          but it also staves off stack overflow."
  43628.  
  43629.     "Skip over the object and return the already-read-in value from 'object'."
  43630.     byteStream position: skipToPosn.
  43631.     ^ objects at: curPosn ifAbsent: [self errorInternalInconsistency]!
  43632. nextPutWeak: anObject
  43633.     "Write a weak reference to anObject to the receiver stream. Answer anObject.
  43634.      If anObject is not a reference type of object, then just put it normally.
  43635.      A 'weak' reference means: If anObject gets written this stream via nextPut:,
  43636.      then its weak references will become normal references. Otherwise they'll
  43637.      read back as nil. -- 11/15/92 jhm"
  43638.     | typeID referencePosn |
  43639.  
  43640.     "Is it a reference type of object? If not, just write it normally."
  43641.     typeID _ self typeIDFor: anObject.
  43642.     (self isAReferenceType: typeID) ifFalse: [^ self nextPut: anObject].
  43643.  
  43644.     "Have we heard of and maybe even written anObject before?"
  43645.     referencePosn _ references
  43646.               at: anObject
  43647.         ifAbsent: [references at: anObject put: OrderedCollection new].
  43648.  
  43649.     "If referencePosn is an Integer, it's the stream position of anObject.
  43650.      Else it's a collection of hopeful weak-references to anObject."
  43651.     (referencePosn isKindOf: Integer) ifFalse:
  43652.         [referencePosn add: byteStream position.
  43653.         referencePosn _ self vacantRef].
  43654.     self outputReference: referencePosn.
  43655.  
  43656.     ^ anObject!
  43657. noteCurrentReference: typeID
  43658.     "PRIVATE -- If we support references for type typeID, remember
  43659.      the current byteStream position so beginReference: can add the
  43660.      next object to the ╘objects╒ dictionary of reference positions,
  43661.      then return true. Else return false."
  43662.     | answer |
  43663.  
  43664.     (answer _ self isAReferenceType: typeID)
  43665.         ifTrue: [self setCurrentReference: byteStream position - 1
  43666.                 "subtract 1 because we already read the object╒s
  43667.                  type ID byte"].
  43668.     ^ answer!
  43669. objectAt: anInteger
  43670.     "PRIVATE -- Read & return the object at a given stream position.
  43671.      If we already read it, just get it from the objects dictionary.
  43672.      (Reading it again wouldn╒t work with cycles or sharing.)
  43673.      If not, go read it and put it in the objects dictionary.
  43674.      NOTE: This resolves a cross-reference in the ReferenceStream:
  43675.        1. A backward reference to an object already read (the normal case).
  43676.        2. A forward reference which is a sated weak reference (we record where
  43677.           the object ends so when we get to it normally we can fetch it from
  43678.           ╘objects╒ and skip over it).
  43679.        3. A backward reference to a ╘non-reference type╒ per the long NOTE in
  43680.           nextPut: (we compensate here--seek back to re-read it and add the object
  43681.           to ╘objects╒ to avoid seeking back to read it any more times).
  43682.        4. While reading a foward weak reference (case 2), we may recursively hit an
  43683.           ordinary backward reference to an object that we haven╒t yet read because
  43684.           we temporarily skipped ahead. Such a reference is forward in time so we
  43685.           treat it much like case 2.
  43686.      11/16-24/92 jhm: Handle forward refs. Cf. class comment and above NOTE."
  43687.     | savedPosn refPosn anObject |
  43688.  
  43689.     ^ objects
  43690.         at: anInteger   "case 1: It╒s in ╘objects╒"
  43691.         ifAbsent:   "do like super objectAt:, but remember the fwd-ref-end position"
  43692.             [savedPosn _ byteStream position.
  43693.             refPosn _ self getCurrentReference.
  43694.  
  43695.             byteStream position: anInteger.
  43696.             anObject _ self next.
  43697.  
  43698.             (self isAReferenceType: (self typeIDFor: anObject))
  43699.                 ifTrue:  [fwdRefEnds at: anInteger put: byteStream position] "cases 2, 4"
  43700.                 ifFalse: [objects at: anInteger put: anObject]. "case 3"
  43701.  
  43702.             self setCurrentReference: refPosn.
  43703.             byteStream position: savedPosn.
  43704.             anObject]!
  43705. reset
  43706.     "Reset the stream."
  43707.  
  43708.     super reset.
  43709.     self forgetReferences!
  43710. setCurrentReference: refPosn
  43711.     "PRIVATE -- Set currentReference to refPosn."
  43712.  
  43713.     currentReference _ refPosn!
  43714. setStream: aStream
  43715.     "PRIVATE -- Initialization method."
  43716.  
  43717.     super setStream: aStream.
  43718.     self forgetReferences!
  43719. tryToPutReference: anObject typeID: typeID
  43720.     "PRIVATE -- If we support references for type typeID, and if
  43721.        anObject already appears in my output stream, then put a
  43722.        reference to the place where anObject already appears. If we
  43723.        support references for typeID but didn╒t already put anObject,
  43724.        then associate the current stream position with anObject in
  43725.        case one wants to nextPut: it again.
  43726.      Return true after putting a reference; false if the object still
  43727.        needs to be put.
  43728.      11/15/92 jhm: Added support for weak refs. Split out outputReference:."
  43729.     | referencePosn nextPosn |
  43730.  
  43731.     "Is it a reference type of object?"
  43732.     (self isAReferenceType: typeID) ifFalse: [^ false].
  43733.  
  43734.     "Have we heard of and maybe even written anObject before?"
  43735.     referencePosn _ references
  43736.               at: anObject
  43737.         ifAbsent:   "Nope. Remember it and let the sender write it."
  43738.             [references at: anObject put: byteStream position.
  43739.             ^ false].
  43740.  
  43741.     "If referencePosn is an Integer, it's the stream position of anObject."
  43742.     (referencePosn isKindOf: Integer) ifTrue:
  43743.         [self outputReference: referencePosn.
  43744.         ^ true].
  43745.  
  43746.     "Else referencePosn is a collection of positions of weak-references to anObject.
  43747.      Make them full references since we're about to really write anObject."
  43748.     references at: anObject put: (nextPosn _ byteStream position).
  43749.     referencePosn do:
  43750.         [:weakRefPosn |
  43751.             byteStream position: weakRefPosn.
  43752.             self outputReference: nextPosn].
  43753.     byteStream position: nextPosn.
  43754.     ^ false! !
  43755.  
  43756. !ReferenceStream methodsFor: 'imported from V'!
  43757. internalize: externalObject
  43758.     "PRIVATE -- We just read externalObject. Give it a chance to internalize. Return the internalized object.
  43759.      If become: is expensive, we could use it less often. It's needed when we've already given out references to the object being read (while recursively reading its contents).  In other cases, we could just change the entry in the objects Dictionary.
  43760.     If an object is pointed at from inside itself, then it cannot have a different external and internal form.  It cannot be a PathFromHome or return anything other than self when sent comeFullyUpOnReload. (DiskProxy is OK)
  43761.     Objects that do return something other than self when sent comeFullyUpOnReload must not point to themselves, even indirectly.    8/14/96 tk"
  43762.     | internalObject |
  43763.  
  43764.     internalObject _ externalObject comeFullyUpOnReload.
  43765.     (externalObject ~~ internalObject and: [externalObject isKindOf: DiskProxy])
  43766.         ifTrue: [externalObject become: internalObject]
  43767.         ifFalse: [(self isAReferenceType:(self typeIDFor: internalObject))
  43768.             ifTrue: [self beginReference: internalObject]].
  43769.             "save the final object and give it out next time.  Substitute for become"
  43770.     ^ internalObject!
  43771. isAReferenceType: typeID
  43772.     "Return true iff typeID is one of the classes that can be written as a reference to an instance elsewhere in the stream. -- jhm, 8/9/96 tk"
  43773.  
  43774.     "too bad we can't put Booleans in an Array literal"
  43775.     ^ (RefTypes at: typeID) == 1!
  43776. references
  43777.     ^ references! !
  43778. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  43779.  
  43780. ReferenceStream class
  43781.     instanceVariableNames: ''!
  43782. ReferenceStream class comment:
  43783. 'See comment in ReferenceStream itself'!
  43784.  
  43785. !ReferenceStream class methodsFor: 'imported from V'!
  43786. example2
  43787. "Here is the way to use DataStream and ReferenceStream:
  43788.     rr _ ReferenceStream fileNamed: ''test.obj''.
  43789.     rr nextPut: <your object>.
  43790.     rr close.
  43791.  
  43792. To get it back:
  43793.     rr _ ReferenceStream fileNamed: ''test.obj''.
  43794.     <your object> _ rr next.
  43795.     rr close.
  43796. "
  43797. "An example and test of DataStream/ReferenceStream.
  43798.      11/19/92 jhm: Use self testWith:."
  43799.     "ReferenceStream example2"
  43800.     | input sharedPoint |
  43801.  
  43802.     "Construct the test data."
  43803.     input _ Array new: 9.
  43804.     input at: 1 put: nil.
  43805.     input at: 2 put: true.
  43806.     input at: 3 put: false.
  43807.     input at: 4 put: #(-4 -4.0 'four' four).
  43808.     input at: 5 put: (Form extent: 63 @ 50 depth: 8).
  43809.         (input at: 5) fillWithColor: Color lightOrange.
  43810.     input at: 6 put: 1024 @ -2048.
  43811.     input at: 7 put: input. "a cycle"
  43812.     input at: 8 put: (Array with: (sharedPoint _ 0 @ -30000)).
  43813.     input at: 9 put: sharedPoint.
  43814.  
  43815.     "Write it out, read it back, and return it for inspection."
  43816.     ^ self testWith: input
  43817. !
  43818. fileTypeCode
  43819.     "Answer a default file type code to use for DataStream files. -- 11/13/92 jhm"
  43820.  
  43821.     ^ 'RefS'!
  43822. refTypes: oc
  43823.     RefTypes _ oc!
  43824. versionCode
  43825.     "Answer a number representing the 'version' of the ReferenceStream facility; this is stashed at the beginning of ReferenceStreams, as a secondary versioning mechanism (the primary one is the fileTypeCode).   At present, it serves for information only, and is not checked for compatibility at reload time, but could in future be used to branch to variant code. 12/2/92 sw"
  43826.  
  43827.     " 1 = "
  43828.     " 2 = HyperSqueak.  PathFromHome used for Objs outside the tree.  SqueakSupport SysLibrary for shared globals like Display and StrikeFonts.  File has version number, class structure, then an IncomingObjects manager.  8/16/96 tk"
  43829.     ^ 2! !Object subclass: #RemoteString
  43830.     instanceVariableNames: 'sourceFileNumber filePositionHi filePositionLo '
  43831.     classVariableNames: ''
  43832.     poolDictionaries: ''
  43833.     category: 'Kernel-Support'!
  43834. RemoteString comment:
  43835. 'My instances provide an external file reference to a piece of executable text, for example, class comments.'!
  43836.  
  43837. !RemoteString methodsFor: 'accessing'!
  43838. position
  43839.     "Answer the location of the string on a file."
  43840.  
  43841.     ^(filePositionHi bitShift: 8) + filePositionLo!
  43842. sourceFileNumber
  43843.     "Answer the index of the file on which the string is stored."
  43844.  
  43845.     ^sourceFileNumber!
  43846. string
  43847.     "Answer the receiver's string if remote files are enabled."
  43848.  
  43849.     | theFile |
  43850.     (sourceFileNumber == nil or: [(SourceFiles at: sourceFileNumber) == nil])
  43851.         ifTrue: [^'']
  43852.         ifFalse: 
  43853.             [theFile _ SourceFiles at: sourceFileNumber.
  43854.             theFile position: (filePositionHi bitShift: 8) + filePositionLo.
  43855.             ^theFile nextChunk]! !
  43856.  
  43857. !RemoteString methodsFor: 'private'!
  43858. fileNumber: sourceIndex position: anInteger
  43859.  
  43860.     sourceFileNumber _ sourceIndex.
  43861.     filePositionHi _ anInteger bitShift: -8.
  43862.     filePositionLo _ anInteger bitAnd: 255!
  43863. fromFile: aPositionableStream onFileNumber: anInteger toFile: aFileStream 
  43864.     "Store the next chunk from aPositionableStream as the receiver's string."
  43865.  
  43866.     | position |
  43867.     sourceFileNumber _ anInteger.
  43868.     filePositionHi _ (position _ aFileStream position) bitShift: -8.
  43869.     filePositionLo _ position bitAnd: 255.
  43870.     aPositionableStream copyChunkTo: aFileStream!
  43871. string: aString onFileNumber: anInteger
  43872.     "Store this as my string if source files exist."
  43873.  
  43874.     | theFile |
  43875.     (SourceFiles at: anInteger) == nil
  43876.         ifFalse: 
  43877.             [theFile _ SourceFiles at: anInteger.
  43878.             theFile setToEnd; cr.
  43879.             self string: aString
  43880.                 onFileNumber: anInteger
  43881.                 toFile: theFile]!
  43882. string: aString onFileNumber: anInteger toFile: aFileStream 
  43883.     "Store this as the receiver's string if source files exist."
  43884.  
  43885.     | position |
  43886.     sourceFileNumber _ anInteger.
  43887.     filePositionHi _ (position _ aFileStream position) bitShift: -8.
  43888.     filePositionLo _ position bitAnd: 255.
  43889.     aFileStream nextChunkPut: aString! !
  43890. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  43891.  
  43892. RemoteString class
  43893.     instanceVariableNames: ''!
  43894.  
  43895. !RemoteString class methodsFor: 'instance creation'!
  43896. newFileNumber: sourceIndex position: anInteger 
  43897.     "Answer an instance of me fora file indexed by sourceIndex, at the 
  43898.     position anInteger. Assume that the string is already stored on the file 
  43899.     and the instance will be used to access it."
  43900.  
  43901.     ^self new fileNumber: sourceIndex position: anInteger!
  43902. newString: aString onFileNumber: sourceIndex 
  43903.     "Answer an instance of me for string, aString, on file indexed by 
  43904.     sourceIndex. Put the string on the file and create the remote reference."
  43905.  
  43906.     ^self new string: aString onFileNumber: sourceIndex!
  43907. newString: aString onFileNumber: sourceIndex toFile: aFileStream
  43908.     "Answer an instance of me for string, aString, on file indexed by 
  43909.     sourceIndex. Put the string on the file, aFileStream, and create the 
  43910.     remote reference. Assume that the index corresponds properly to 
  43911.     aFileStream."
  43912.  
  43913.     ^self new string: aString onFileNumber: sourceIndex toFile: aFileStream! !AbstractSound subclass: #RestSound
  43914.     instanceVariableNames: 'initialCount count '
  43915.     classVariableNames: ''
  43916.     poolDictionaries: ''
  43917.     category: 'Sound'!
  43918.  
  43919. !RestSound methodsFor: 'initialization'!
  43920. setDur: d
  43921.     "Set duration in seconds."
  43922.  
  43923.     initialCount _ (d * self samplingRate asFloat) asInteger.
  43924.     count _ initialCount.
  43925. ! !
  43926.  
  43927. !RestSound methodsFor: 'sound generation'!
  43928. mixSampleCount: n into: aByteArray startingAt: startIndex pan: pan
  43929.     "Play silence for a given duration."
  43930.     "(RestSound dur: 1.0) play"
  43931.  
  43932.     count _ count - n.
  43933. !
  43934. reset
  43935.  
  43936.     super reset.
  43937.     count _ initialCount.
  43938. !
  43939. samplesRemaining
  43940.  
  43941.     ^ count! !
  43942. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  43943.  
  43944. RestSound class
  43945.     instanceVariableNames: ''!
  43946.  
  43947. !RestSound class methodsFor: 'instance creation'!
  43948. pitch: p dur: d loudness: l
  43949.     "Return a rest of the given duration."
  43950.     "Note: This message allows one to silence one or more voices of a multi-voice piece by using RestSound as their instrument."
  43951.  
  43952.     ^ self new setDur: d! !ParseNode subclass: #ReturnNode
  43953.     instanceVariableNames: 'expr pc '
  43954.     classVariableNames: ''
  43955.     poolDictionaries: ''
  43956.     category: 'System-Compiler'!
  43957. ReturnNode comment:
  43958. 'I represent an expression of the form ^expr.'!
  43959.  
  43960. !ReturnNode methodsFor: 'initialize-release'!
  43961. expr: e
  43962.  
  43963.     expr _ e!
  43964. expr: e encoder: encoder sourceRange: range
  43965.  
  43966.     expr _ e.
  43967.     encoder noteSourceRange: range forNode: self! !
  43968.  
  43969. !ReturnNode methodsFor: 'converting'!
  43970. asReturnNode! !
  43971.  
  43972. !ReturnNode methodsFor: 'testing'!
  43973. isReturnSelf
  43974.  
  43975.     ^expr == NodeSelf!
  43976. isSpecialConstant
  43977.  
  43978.     ^expr isSpecialConstant!
  43979. isVariableReference
  43980.  
  43981.     ^expr isVariableReference! !
  43982.  
  43983. !ReturnNode methodsFor: 'code generation'!
  43984. code
  43985.  
  43986.     ^expr code!
  43987. emitForReturn: stack on: strm
  43988.  
  43989.     expr emitForReturn: stack on: strm.
  43990.     pc _ strm position!
  43991. emitForValue: stack on: strm
  43992.  
  43993.     expr emitForReturn: stack on: strm.
  43994.     pc _ strm position!
  43995. pc
  43996.     "Used by encoder source mapping."
  43997.  
  43998.     ^pc!
  43999. sizeForReturn: encoder
  44000.  
  44001.     ^expr sizeForReturn: encoder!
  44002. sizeForValue: encoder
  44003.  
  44004.     ^expr sizeForReturn: encoder! !
  44005.  
  44006. !ReturnNode methodsFor: 'printing'!
  44007. printOn: aStream indent: level
  44008.  
  44009.     aStream nextPutAll: '^ '.
  44010.     expr printOn: aStream indent: level.
  44011.     expr printCommentOn: aStream indent: level! !
  44012.  
  44013. !ReturnNode methodsFor: 'equation translation'!
  44014. collectVariables
  44015.     ^expr collectVariables!
  44016. copyReplacingVariables: varDict 
  44017.     ^self class new expr: (expr copyReplacingVariables: varDict)!
  44018. expr
  44019.     ^expr!
  44020. specificMatch: aTree using: matchDict 
  44021.     ^expr match: aTree expr using: matchDict! !
  44022.  
  44023. !ReturnNode methodsFor: 'C translation'! !ArrayedCollection subclass: #RunArray
  44024.     instanceVariableNames: 'runs values lastIndex lastRun lastOffset '
  44025.     classVariableNames: ''
  44026.     poolDictionaries: ''
  44027.     category: 'Collections-Arrayed'!
  44028. RunArray comment:
  44029. 'My instances provide space-efficient storage of data which tends to be constant over long runs of the possible indices. Essentially repeated values are stored singly and then associated with a "run" that denotes the number of consecutive occurrences of the value.
  44030. The variables lastIndex, lastRun and lastOffset cache the last access
  44031. so that streaming through RunArrays is not an N-squared process.'!
  44032.  
  44033. !RunArray methodsFor: 'accessing'!
  44034. at: index
  44035.  
  44036.     | run offset value |
  44037.     self at: index setRunOffsetAndValue: [:run :offset :value | ^value]!
  44038. runLengthAt: index 
  44039.     "Answer the length remaining in run beginning at index."
  44040.  
  44041.     | run offset value |
  44042.     self at: index 
  44043.         setRunOffsetAndValue: [:run :offset :value | ^(runs at: run) - offset]!
  44044. size
  44045.     | size |
  44046.     size _ 0.
  44047.     1 to: runs size do: [:i | size _ size + (runs at: i)].
  44048.     ^size! !
  44049.  
  44050. !RunArray methodsFor: 'adding'!
  44051. addFirst: value
  44052.     "Add value as the first element of the receiver."
  44053.     lastIndex _ nil.  "flush access cache"
  44054.     (runs size=0 or: [values first ~= value])
  44055.       ifTrue:
  44056.         [runs_ (Array with: 1) , runs.
  44057.         values_ (Array with: value) , values]
  44058.       ifFalse:
  44059.         [runs at: 1 put: runs first+1]!
  44060. addLast: value
  44061.     "Add value as the last element of the receiver."
  44062.     lastIndex _ nil.  "flush access cache"
  44063.     (runs size=0 or: [values last ~= value])
  44064.       ifTrue:
  44065.         [runs_ runs copyWith: 1.
  44066.         values_ values copyWith: value]
  44067.       ifFalse:
  44068.         [runs at: runs size put: runs last+1]! !
  44069.  
  44070. !RunArray methodsFor: 'copying'!
  44071. , aRunArray 
  44072.     "Answer a new RunArray that is a concatenation of the receiver and
  44073.     aRunArray."
  44074.  
  44075.     | new newRuns |
  44076.     (aRunArray isMemberOf: RunArray)
  44077.         ifFalse: 
  44078.             [new _ self copy.
  44079.             "attempt to be sociable"
  44080.             aRunArray do: [:each | new addLast: each].
  44081.             ^new].
  44082.     runs size = 0 ifTrue: [^aRunArray copy].
  44083.     aRunArray runs size = 0 ifTrue: [^self copy].
  44084.     values last ~= aRunArray first
  44085.         ifTrue: [^RunArray
  44086.                     runs: runs , aRunArray runs
  44087.                     values: values , aRunArray values].
  44088.     newRuns _ runs
  44089.                     copyReplaceFrom: runs size
  44090.                     to: runs size
  44091.                     with: aRunArray runs.
  44092.     newRuns at: runs size put: runs last + aRunArray runs first.
  44093.     ^RunArray
  44094.         runs: newRuns
  44095.         values: 
  44096.             (values
  44097.                 copyReplaceFrom: values size
  44098.                 to: values size
  44099.                 with: aRunArray values)!
  44100. copyFrom: start to: stop
  44101.  
  44102.     | run1 offset1 value1 run2 offset2 value2 newRuns |
  44103.     stop < start ifTrue: [^RunArray new].
  44104.     self at: start setRunOffsetAndValue: [:run1 :offset1 :value1 | value1].
  44105.     self at: stop setRunOffsetAndValue: [:run2 :offset2 :value2 | value2].
  44106.     run1 = run2
  44107.         ifTrue: 
  44108.             [newRuns _ Array with: offset2 - offset1 + 1]
  44109.         ifFalse: 
  44110.             [newRuns _ runs copyFrom: run1 to: run2.
  44111.             newRuns at: 1 put: (newRuns at: 1) - offset1.
  44112.             newRuns at: newRuns size put: offset2 + 1].
  44113.     ^RunArray runs: newRuns values: (values copyFrom: run1 to: run2)!
  44114. copyReplaceFrom: start to: stop with: replacement
  44115.  
  44116.     ^(self copyFrom: 1 to: start - 1)
  44117.         , replacement 
  44118.         , (self copyFrom: stop + 1 to: self size)! !
  44119.  
  44120. !RunArray methodsFor: 'printing'!
  44121. storeOn: aStream
  44122.  
  44123.     aStream nextPut: $(.
  44124.     aStream nextPutAll: self class name.
  44125.     aStream nextPutAll: ' runs: '.
  44126.     runs storeOn: aStream.
  44127.     aStream nextPutAll: ' values: '.
  44128.     values storeOn: aStream.
  44129.     aStream nextPut: $)!
  44130. writeOn: aStream
  44131.  
  44132.     aStream nextWordPut: runs size.
  44133.     1 to: runs size do:
  44134.         [:x |
  44135.         aStream nextWordPut: (runs at: x).
  44136.         aStream nextWordPut: (values at: x)]! !
  44137.  
  44138. !RunArray methodsFor: 'private'!
  44139. at: index setRunOffsetAndValue: aBlock 
  44140.     "Supply all run information to aBlock."
  44141.     "Tolerates index=0 and index=size+1 for copyReplace: "
  44142.     | run limit offset |
  44143.     limit _ runs size.
  44144.     (lastIndex == nil or: [index < lastIndex])
  44145.         ifTrue:  "cache not loaded, or beyond index - start over"
  44146.             [run _ 1.
  44147.             offset _ index-1]
  44148.         ifFalse:  "cache loaded and before index - start at cache"
  44149.             [run _ lastRun.
  44150.             offset _ lastOffset + (index-lastIndex)].
  44151.     [run <= limit and: [offset >= (runs at: run)]]
  44152.         whileTrue: 
  44153.             [offset _ offset - (runs at: run).
  44154.             run _ run + 1].
  44155.     lastIndex _ index.  "Load cache for next access"
  44156.     lastRun _ run.
  44157.     lastOffset _ offset.
  44158.     run > limit
  44159.         ifTrue: 
  44160.             ["adjustment for size+1"
  44161.             run _ run - 1.
  44162.             offset _ offset + (runs at: run)].
  44163.     ^aBlock
  44164.         value: run    "an index into runs and values"
  44165.         value: offset    "zero-based offset from beginning of this run"
  44166.         value: (values at: run)    "value for this run"!
  44167. runs
  44168.  
  44169.     ^runs!
  44170. setRuns: newRuns setValues: newValues
  44171.     lastIndex _ nil.  "flush access cache"
  44172.     runs _ newRuns.
  44173.     values _ newValues!
  44174. values
  44175.     "Answer the values in the receiver."
  44176.  
  44177.     ^values! !
  44178. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  44179.  
  44180. RunArray class
  44181.     instanceVariableNames: ''!
  44182.  
  44183. !RunArray class methodsFor: 'instance creation'!
  44184. fromBraceStack: itsSize 
  44185.     "Answer an instance of me with itsSize elements, popped in reverse order from
  44186.      the stack of thisContext sender.  Do not call directly: this is called by {1. 2. 3}
  44187.      constructs."
  44188.  
  44189.     ^ self newFrom: ((Array new: itsSize) fill: itsSize fromStack: thisContext sender)!
  44190. new
  44191.  
  44192.     ^self runs: Array new values: Array new!
  44193. new: size withAll: value 
  44194.     "Answer a new instance of me, whose every element is equal to the
  44195.     argument, value."
  44196.  
  44197.     size = 0 ifTrue: [^self new].
  44198.     ^self runs: (Array with: size) values: (Array with: value)!
  44199. newFrom: aCollection 
  44200.     "Answer an instance of me containing the same elements as aCollection."
  44201.  
  44202.     | newCollection |
  44203.     newCollection _ self new.
  44204.     aCollection do: [:x | newCollection addLast: x].
  44205.     ^newCollection
  44206.  
  44207. "    RunArray newFrom: {1. 2. 2. 3}
  44208.     {1. $a. $a. 3} as: RunArray
  44209.     ({1. $a. $a. 3} as: RunArray) values
  44210. "!
  44211. readFrom: aStream
  44212.     "Answer an instance of me as described on the stream, aStream."
  44213.  
  44214.     | size runs values |
  44215.     size _ aStream nextWord.
  44216.     runs _ Array new: size.
  44217.     values _ Array new: size.
  44218.     1 to: size do:
  44219.         [:x |
  44220.         runs at: x put: aStream nextWord.
  44221.         values at: x put: aStream nextWord].
  44222.     ^ self runs: runs values: values!
  44223. runs: newRuns values: newValues 
  44224.     "Answer an instance of me with runs and values specified by the 
  44225.     arguments."
  44226.  
  44227.     | instance |
  44228.     instance _ self basicNew.
  44229.     instance setRuns: newRuns setValues: newValues.
  44230.     ^instance! !Object subclass: #Scanner
  44231.     instanceVariableNames: 'source mark hereChar aheadChar token tokenType currentComment buffer typeTable '
  44232.     classVariableNames: 'TypeTable '
  44233.     poolDictionaries: ''
  44234.     category: 'System-Compiler'!
  44235. Scanner comment:
  44236. 'I scan a string or text, picking out Smalltalk syntactic tokens. I look one character ahead. I put each token found into the instance variable, token, and its type (a Symbol) into the variable, tokenType. At the end of the input stream, I pretend to see an endless sequence of special characters called doits.'!
  44237.  
  44238. !Scanner methodsFor: 'initialize-release'!
  44239. initScanner
  44240.  
  44241.     buffer _ WriteStream on: (String new: 40).
  44242.     typeTable _ TypeTable!
  44243. scan: inputStream 
  44244.     "Bind the input stream, fill the character buffers and first token buffer."
  44245.  
  44246.     source _ inputStream.
  44247.     self step.
  44248.     self step.
  44249.     self scanToken! !
  44250.  
  44251. !Scanner methodsFor: 'public access'!
  44252. scanFieldNames: stringOrArray
  44253.     "Answer an Array of Strings that are the identifiers in the input string, 
  44254.     stringOrArray. If passed an Array, just answer with that Array, i.e., 
  44255.     assume it has already been scanned."
  44256.  
  44257.     | strm |
  44258.     (stringOrArray isMemberOf: Array)
  44259.         ifTrue: [^stringOrArray].
  44260.     self scan: (ReadStream on: stringOrArray asString).
  44261.     strm _ WriteStream on: (Array new: 10).
  44262.     [tokenType = #doIt]
  44263.         whileFalse: 
  44264.             [tokenType = #word ifTrue: [strm nextPut: token].
  44265.             self scanToken].
  44266.     ^strm contents
  44267.  
  44268.     "Scanner new scanFieldNames: 'abc  def ghi' ('abc' 'def' 'ghi' )"!
  44269. scanStringStruct: textOrString 
  44270.     "The input is a string whose elements are identifiers and parenthesized
  44271.      groups of identifiers.  Answer an array reflecting that structure, representing
  44272.      each identifier by an uninterned string."
  44273.  
  44274.     self scan: (ReadStream on: textOrString asString).
  44275.     self scanStringStruct.
  44276.     ^token
  44277.  
  44278.     "Scanner new scanStringStruct: 'a b (c d) (e f g)'"!
  44279. scanTokens: textOrString 
  44280.     "Answer an Array that has been tokenized as though the input text, 
  44281.     textOrString, had appeared between the array delimitors #( and ) in a 
  44282.     Smalltalk literal expression."
  44283.  
  44284.     self scan: (ReadStream on: textOrString asString).
  44285.     self scanLitVec.
  44286.     ^token
  44287.  
  44288.     "Scanner new scanTokens: 'identifier keyword: 8r31 ''string'' .'"! !
  44289.  
  44290. !Scanner methodsFor: 'expression types'!
  44291. advance
  44292.  
  44293.     | prevToken |
  44294.     prevToken _ token.
  44295.     self scanToken.
  44296.     ^prevToken!
  44297. nextLiteral
  44298.     "Same as advance, but -4 comes back as a number instead of two tokens"
  44299.  
  44300.     | prevToken |
  44301.     prevToken _ self advance.
  44302.     (prevToken == #- and: [token isKindOf: Number])
  44303.         ifTrue: 
  44304.             [^self advance negated].
  44305.     ^prevToken!
  44306. scanLitVec
  44307.  
  44308.     | s |
  44309.     s _ WriteStream on: (Array new: 16).
  44310.     [tokenType = #rightParenthesis or: [tokenType = #doIt]]
  44311.         whileFalse: 
  44312.             [tokenType = #leftParenthesis
  44313.                 ifTrue: 
  44314.                     [self scanToken; scanLitVec]
  44315.                 ifFalse: 
  44316.                     [tokenType = #word | (tokenType = #keyword)
  44317.                         ifTrue: 
  44318.                             [self scanLitWord]
  44319.                         ifFalse:
  44320.                             [(token == #- 
  44321.                                     and: [(typeTable at: hereChar asciiValue) = #xDigit])
  44322.                                 ifTrue: 
  44323.                                     [self scanToken.
  44324.                                     token _ token negated]]].
  44325.             s nextPut: token.
  44326.             self scanToken].
  44327.     token _ s contents!
  44328. scanLitWord
  44329.     "Accumulate keywords and asSymbol the result."
  44330.  
  44331.     | t |
  44332.     [(typeTable at: hereChar asciiValue) = #xLetter]
  44333.         whileTrue: 
  44334.             [t _ token.
  44335.             self xLetter.
  44336.             token _ t , token].
  44337.     token _ token asSymbol!
  44338. scanStringStruct
  44339.  
  44340.     | s |
  44341.     s _ WriteStream on: (Array new: 16).
  44342.     [tokenType = #rightParenthesis or: [tokenType = #doIt]]
  44343.         whileFalse: 
  44344.             [tokenType = #leftParenthesis
  44345.                 ifTrue: 
  44346.                     [self scanToken; scanStringStruct]
  44347.                 ifFalse: 
  44348.                     [tokenType = #word ifFalse:
  44349.                         [^self error: 'only words and parens allowed']].
  44350.             s nextPut: token.
  44351.             self scanToken].
  44352.     token _ s contents!
  44353. scanToken
  44354.  
  44355.     [(tokenType _ typeTable at: hereChar asciiValue) == #xDelimiter]
  44356.         whileTrue: [self step].  "Skip delimiters fast, there almost always is one."
  44357.     mark _ source position - 1.
  44358.     (tokenType at: 1) = $x "x as first letter"
  44359.         ifTrue: [self perform: tokenType "means perform to compute token & type"]
  44360.         ifFalse: [token _ self step asSymbol "else just unique the first char"].
  44361.     ^token!
  44362. step
  44363.  
  44364.     | c |
  44365.     c _ hereChar.
  44366.     hereChar _ aheadChar.
  44367.     source atEnd
  44368.         ifTrue: [aheadChar _ 30 asCharacter "doit"]
  44369.         ifFalse: [aheadChar _ source next].
  44370.     ^c! !
  44371.  
  44372. !Scanner methodsFor: 'multi-character scans'!
  44373. xBinary
  44374.  
  44375.     tokenType _ #binary.
  44376.     token _ Symbol internCharacter: self step.
  44377.     ((typeTable at: hereChar asciiValue) = #xBinary and: [hereChar ~= $-])
  44378.         ifTrue: [token _ (token , (String with: self step)) asSymbol]!
  44379. xDelimiter
  44380.     "Ignore blanks, etc."
  44381.  
  44382.     self scanToken!
  44383. xDigit
  44384.     "Form a number."
  44385.  
  44386.     tokenType _ #number.
  44387.     (aheadChar = 30 asCharacter and: [source atEnd
  44388.             and:  [source skip: -1. source next ~= 30 asCharacter]])
  44389.         ifTrue: [source skip: -1 "Read off the end last time"]
  44390.         ifFalse: [source skip: -2].
  44391.     token _ Number readFrom: source.
  44392.     self step; step!
  44393. xDollar
  44394.     "Form a Character literal."
  44395.  
  44396.     self step. "pass over $"
  44397.     token _ self step.
  44398.     tokenType _ #number "really should be Char, but rest of compiler doesn't know"!
  44399. xDoubleQuote
  44400.     "Collect a comment."
  44401.  
  44402.     | aStream stopChar |
  44403.     stopChar _ 30 asCharacter.
  44404.     aStream _ WriteStream on: (String new: 200).
  44405.     self step.
  44406.     [aStream nextPut: self step. hereChar == $"]
  44407.         whileFalse: 
  44408.             [(hereChar == stopChar and: [source atEnd])
  44409.                 ifTrue: [^self offEnd: 'Unmatched comment quote']].
  44410.     self step.
  44411.     currentComment == nil
  44412.         ifTrue: [currentComment _ OrderedCollection with: aStream contents]
  44413.         ifFalse: [currentComment add: aStream contents].
  44414.     self scanToken!
  44415. xLetter
  44416.     "Form a word or keyword."
  44417.  
  44418.     | type |
  44419.     buffer reset.
  44420.     [(type _ typeTable at: hereChar asciiValue) == #xLetter or: [type == #xDigit]]
  44421.         whileTrue:
  44422.             ["open code step for speed"
  44423.             buffer nextPut: hereChar.
  44424.             hereChar _ aheadChar.
  44425.             source atEnd
  44426.                 ifTrue: [aheadChar _ 30 asCharacter "doit"]
  44427.                 ifFalse: [aheadChar _ source next]].
  44428.     type == #colon
  44429.         ifTrue: 
  44430.             [buffer nextPut: self step.
  44431.             tokenType _ #keyword]
  44432.         ifFalse: 
  44433.             [tokenType _ #word].
  44434.     token _ buffer contents!
  44435. xLitQuote
  44436.     "UniqueStrings and vectors: #(1 (4 5) 2 3) #ifTrue:ifFalse:.
  44437.      For ##x answer #x->nil.  For ###x answer nil->#x."
  44438.  
  44439.     | start |
  44440.     self step. "litQuote"
  44441.     self scanToken.
  44442.     tokenType = #leftParenthesis
  44443.         ifTrue: 
  44444.             [start _ mark.
  44445.             self scanToken; scanLitVec.
  44446.             tokenType == #doIt
  44447.                 ifTrue: [mark _ start.
  44448.                         self offEnd: 'Unmatched parenthesis']]
  44449.         ifFalse: 
  44450.             [(#(word keyword colon ) includes: tokenType) 
  44451.                 ifTrue:
  44452.                     [self scanLitWord]
  44453.                 ifFalse:
  44454.                     [(tokenType==#literal)
  44455.                         ifTrue:
  44456.                             [(token isMemberOf: Association)
  44457.                                 ifTrue: "###word"
  44458.                                     [token _ nil->token key].
  44459.                             (token isMemberOf: Symbol)
  44460.                                 ifTrue: "##word"
  44461.                                     [token _ token->nil]]]].
  44462.     tokenType _ #literal
  44463.  
  44464. "    #(Pen)
  44465.     #Pen
  44466.     ##Pen
  44467.     ###Pen
  44468. "!
  44469. xSingleQuote
  44470.     "String."
  44471.  
  44472.     self step.
  44473.     buffer reset.
  44474.     [hereChar = $' 
  44475.         and: [aheadChar = $' 
  44476.                 ifTrue: [self step. false]
  44477.                 ifFalse: [true]]]
  44478.         whileFalse: 
  44479.             [buffer nextPut: self step.
  44480.             (hereChar = 30 asCharacter and: [source atEnd])
  44481.                 ifTrue: [^self offEnd: 'Unmatched string quote']].
  44482.     self step.
  44483.     token _ buffer contents.
  44484.     tokenType _ #string! !
  44485.  
  44486. !Scanner methodsFor: 'error handling'!
  44487. notify: string 
  44488.     "Refer to the comment in Object|notify:." 
  44489.     self error: string!
  44490. offEnd: aString 
  44491.     "Parser overrides this"
  44492.  
  44493.     ^self notify: aString! !
  44494. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  44495.  
  44496. Scanner class
  44497.     instanceVariableNames: ''!
  44498.  
  44499. !Scanner class methodsFor: 'class initialization'!
  44500. initialize
  44501.  
  44502.     | newTable |
  44503.     newTable _ Array new: 256 withAll: #xBinary. "default"
  44504.     newTable atAll: #(9 10 12 13 32 ) put: #xDelimiter. "tab lf ff cr space"
  44505.     newTable atAll: ($0 asciiValue to: $9 asciiValue) put: #xDigit.
  44506.     newTable atAll: ($A asciiValue to: $Z asciiValue) put: #xLetter.
  44507.     newTable atAll: ($a asciiValue to: $z asciiValue) put: #xLetter.
  44508.     newTable at: 30 put: #doIt.
  44509.     newTable at: $" asciiValue put: #xDoubleQuote.
  44510.     newTable at: $# asciiValue put: #xLitQuote.
  44511.     newTable at: $$ asciiValue put: #xDollar.
  44512.     newTable at: $' asciiValue put: #xSingleQuote.
  44513.     newTable at: $( asciiValue put: #leftParenthesis.
  44514.     newTable at: $) asciiValue put: #rightParenthesis.
  44515.     newTable at: $. asciiValue put: #period.
  44516.     newTable at: $: asciiValue put: #colon.
  44517.     newTable at: $; asciiValue put: #semicolon.
  44518.     newTable at: $[ asciiValue put: #leftBracket.
  44519.     newTable at: $] asciiValue put: #rightBracket.
  44520.     newTable at: ${ asciiValue put: #leftBrace.
  44521.     newTable at: $} asciiValue put: #rightBrace.
  44522.     newTable at: $^ asciiValue put: #upArrow.
  44523.     newTable at: $_ asciiValue put: #leftArrow.
  44524.     newTable at: $| asciiValue put: #verticalBar.
  44525.     TypeTable _ newTable "bon voyage!!"
  44526.  
  44527.     "Scanner initialize"! !
  44528.  
  44529. !Scanner class methodsFor: 'instance creation'!
  44530. new
  44531.  
  44532.     ^super new initScanner! !
  44533.  
  44534. !Scanner class methodsFor: 'testing'!
  44535. isLiteralSymbol: aSymbol 
  44536.     "Test whether a symbol can be stored as # followed by its characters.  
  44537.     Symbols created internally with asSymbol may not have this property, 
  44538.     e.g. '3' asSymbol."
  44539.  
  44540.     | i ascii type |
  44541.     i _ aSymbol size.
  44542.     i = 0 ifTrue: [^false].
  44543.     ascii _ (aSymbol at: 1) asciiValue.
  44544.     "TypeTable should have been origined at 0 rather than 1 ..."
  44545.     ascii = 0 ifTrue: [^false].
  44546.     type _ TypeTable at: ascii.
  44547.     (type == #colon or: [type == #verticalBar])
  44548.         ifTrue: [^i = 1].
  44549.     type == #xBinary
  44550.         ifTrue: 
  44551.             [[i > 1]
  44552.                 whileTrue: 
  44553.                     [ascii _ (aSymbol at: i) asciiValue.
  44554.                     ascii = 0 ifTrue: [^false].
  44555.                     (TypeTable at: ascii) == #xBinary ifFalse: [^false].
  44556.                     i _ i - 1].
  44557.             ^true].
  44558.     type == #xLetter
  44559.         ifTrue: 
  44560.             [[i > 1]
  44561.                 whileTrue: 
  44562.                     [ascii _ (aSymbol at: i) asciiValue.
  44563.                     ascii = 0 ifTrue: [^false].
  44564.                     type _ TypeTable at: ascii.
  44565.                     (type == #xLetter or: [type == #xDigit or: [type == #colon]])
  44566.                         ifFalse: [^false].
  44567.                     i _ i - 1].
  44568.             ^true].
  44569.     ^false! !
  44570.  
  44571. Scanner initialize!
  44572. MouseMenuController subclass: #ScreenController
  44573.     instanceVariableNames: ''
  44574.     classVariableNames: 'HelpMenu TopScreenMenu OpenMenu ChangesMenu WindowMenu ProjectScreenMenu '
  44575.     poolDictionaries: ''
  44576.     category: 'Interface-Support'!
  44577. ScreenController comment:
  44578. 'I am the controller for the parts of the display screen that have no view on them. I only provide a standard yellow button menu. I view (a FormView of) an infinite gray form.'!
  44579.  
  44580. !ScreenController methodsFor: 'initialize-release'! !
  44581.  
  44582. !ScreenController methodsFor: 'control defaults'!
  44583. isControlActive
  44584.  
  44585.     ^super isControlActive and: [sensor anyButtonPressed]!
  44586. isControlWanted
  44587.  
  44588.     ^super isControlWanted and: [sensor anyButtonPressed]! !
  44589.  
  44590. !ScreenController methodsFor: 'menu messages'!
  44591. aboutThisSystem 
  44592.     "Identify software version.  1/17/96 sw"
  44593.  
  44594.     ^ self inform: Smalltalk version!
  44595. blueButtonActivity
  44596.     self yellowButtonActivity!
  44597. browseChangedMessages
  44598.     "Browse all methods in the current change set.  1/18/96 sw"
  44599.  
  44600.     Smalltalk browseChangesAndAdditions!
  44601. browsePostSnapshotChanges
  44602.     "Open a changelist browser on changes submitted since the last snapshot.  5/8/96 sw"
  44603.  
  44604.     ChangeList browseRecentLog!
  44605. browseRecentChanges
  44606.     "Open a changelist browser on the tail end of the changes log"
  44607.  
  44608.     ChangeList browseRecent: 5000!
  44609. browseRecentLog
  44610.     "Open a changelist browser on changes submitted since the last snapshot.  1/17/96 sw"
  44611.  
  44612.     ChangeList browseRecentLog!
  44613. browseRecentSubmissions
  44614.     "Open a method-list browser on recently-submitted methods.  5/16/96 sw"
  44615.  
  44616.     Utilities browseRecentSubmissions!
  44617. closeUnchangedWindows
  44618.     "Close any window that doesn't have unaccepted input.  1/12/97 sw."
  44619.  
  44620.     | oneModel clean |
  44621.  
  44622.     "ScreenController indicateWindowsWithUnacceptedInput"
  44623.  
  44624.     true ifTrue: [^ self notYetImplemented].
  44625.     self flag: #noteToDan.
  44626.     "Dan -- I tried a couple of things in an attempt to find a wholesale way to close all windows that didn't have unsubmitted changes them -- the idea is that sometimes one gets a screen full of dozens of windows from some furious investigation, and wants just to see the last of most of them.  The code below appeared to do the right thing except that in the end the old windows stayed around as garbage, and I dropped this effort before figuring out what I'm doing wrong.  2/5/96 sw"
  44627.  
  44628.     clean _ ScheduledControllers scheduledControllers select:
  44629.         [:contr | contr modelUnchanged].
  44630.  
  44631.     clean do:
  44632.         [:contr | contr closeAndUnschedule].
  44633.     self restoreDisplay!
  44634. collapseAll
  44635.     "Collapses all open windows"
  44636.     ScheduledControllers scheduledControllers do:
  44637.         [:controller | controller == self ifFalse:
  44638.             [controller view isCollapsed ifFalse:
  44639.                     [controller collapse.
  44640.                     controller view deEmphasize]]]!
  44641. commonRequests 
  44642.     "Put up a popup of common requests, and perform whatever the user request.  2/1/96 sw"
  44643.     Utilities offerCommonRequests!
  44644. editPreferences
  44645.     "Open up a Preferences inspector.  2/7/96 sw"
  44646.  
  44647.     Preferences openPreferencesInspector!
  44648. emergencyCollapse
  44649.     "Emergency collapse of a selected window"
  44650.     | controller |
  44651.     (controller _ ScheduledControllers windowFromUser) notNil
  44652.         ifTrue:
  44653.             [controller collapse.
  44654.             controller view deEmphasize]!
  44655. exitProject 
  44656.     "Leave the current Project and enter the Project in which the receiver's 
  44657.     view is scheduled."
  44658.  
  44659.     Project current exit!
  44660. expandAll
  44661.     "Reopens all collapsed windows"
  44662.     ScheduledControllers scheduledControllers reverseDo:
  44663.         [:controller | controller == self ifFalse:
  44664.             [controller view isCollapsed
  44665.                 ifTrue:  [controller view expand]
  44666.                 ifFalse: [controller view displayDeEmphasized]]]!
  44667. fastWindows
  44668.     StandardSystemView doCacheBits!
  44669. fileOutChanges 
  44670.     "File out changes to a file whose name is a functon of the current date and time.  1/8/96 sw, 1/18/96 sw, 1/31/96 sw"
  44671.  
  44672.     Smalltalk changes fileOut.
  44673.     self showInTranscript: 'Changes filed out ', Date dateAndTimeNow printString!
  44674. findWindow
  44675.     "Put up a menu of all windows on the screen, and let the user select one.
  44676.      1/18/96 sw: the real work devolved to ControlManager>>findWindowSatisfying:"
  44677.  
  44678.     ScheduledControllers findWindowSatisfying: [:c | true]!
  44679. garbageCollect
  44680.     "Do a garbage collection, and report results to the user.  2/1/96 sw
  44681.      5/10/96 sw: nicer display, as per JM's suggestion"
  44682.  
  44683.     self inform: Utilities garbageCollectReportString!
  44684. hyperSqueakMenu 
  44685.     "Put up a popup of HyperSqueak-related menu items.  7/24/96 sw"
  44686.  
  44687.     (Smalltalk at: #SqueakSupport ifAbsent: [^ self beep]) offerHyperSqueakMenu!
  44688. indicateWindowsWithUnacceptedInput
  44689.     "Put up a list of windows with unaccepted input, and let the user chose one to activate.  1/18/96 sw.  2/22/96 sw: use hasUnacceptedInput"
  44690.  
  44691.     ScheduledControllers findWindowSatisfying:
  44692.         [:contr |  contr model hasUnacceptedInput]!
  44693. modelUnchanged
  44694.     "Answer true if the receiver's model is unchanged, and hence able to be closed.  For the ScreenController, vacuously, we return false, so that no attempt is made to close the poor fellow.  2/5/96 sw"
  44695.  
  44696.     ^ false!
  44697. openBrowser 
  44698.     "Create and schedule a Browser view for browsing code."
  44699.  
  44700.     BrowserView openBrowser!
  44701. openChangeManager
  44702.     "Open a dual change sorter.  For looking at two change sets at once."
  44703.     DualChangeSorter new open!
  44704. openCommandKeyHelp
  44705.     "1/18/96 sw Open a window that explains command-keys"
  44706.  
  44707.     Utilities openCommandKeyHelp!
  44708. openFileList
  44709.     "Create and schedule a FileList view for specifying files to access."
  44710.  
  44711.     FileList open!
  44712. openProject 
  44713.     "Create and schedule a Project."
  44714.  
  44715.     ProjectView open: Project new!
  44716. openStandardWorkspace
  44717.     "Open a standard, throwaway window chock full of useful expressions.  1/17/96 sw"
  44718.  
  44719.     Utilities openStandardWorkspace!
  44720. openSystemWorkspace
  44721.     StringHolderView openSystemWorkspace!
  44722. openTranscript 
  44723.     "Create and schedule a System Transcript.
  44724.      2/5/96 sw: if there is already one open, then instead of refusing the user permission, just activate the damned thing."
  44725.  
  44726.     (Transcript transcriptOpen)
  44727.         ifTrue: [ScheduledControllers activateTranscript]
  44728.         ifFalse: [Transcript aTranscriptIsOpen.
  44729.                 TextCollectorView open: Transcript label: 'System Transcript']!
  44730. openWorkspace 
  44731.     "Create and schedule a StringHolderView for use as a workspace."
  44732.  
  44733.     StringHolderView open!
  44734. quit
  44735.     Smalltalk
  44736.         snapshot:
  44737.             (self confirm: 'Save changes before quitting?'
  44738.                 orCancel: [^ self])
  44739.         andQuit: true!
  44740. redButtonActivity
  44741.     self yellowButtonActivity!
  44742. restoreDisplay 
  44743.     "Clear the screen to gray and then redisplay all the scheduled views."
  44744.  
  44745.     Display extent = DisplayScreen actualScreenSize ifFalse:
  44746.         [DisplayScreen startUp.
  44747.         ScheduledControllers unCacheWindows].
  44748.     ScheduledControllers restore!
  44749. saveAs
  44750.     ^ Smalltalk saveAs!
  44751. setAuthorInitials
  44752.     "Put up a dialog allowing the user to specify the author's initials.  5/10/96 sw"
  44753.  
  44754.     | initials reply |
  44755.     initials _ Utilities authorInitials.
  44756.     reply _ FillInTheBlank request: 'New author initals: ' initialAnswer: initials.
  44757.     (reply size > 0 and: [reply ~~ initials]) ifTrue:
  44758.         [Utilities authorInitials: reply.
  44759.         Transcript cr; show: 'author initials are now ', reply]!
  44760. shiftedYellowButtonMessages
  44761.     "Answer an array of message selectors corresponding to the shifted-yellow-button menu for the Screen.  1/18/96 sw
  44762.      1/24/96 sw: added unshiftedYellowButtonActivity
  44763.      2/1/96 sw: common requests"
  44764.  
  44765.     ^ #(editPreferences  collapseAll expandAll indicateWindowsWithUnacceptedInput closeUnchangedWindows
  44766.         openProject exitProject openCommandKeyHelp garbageCollect commonRequests unshiftedYellowButtonActivity)!
  44767. snapshot
  44768.     Smalltalk snapshot: true andQuit: false!
  44769. snapshotAndQuit
  44770.     "Snapshot and quit without bother the user further.  2/4/96 sw"
  44771.  
  44772.     Smalltalk
  44773.         snapshot: true
  44774.         andQuit: true!
  44775. viewGIFImports
  44776.     "Open an inspector on forms imported from GIF files.  7/24/96 sw"
  44777.  
  44778.     Smalltalk viewGIFImports! !
  44779.  
  44780. !ScreenController methodsFor: 'cursor'!
  44781. centerCursorInView
  44782.     "Override so this doesn't happen when taking control"! !
  44783.  
  44784. !ScreenController methodsFor: 'private'! !
  44785.  
  44786. !ScreenController methodsFor: 'nested menus'!
  44787. changesMenu
  44788.     "Answer a menu for changes-related items.  2/4/96 sw
  44789.      5/8/96 sw: divided changelist options into two
  44790.      5/17/96 sw: added browse recent submissions"
  44791.  
  44792.     ChangesMenu == nil ifTrue: 
  44793.         [ChangesMenu _ SelectionMenu labelList:
  44794.         #(    'file out changes'
  44795.             'browse changed methods'
  44796.             'browse recent submissions'
  44797.             'open change sorter'
  44798.             'post-snapshot change log'
  44799.             'recent change log')
  44800.         lines: #(1 4)
  44801.         selections: #(fileOutChanges browseChangedMessages browseRecentSubmissions openChangeManager browsePostSnapshotChanges browseRecentChanges)].
  44802.  
  44803.     ^ ChangesMenu
  44804.  
  44805. "
  44806. ScreenController new changesMenu startUp
  44807. "!
  44808. helpMenu
  44809.     "Answer the help menu to be put up as a screen submenu.  7/24/96 sw"
  44810.  
  44811.     HelpMenu == nil ifTrue:
  44812.         [HelpMenu _ SelectionMenu labelList:
  44813.         #(    'preferences...'
  44814.             'about this system...'
  44815.             'command-key help'
  44816.             'useful expressions'
  44817.             'set author initials...'
  44818.             'view GIF imports'
  44819.             'space left'
  44820.                 )
  44821.         lines: #(1 4)
  44822.         selections: #(editPreferences  aboutThisSystem openCommandKeyHelp openStandardWorkspace setAuthorInitials viewGIFImports garbageCollect)].
  44823.     ^ HelpMenu
  44824.  
  44825. "
  44826. ScreenController new helpMenu startUp
  44827. ScreenController initialize
  44828. "!
  44829. openMenu
  44830.     "Answer a menu for open-related items.  2/4/96 sw
  44831.      5/10/96 sw: useful expressions moved to help menu"
  44832.  
  44833.     OpenMenu == nil ifTrue:
  44834.         [OpenMenu _ SelectionMenu labelList:
  44835.         #(    'open browser'
  44836.             'open workspace'
  44837.             'open file list'
  44838.             'open project'
  44839.             'open transcript'
  44840.             'open system workspace')
  44841.         selections: #(openBrowser openWorkspace openFileList openProject openTranscript  openSystemWorkspace)].
  44842.     ^ OpenMenu
  44843.  
  44844. "
  44845. ScreenController new openMenu startUp
  44846. "!
  44847. projectScreenMenu
  44848.     "Answer the project screen menu.   7/23/96 sw
  44849.      7/24/96 sw: remove misc menu thing"
  44850.  
  44851.     ProjectScreenMenu == nil ifTrue:
  44852.         [ProjectScreenMenu _ SelectionMenu labelList:
  44853.         #(    'exit project'
  44854.             'restore display'
  44855.             'open...'
  44856.             'changes...'
  44857.             'window...'
  44858.             'help...'
  44859.             'do...'
  44860.             'save'
  44861.             'save as...'
  44862.             'quit...')
  44863.         lines: #(2 7)
  44864.         selections: #(exitProject restoreDisplay openMenu changesMenu windowMenu helpMenu commonRequests  snapshot saveAs quit)].
  44865.     ^ ProjectScreenMenu
  44866.  
  44867. "
  44868. ScreenController new projectScreenMenu startUp
  44869. "!
  44870. topScreenMenu
  44871.     "Answer the screen menu for the top project, from whence there is no relevance to the 'exit project' item.  7/24/96 sw"
  44872.  
  44873.     TopScreenMenu == nil ifTrue:
  44874.         [TopScreenMenu _ SelectionMenu labelList:
  44875.         #(    'restore display'
  44876.             'open...'
  44877.             'changes...'
  44878.             'window...'
  44879.             'help...'
  44880.             'do...'
  44881.             'save'
  44882.             'save as...'
  44883.             'quit...')
  44884.         lines: #(1 6)
  44885.         selections: #( restoreDisplay openMenu changesMenu windowMenu helpMenu commonRequests  snapshot saveAs quit)].
  44886.     ^ TopScreenMenu
  44887.  
  44888. "
  44889. ScreenController new newScreenMenu startUp
  44890. "!
  44891. windowMenu
  44892.     "Answer a menu for windows-related items.  2/4/96 sw"
  44893.  
  44894.     WindowMenu == nil ifTrue:
  44895.         [WindowMenu _ SelectionMenu labelList:
  44896.         #(    'find window...'
  44897.             'find changed windows...'
  44898.             'collapse all windows'
  44899.             'expand all windows'
  44900.             'close unchanged windows'
  44901.             'fast windows')
  44902.         lines: #(2 4)
  44903.         selections: #(findWindow indicateWindowsWithUnacceptedInput collapseAll expandAll  closeUnchangedWindows fastWindows)].
  44904.     ^ WindowMenu
  44905.  
  44906. "
  44907. ScreenController new windowMenu startUp
  44908. "!
  44909. yellowButtonActivity
  44910.     "Put up the alternate yellow button activity if appropriate, else defer to the old way.  2/7/96 sw
  44911.      5/8/96 sw: if shift key down, do find window.
  44912.      7/23/96 sw: project screen menu different from regular (top) screen menu"
  44913.  
  44914.     | reply aMenu |
  44915.     Sensor leftShiftDown ifTrue: [^ self findWindow].
  44916.  
  44917.     aMenu _ Project current isTopProject
  44918.         ifFalse:
  44919.             [self projectScreenMenu]
  44920.         ifTrue:
  44921.             [self topScreenMenu].
  44922.     (reply _ aMenu startUp) isNil ifTrue: [^ super controlActivity].
  44923.     (#(changesMenu helpMenu openMenu windowMenu miscMenu) includes: reply)
  44924.         ifTrue:  "submenu called for"
  44925.             [reply _ (self perform: reply) startUp.
  44926.             reply == nil ifTrue: [^ super controlActivity]].
  44927.     ^ self perform: reply! !
  44928. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  44929.  
  44930. ScreenController class
  44931.     instanceVariableNames: ''!
  44932.  
  44933. !ScreenController class methodsFor: 'class initialization'!
  44934. initialize
  44935.     "Initialize the screen menus.  Call this method to reset everything back to nil, so that the various menu retrieval methods will duly reinitialize them.  7/24/96 sw"
  44936.  
  44937.     "ScreenController initialize"
  44938.     ChangesMenu _ HelpMenu _ TopScreenMenu _ OpenMenu _ WindowMenu _ ProjectScreenMenu _ nil!
  44939. installScottsScreenMenu
  44940.     "Install the variant of the screen menu preferred by Scott.  To restore the standard version, just set the TopScreenMenu class variable back to nil, or call ScreenController revertToStandardMenus, which does just that. 7/24/96 sw"
  44941.  
  44942.     "ScreenController installScottsScreenMenu"
  44943.     TopScreenMenu _ SelectionMenu labelList:
  44944.         #('HyperSqueak...'
  44945.             'restore display'
  44946.             'open...'
  44947.             'changes...'
  44948.             'window...'
  44949.             'help...'
  44950.             'do...'
  44951.             'save'
  44952.             'save as...'
  44953.             'save and quit'
  44954.             'quit...')
  44955.         lines: #(1 2 7)
  44956.         selections: #(hyperSqueakMenu restoreDisplay openMenu changesMenu windowMenu helpMenu commonRequests  snapshot saveAs snapshotAndQuit quit).
  44957.  
  44958.     ProjectScreenMenu _ SelectionMenu labelList:
  44959.         #('HyperSqueak...'
  44960.             'exit project'
  44961.             'restore display'
  44962.             'open...'
  44963.             'changes...'
  44964.             'window...'
  44965.             'help...'
  44966.             'do...'
  44967.             'save'
  44968.             'save as...'
  44969.             'quit...')
  44970.         lines: #(1 3 8)
  44971.         selections: #(hyperSqueakMenu exitProject restoreDisplay openMenu changesMenu windowMenu helpMenu commonRequests  snapshot saveAs quit)!
  44972. revertToStandardMenus
  44973.     "Restore the standard version of the screen menu, after it has been changed by some nonconformist.  7/24/96 sw"
  44974.  
  44975.     ProjectScreenMenu _ TopScreenMenu _ nil
  44976.  
  44977.     "ScreenController revertToStandardMenus"! !
  44978.  
  44979. ScreenController initialize!
  44980. MouseMenuController subclass: #ScrollController
  44981.     instanceVariableNames: 'scrollBar marker savedArea menuBar savedMenuBarArea '
  44982.     classVariableNames: ''
  44983.     poolDictionaries: ''
  44984.     category: 'Interface-Support'!
  44985. ScrollController comment:
  44986. 'I represent control for scrolling using a scrollBar. I am a MouseMenuController that creates a scrollBar, rather than menus. My subclasses add the button menus. I keep control as long as the cursor is inside the view or the scrollBar area.
  44987.     
  44988. A scrollBar is a rectangular area representing the length of the information being viewed. It contains an inner rectangle whose top y-coordinate represents the relative position of the information visible on the screen with respect to all of the information, and whose size represents the relative amount of that information visible on the screen. The user controls which part of the information is visible by pressing the red button. If the cursor is to the right of the inner rectangle, the window onto the visible information moves upward, if the cursor is to the left, the window moves downward, and if the cursor is inside, the inner rectangle is grabbed and moved to a desired position.'!
  44989.  
  44990. !ScrollController methodsFor: 'initialize-release'!
  44991. initialize
  44992.     super initialize.
  44993.     scrollBar _ Quadrangle new.
  44994.     scrollBar borderWidthLeft: 2 right: 0 top: 2 bottom: 2.
  44995.     marker _ Quadrangle new.
  44996.     marker insideColor: Color gray.
  44997.     menuBar _ Quadrangle new.
  44998.     menuBar borderWidthLeft:  2 right: 0 top: 2 bottom: 2.! !
  44999.  
  45000. !ScrollController methodsFor: 'basic control sequence'!
  45001. controlInitialize
  45002.     "Recompute scroll bars.  Save underlying image unless it is already saved."
  45003.     | yellowBar |
  45004.     super controlInitialize.
  45005.     scrollBar region: (0 @ 0 extent: 44 @ view apparentDisplayBox height).
  45006.     scrollBar insideColor: view backgroundColor.
  45007.     marker region: self computeMarkerRegion.
  45008.     scrollBar _ scrollBar align: scrollBar topRight with: view apparentDisplayBox topLeft.
  45009.     marker _ marker align: marker topCenter with: self upDownLine @ (scrollBar top + 2).
  45010.     savedArea isNil ifTrue: [savedArea _ Form fromDisplay: scrollBar].
  45011.     scrollBar displayOn: Display.
  45012.  
  45013.     "Show a border around yellow-button (menu) region"
  45014. "
  45015.     yellowBar _ Rectangle left: self yellowLine right: scrollBar right + 1
  45016.         top: scrollBar top bottom: scrollBar bottom.
  45017.     Display border: yellowBar width: 1 mask: Form veryLightGray.
  45018. "
  45019.     self moveMarker
  45020. !
  45021. controlTerminate
  45022.  
  45023.     super controlTerminate.
  45024.     savedArea notNil     
  45025.         ifTrue: 
  45026.             [savedArea displayOn: Display at: scrollBar topLeft.
  45027.             savedArea _ nil].! !
  45028.  
  45029. !ScrollController methodsFor: 'control defaults'!
  45030. controlActivity
  45031.     self scrollBarContainsCursor
  45032.                 ifTrue: [self scroll]
  45033.                 ifFalse: [super controlActivity]!
  45034. isControlActive 
  45035.     | fullArea |
  45036.     view isNil ifTrue: [^ false].
  45037.     fullArea _ view insetDisplayBox merge: scrollBar.
  45038.     ^ fullArea containsPoint: sensor cursorPoint!
  45039. isControlWanted
  45040.  
  45041.     ^self viewHasCursor! !
  45042.  
  45043. !ScrollController methodsFor: 'scrolling'!
  45044. anyButtonActivity
  45045.     "deal with red button down in scrollBar beyond yellowLine"
  45046.  
  45047.     self yellowButtonActivity!
  45048. downLine
  45049.     "if cursor before downLine, display down cursor and scroll down on button down"
  45050.  
  45051.     ^scrollBar left + 10 !
  45052. scroll
  45053.     "Check to see whether the user wishes to jump, scroll up, or scroll down."
  45054.     | savedCursor |
  45055.     savedCursor _ sensor currentCursor.
  45056.             [self scrollBarContainsCursor]
  45057.                 whileTrue: 
  45058.                     [Processor yield.
  45059.                     sensor cursorPoint x <= self downLine
  45060.                                 ifTrue: [self scrollDown]
  45061.                                 ifFalse: [sensor cursorPoint x <= self upLine
  45062.                                         ifTrue: [self scrollAbsolute]
  45063.                                         ifFalse: [sensor cursorPoint x <= self yellowLine
  45064.                                                 ifTrue: [self scrollUp]
  45065.                                                 ifFalse: [self changeCursor: Cursor menu.
  45066.                                                         sensor anyButtonPressed 
  45067.                                                         ifTrue: [self changeCursor: savedCursor. 
  45068.                                                                 self anyButtonActivity]]]]].
  45069.     savedCursor show!
  45070. scrollAmount
  45071.     "Answer the number of bits of y-coordinate should be scrolled. This is a 
  45072.     default determination based on the view's preset display transformation."
  45073.  
  45074.     ^((view inverseDisplayTransform: sensor cursorPoint)
  45075.         - (view inverseDisplayTransform: scrollBar inside topCenter)) y!
  45076. scrollView
  45077.     "The scroll bar jump method was used so that the view should be 
  45078.     updated to correspond to the location of the scroll bar gray area.
  45079.     Return true only if scrolling took place."
  45080.     ^ self scrollView: self viewDelta!
  45081. scrollView: anInteger 
  45082.     "Tell the reciever's view to scroll by anInteger amount.
  45083.     Return true only if scrolling actually resulted."
  45084.     (view scrollBy: 0 @ 
  45085.                 ((anInteger min: view window top - view boundingBox top)
  45086.                         max: view window top - view boundingBox bottom))
  45087.         ifTrue: [view clearInside; display.  ^ true]
  45088.         ifFalse: [^ false]!
  45089. scrollViewDown
  45090.     "Scroll the receiver's view down the default amount.
  45091.     Return true only if scrolling actually took place."
  45092.     ^ self scrollView: self scrollAmount!
  45093. scrollViewUp
  45094.     "Scroll the receiver's view up the default amount.
  45095.     Return true only if scrolling actually took place."
  45096.     ^ self scrollView: self scrollAmount negated!
  45097. upDownLine
  45098.     "Check to see whether the user wishes to jump, scroll up, or scroll down."
  45099.  
  45100.     ^scrollBar left + 18 !
  45101. upLine
  45102.     "if cursor beyond upLine, display up cursor and scroll up on button down"
  45103.  
  45104.     ^scrollBar left + 20 !
  45105. viewDelta
  45106.     "Answer an integer that indicates how much the view should be scrolled. 
  45107.     The scroll bar has been moved and now the view must be so the amount 
  45108.     to scroll is computed as a ratio of the current scroll bar position."
  45109.  
  45110.     ^view window top - view boundingBox top -
  45111.         ((marker top - scrollBar inside top) asFloat /
  45112.             scrollBar inside height asFloat *
  45113.                 view boundingBox height asFloat) rounded!
  45114. yellowLine
  45115.     "Check to see whether the user wishes to jump, scroll up, or scroll down."
  45116.  
  45117.     ^scrollBar left + 30 "8"! !
  45118.  
  45119. !ScrollController methodsFor: 'cursor'!
  45120. changeCursor: aCursor 
  45121.     "The current cursor should be set to be aCursor."
  45122.  
  45123.     sensor currentCursor ~~ aCursor ifTrue: [aCursor show]!
  45124. markerContainsCursor
  45125.     "Answer whether the gray area inside the scroll bar area contains the 
  45126.     cursor."
  45127.  
  45128.     ^marker inside containsPoint: sensor cursorPoint!
  45129. menuBarContainsCursor
  45130.     "Answer whether the cursor is anywhere within the menu bar area."
  45131.  
  45132.     ^ menuBar notNil and:
  45133.             [menuBar containsPoint: sensor cursorPoint]!
  45134. scrollBarContainsCursor
  45135.     "Answer whether the cursor is anywhere within the scroll bar area."
  45136.  
  45137.     ^scrollBar containsPoint: sensor cursorPoint! !
  45138.  
  45139. !ScrollController methodsFor: 'marker adjustment'!
  45140. computeMarkerRegion
  45141.     "Answer the rectangular area in which the gray area of the scroll bar 
  45142.     should be displayed."
  45143.  
  45144.     ^0@0 extent: 10 @
  45145.             ((view window height asFloat /
  45146.                         view boundingBox height *
  45147.                             scrollBar inside height)
  45148.                  rounded min: scrollBar inside height)!
  45149. markerDelta
  45150.     ^ marker top 
  45151.         - scrollBar inside top  
  45152.         - ((view window top - view boundingBox top) asFloat 
  45153.             / view boundingBox height asFloat *
  45154.                 scrollBar inside height asFloat) rounded!
  45155. markerRegion: aRectangle 
  45156.     "Set the area defined by aRectangle as the marker. Fill it with gray tone."
  45157.  
  45158.     Display fill: marker fillColor: scrollBar insideColor.
  45159.     marker region: aRectangle.
  45160.     marker _ marker align: marker topCenter with: self upDownLine @ (scrollBar top + 2) !
  45161. moveMarker
  45162.     "The view window has changed. Update the marker."
  45163.  
  45164.     self moveMarker: self markerDelta negated anchorMarker: nil!
  45165. moveMarker: anInteger anchorMarker: anchorMarker
  45166.     "Update the marker so that is is translated by an amount corresponding to 
  45167.     a distance of anInteger, constrained within the boundaries of the scroll 
  45168.     bar.  If anchorMarker ~= nil, display the border around the area where the
  45169.     marker first went down."
  45170.  
  45171.     Display fill: marker fillColor: scrollBar insideColor.
  45172.     anchorMarker = nil
  45173.         ifFalse: [Display border: anchorMarker width: 1 fillColor: Color gray].
  45174.     marker _ marker translateBy: 0 @
  45175.                 ((anInteger min: scrollBar inside bottom - marker bottom) max:
  45176.                     scrollBar inside top - marker top).
  45177.     marker displayOn: Display!
  45178. moveMarkerTo: aRectangle 
  45179.     "Same as markerRegion: aRectangle; moveMarker, except a no-op if the marker
  45180.      would not move."
  45181.  
  45182.     (aRectangle height = marker height and: [self viewDelta = 0]) ifFalse:
  45183.         [self markerRegion: aRectangle.
  45184.         self moveMarker]! !
  45185.  
  45186. !ScrollController methodsFor: 'private'!
  45187. scrollAbsolute
  45188.     | markerOutline oldY markerForm |
  45189.     self changeCursor: Cursor rightArrow.
  45190.  
  45191.     oldY _ -1.
  45192.     sensor anyButtonPressed ifTrue: 
  45193.       [markerOutline _ marker deepCopy.
  45194.       markerForm _ Form fromDisplay: marker.
  45195.       Display fill: marker fillColor: scrollBar insideColor.
  45196.       Display border: markerOutline width: 1 fillColor: Color gray.
  45197.       markerForm 
  45198.         follow: 
  45199.             [oldY ~= sensor cursorPoint y
  45200.                 ifTrue: 
  45201.                     [oldY _ sensor cursorPoint y.
  45202.                     marker _ marker translateBy: 
  45203.                       0 @ ((oldY - marker center y 
  45204.                         min: scrollBar inside bottom - marker bottom) 
  45205.                         max: scrollBar inside top - marker top).
  45206.                     self scrollView].
  45207.                 marker origin] 
  45208.         while: [sensor anyButtonPressed].
  45209.  
  45210.       Display fill: markerOutline fillColor: scrollBar insideColor.
  45211.       self moveMarker]!
  45212. scrollDown
  45213.     | markerForm firstTime |
  45214.     self changeCursor: Cursor down.
  45215.     sensor anyButtonPressed ifTrue:
  45216.       [markerForm _ Form fromDisplay: marker.
  45217.       Display fill: marker fillColor: scrollBar insideColor.
  45218.       firstTime _ true.
  45219.       markerForm 
  45220.         follow: 
  45221.             [self scrollViewDown ifTrue:
  45222.                 [marker _ marker translateBy: 0 @
  45223.                     ((self markerDelta negated 
  45224.                         min: scrollBar inside bottom - marker bottom) 
  45225.                         max: scrollBar inside top - marker top).
  45226.                 firstTime
  45227.                     ifTrue: [
  45228.                         "pause before scrolling repeatedly"
  45229.                         (Delay forMilliseconds: 250) wait.
  45230.                         firstTime _ false.
  45231.                     ] ifFalse: [
  45232.                         (Delay forMilliseconds: 50) wait.
  45233.                     ].
  45234.                 ].
  45235.             marker origin] 
  45236.         while: [sensor anyButtonPressed].
  45237.       self moveMarker.]!
  45238. scrollUp
  45239.     | markerForm firstTime |
  45240.     self changeCursor: Cursor up.
  45241.     sensor anyButtonPressed ifTrue:
  45242.       [markerForm _ Form fromDisplay: marker.
  45243.       Display fill: marker fillColor: scrollBar insideColor.
  45244.       firstTime _ true.
  45245.       markerForm 
  45246.         follow: 
  45247.             [self scrollViewUp ifTrue:
  45248.                 [marker _ marker translateBy: 0 @
  45249.                     ((self markerDelta negated 
  45250.                         min: scrollBar inside bottom - marker bottom) 
  45251.                         max: scrollBar inside top - marker top).
  45252.                 firstTime
  45253.                     ifTrue: [
  45254.                         "pause before scrolling repeatedly"
  45255.                         (Delay forMilliseconds: 250) wait.
  45256.                         firstTime _ false.
  45257.                     ] ifFalse: [
  45258.                         (Delay forMilliseconds: 50) wait.
  45259.                     ].
  45260.                 ].
  45261.             marker origin] 
  45262.         while: [sensor anyButtonPressed].
  45263.       self moveMarker.]! !PopUpMenu subclass: #SelectionMenu
  45264.     instanceVariableNames: 'selections '
  45265.     classVariableNames: ''
  45266.     poolDictionaries: ''
  45267.     category: 'Interface-Menus'!
  45268.  
  45269. !SelectionMenu methodsFor: 'initialization'!
  45270. startUpWithCaption: captionOrNil
  45271.     "Overridden to return inner values from manageMarker"
  45272.     | selectedItem |
  45273.     self displayAt: Sensor cursorPoint 
  45274.         withCaption: captionOrNil
  45275.         during: [Sensor cursorPoint: marker center.
  45276.                 [Sensor anyButtonPressed] whileFalse: [].
  45277.                 [Sensor anyButtonPressed]
  45278.                     whileTrue: [selectedItem _ self manageMarker]].
  45279.     ^ selectedItem! !
  45280.  
  45281. !SelectionMenu methodsFor: 'access'!
  45282. selections
  45283.  
  45284.     ^ selections!
  45285. selections: selectionArray
  45286.     selections _ selectionArray! !
  45287.  
  45288. !SelectionMenu methodsFor: 'marker management'!
  45289. manageMarker
  45290.     "Returns the selected item, or else the last selection
  45291.     2/4/96 sw: if no selection, return nil"
  45292.  
  45293.     super manageMarker.
  45294.     selection = 0 ifTrue: [^ nil].
  45295.     ^ selections at: selection! !
  45296. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  45297.  
  45298. SelectionMenu class
  45299.     instanceVariableNames: ''!
  45300.  
  45301. !SelectionMenu class methodsFor: 'instance creation'!
  45302. labelList: labelList lines: lines selections: selections
  45303.     ^ self labels: (String streamContents:
  45304.             [:strm |  "Concatenate labels with CRs"
  45305.             labelList do: [:each | strm nextPutAll: each; cr].
  45306.             strm skip: -1])  "No CR at end"
  45307.         lines: lines selections: selections!
  45308. labelList: labelList selections: selections
  45309.     ^ self labelList: labelList lines: nil selections: selections
  45310. !
  45311. labels: labels lines: lines selections: selections
  45312.     "Note that the last item in selections will be returned on menu aborts"
  45313.     ^ (self labels: labels lines: lines) selections: selections!
  45314. labels: labels selections: selections
  45315.     ^ self labels: labels lines: nil selections: selections!
  45316. selections: aList
  45317.     "Create a Selection menu whose labels and selections are identical.  6/27/96 sw"
  45318.  
  45319.     ^ self labelList: aList lines: nil selections: aList! !LeafNode subclass: #SelectorNode
  45320.     instanceVariableNames: ''
  45321.     classVariableNames: ''
  45322.     poolDictionaries: ''
  45323.     category: 'System-Compiler'!
  45324. SelectorNode comment:
  45325. 'I am a parse tree leaf representing a selector.'!
  45326.  
  45327. !SelectorNode methodsFor: 'code generation'!
  45328. emit: stack args: nArgs on: strm
  45329.  
  45330.     self emit: stack
  45331.         args: nArgs
  45332.         on: strm
  45333.         super: false!
  45334. emit: stack args: nArgs on: aStream super: supered
  45335.  
  45336.     | index |
  45337.     stack pop: nArgs.
  45338.     (supered not and: [code - Send < SendLimit and: [nArgs < 3]])
  45339.         ifTrue: 
  45340.             ["short send"
  45341.             aStream nextPut: 
  45342.                     (code < Send
  45343.                         ifTrue: [code]
  45344.                         ifFalse: ["special" nArgs * 16 + code])]
  45345.         ifFalse: 
  45346.             [index _ code < 256 ifTrue: [code - Send] ifFalse: [code \\ 256].
  45347.             (index < 32 and: [nArgs <= 7])
  45348.                 ifTrue: 
  45349.                     ["medium send"
  45350.                     aStream nextPut: SendLong + (supered ifTrue: [2] ifFalse: [0]).
  45351.                     aStream nextPut: nArgs * 32 + index]
  45352.                 ifFalse: 
  45353.                     ["long send"
  45354.                     aStream nextPut: SendLong + 1 + (supered ifTrue: [2] ifFalse: [0]).
  45355.                     aStream nextPut: nArgs.
  45356.                     aStream nextPut: index]]!
  45357. NEWemit: stack args: nArgs on: aStream super: supered
  45358.     "This can be enabled when bytecode 134 has been redefined
  45359.     to be medium length send up to 64 lits"
  45360.     | index |
  45361.     stack pop: nArgs.
  45362.     (supered not and: [code - Send < SendLimit and: [nArgs < 3]])
  45363.         ifTrue: 
  45364.             ["short send"
  45365.             aStream nextPut: 
  45366.                     (code < Send
  45367.                         ifTrue: [code]
  45368.                         ifFalse: ["special" nArgs * 16 + code])]
  45369.         ifFalse: 
  45370.             [index _ code < 256 ifTrue: [code - Send]
  45371.                                 ifFalse: [code \\ 256].
  45372.             (index <= 31 and: [nArgs <= 7])
  45373.                 ifTrue: 
  45374.                     ["medium send [131 and 133]"
  45375.                     aStream nextPut: SendLong
  45376.                                     + (supered ifTrue: [2] ifFalse: [0]).
  45377.                     aStream nextPut: nArgs * 32 + index]
  45378.                 ifFalse: 
  45379.                     [(supered not and: [index <= 63 and: [nArgs <= 3]])
  45380.                         ifTrue: 
  45381.                             [" new medium send [134]"
  45382.                             aStream nextPut: SendLong + 3.
  45383.                             ^ aStream nextPut: nArgs * 64 + index].
  45384.                     "long send"
  45385.                     aStream nextPut: SendLong + 1.
  45386.                     aStream nextPut: nArgs
  45387.                                     + (supered ifTrue: [32] ifFalse: [0]).
  45388.                     aStream nextPut: index]]!
  45389. NEWsize: encoder args: nArgs super: supered
  45390.     "This can be enabled when bytecode 134 has been redefined
  45391.     to be medium length send up to 64 lits"
  45392.     | index |
  45393.     self reserve: encoder.
  45394.     (supered not and: [code - Send < SendLimit and: [nArgs < 3]])
  45395.         ifTrue: [^1]. "short send"
  45396.     (supered and: [code < Send]) ifTrue: 
  45397.         ["super special:"
  45398.         code _ self code: (encoder litIndex: key) type: 5].
  45399.     index _ code < 256
  45400.                 ifTrue: [code - Send]
  45401.                 ifFalse: [code \\ 256].
  45402.     (index <= 31 and: [nArgs <= 7])
  45403.         ifTrue: [^ 2]. "medium send"
  45404.     (supered not and: [index <= 63 and: [nArgs <= 3]])
  45405.         ifTrue: [^ 2]. "new medium send"
  45406.     ^ 3 "long send"!
  45407. size: encoder args: nArgs super: supered
  45408.  
  45409.     | index |
  45410.     self reserve: encoder.
  45411.     (supered not and: [code - Send < SendLimit and: [nArgs < 3]])
  45412.         ifTrue: [^1]. "short send"
  45413.     (supered and: [code < Send])
  45414.         ifTrue: 
  45415.             ["super special:"
  45416.             code _ self code: (encoder litIndex: key) type: 5].
  45417.     index _ code < 256
  45418.                 ifTrue: [code - Send]
  45419.                 ifFalse: [code \\ 256].
  45420.     (index < 32 and: [nArgs <= 7])
  45421.         ifTrue: [^2]. "medium send"
  45422.     ^3 "long send"! !
  45423.  
  45424. !SelectorNode methodsFor: 'printing'!
  45425. printOn: aStream indent: level
  45426.  
  45427.     aStream nextPutAll: key! !
  45428.  
  45429. !SelectorNode methodsFor: 'inappropriate'!
  45430. emitForEffect: stack on: strm
  45431.  
  45432.     self shouldNotImplement!
  45433. emitForValue: stack on: strm
  45434.  
  45435.     self shouldNotImplement!
  45436. sizeForEffect: encoder
  45437.  
  45438.     self shouldNotImplement!
  45439. sizeForValue: encoder
  45440.  
  45441.     self shouldNotImplement! !
  45442.  
  45443. !SelectorNode methodsFor: 'testing'!
  45444. isPvtSelector
  45445.     "Answer if this selector node is a private message selector."
  45446.  
  45447.     ^key isPvtSelector! !
  45448.  
  45449. !SelectorNode methodsFor: 'equation translation'!
  45450. copyReplacingVariables: varDict 
  45451.     ^self copy!
  45452. specificMatch: aTree using: matchDict 
  45453.     ^key = aTree key! !LinkedList subclass: #Semaphore
  45454.     instanceVariableNames: 'excessSignals '
  45455.     classVariableNames: ''
  45456.     poolDictionaries: ''
  45457.     category: 'Kernel-Processes'!
  45458. Semaphore comment:
  45459. 'I provide synchronized communication of a single bit of information (a "signal") between Processes. A signal is sent by sending the message signal and received by sending the message wait. If no signal has been sent when a wait message is sent, the sending Process will be suspended until a signal is sent.'!
  45460.  
  45461. !Semaphore methodsFor: 'initialize-release'!
  45462. initSignals
  45463.     "Consume any excess signals the receiver may have accumulated."
  45464.  
  45465.     excessSignals _ 0.!
  45466. terminateProcess
  45467.     "Terminate the process waiting on this semaphore, if any."
  45468.  
  45469.     self isEmpty ifFalse: [ self removeFirst terminate ].! !
  45470.  
  45471. !Semaphore methodsFor: 'communication'!
  45472. signal
  45473.     "Primitive. Send a signal through the receiver. If one or more processes 
  45474.     have been suspended trying to receive a signal, allow the first one to 
  45475.     proceed. If no process is waiting, remember the excess signal. Essential. 
  45476.     See Object documentation whatIsAPrimitive."
  45477.  
  45478.     <primitive: 85>
  45479.     self primitiveFailed
  45480.  
  45481.     "self isEmpty    
  45482.         ifTrue: [excessSignals _ excessSignals+1]    
  45483.         ifFalse: [Processor resume: self removeFirstLink]"
  45484.  
  45485. !
  45486. wait
  45487.     "Primitive. The active Process must receive a signal through the receiver 
  45488.     before proceeding. If no signal has been sent, the active Process will be 
  45489.     suspended until one is sent. Essential. See Object documentation 
  45490.     whatIsAPrimitive."
  45491.  
  45492.     <primitive: 86>
  45493.     self primitiveFailed
  45494.  
  45495.     "excessSignals>0  
  45496.         ifTrue: [excessSignals _ excessSignals-1]  
  45497.         ifFalse: [self addLastLink: Processor activeProcess suspend]"
  45498. ! !
  45499.  
  45500. !Semaphore methodsFor: 'mutual exclusion'!
  45501. critical: mutuallyExcludedBlock 
  45502.     "Evaluate mutuallyExcludedBlock only if the receiver is not currently in 
  45503.     the process of running the critical: message. If the receiver is, evaluate 
  45504.     mutuallyExcludedBlock after the other critical: message is finished."
  45505.  
  45506.     | blockValue |
  45507.     self wait.
  45508.     blockValue _ mutuallyExcludedBlock value.
  45509.     self signal.
  45510.     ^blockValue! !
  45511. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  45512.  
  45513. Semaphore class
  45514.     instanceVariableNames: ''!
  45515.  
  45516. !Semaphore class methodsFor: 'instance creation'!
  45517. forMutualExclusion
  45518.     "Answer an instance of me that contains a single signal. This new 
  45519.     instance can now be used for mutual exclusion (see the critical: message 
  45520.     to Semaphore)."
  45521.  
  45522.     ^self new signal!
  45523. new
  45524.     "Answer a new instance of Semaphore that contains no signals."
  45525.  
  45526.     ^self basicNew initSignals! !Collection subclass: #SequenceableCollection
  45527.     instanceVariableNames: ''
  45528.     classVariableNames: ''
  45529.     poolDictionaries: ''
  45530.     category: 'Collections-Abstract'!
  45531. SequenceableCollection comment:
  45532. 'I am an abstract superclass for collections that have a well-defined order associated with their elements. Thus each element is externally-named by integers referred to as indices.'!
  45533.  
  45534. !SequenceableCollection methodsFor: 'comparing'!
  45535. = otherCollection
  45536.     "Answer whether the species of the receiver is the same as
  45537.     otherCollection's species, and the receiver's size is the same as
  45538.     otherCollection's size, and each of the receiver's elements equal the
  45539.     corresponding element of otherCollection."
  45540.     | size |
  45541.     (size _ self size) = otherCollection size ifFalse: [^false].
  45542.     self species == otherCollection species ifFalse: [^false].
  45543.     1 to: size do:
  45544.         [:index |
  45545.         (self at: index) = (otherCollection at: index) ifFalse: [^false]].
  45546.     ^true! !
  45547.  
  45548. !SequenceableCollection methodsFor: 'accessing'!
  45549. at: index ifAbsent: exceptionBlock
  45550.     "Answer the element at my position index. If I do not contain an element
  45551.     at index, answer the result of evaluating the argument, exceptionBlock."
  45552.  
  45553.     (index between: 1 and: self size) ifTrue:
  45554.         [^self at: index].
  45555.     ^exceptionBlock value!
  45556. atAll: anInterval put: anObject 
  45557.     "Put anObject at every index specified by the integer elements of 
  45558.     anInterval."
  45559.  
  45560.     anInterval do: [:index | self at: index put: anObject]!
  45561. atAllPut: anObject 
  45562.     "Put anObject at every one of the receiver's indices."
  45563.     1 to: self size do:
  45564.         [:index | self at: index put: anObject]!
  45565. atRandom
  45566.     "Return a random element of myself.  Uses a shared random number generator owned by class Collection.  If you use this a lot, define your own instance of Random and use atRandom:.  Causes an error if self has no elements."
  45567.  
  45568.     | index |
  45569.     index _ (RandomForPicking next * self size) asInteger + 1.
  45570.     ^ self at: index
  45571.  
  45572. "  #('one' 'or' 'the' 'other') atRandom
  45573.    (1 to: 10) atRandom
  45574.    'Just pick one of these letters at random' atRandom
  45575. "!
  45576. atRandom: aGenerator
  45577.     "Return a random element of myself.  Uses the instance of class Random supplied by the caller.  Caller should keep the generator in a variable and use the same one every time.  Use this instead of atRandom for better uniformity of random numbers because only you use the generator.  Causes an error if self has no elements."
  45578.  
  45579.     | index |
  45580.     index _ (aGenerator next * self size) asInteger + 1.
  45581.     ^ self at: index
  45582.  
  45583. "    | aGen |
  45584.     aGen _ Random new.   
  45585.     (1 to: 10) atRandom: aGen
  45586.   
  45587. "!
  45588. first
  45589.     "Answer the first element of the receiver. Create an error notification if 
  45590.     the receiver contains no elements."
  45591.  
  45592.     self emptyCheck.
  45593.     ^self at: 1!
  45594. indexOf: anElement 
  45595.     "Answer the index of anElement within the receiver. If the receiver does 
  45596.     not contain anElement, answer 0."
  45597.  
  45598.     ^self indexOf: anElement ifAbsent: [0]!
  45599. indexOf: anElement ifAbsent: exceptionBlock
  45600.     "Answer the index of anElement within the receiver. If the receiver does 
  45601.     not contain anElement, answer the result of evaluating the argument, 
  45602.     exceptionBlock."
  45603.     1 to: self size do:
  45604.         [:i | (self at: i) = anElement ifTrue: [^ i]].
  45605.     ^ exceptionBlock value!
  45606. indexOfSubCollection: aSubCollection startingAt: anIndex 
  45607.     "Answer the index of the receiver's first element, such that that element 
  45608.     equals the first element of aSubCollection, and the next elements equal 
  45609.     the rest of the elements of aSubCollection. Begin the search at element 
  45610.     anIndex of the receiver. If no such match is found, answer 0."
  45611.  
  45612.     ^self
  45613.         indexOfSubCollection: aSubCollection
  45614.         startingAt: anIndex
  45615.         ifAbsent: [0]!
  45616. indexOfSubCollection: sub startingAt: start ifAbsent: exceptionBlock
  45617.     "Answer the index of the receiver's first element, such that that element 
  45618.     equals the first element of sub, and the next elements equal 
  45619.     the rest of the elements of sub. Begin the search at element 
  45620.     start of the receiver. If no such match is found, answer the result of 
  45621.     evaluating argument, exceptionBlock."
  45622.     | first index |
  45623.     sub isEmpty ifTrue: [^ exceptionBlock value].
  45624.     first _ sub first.
  45625.     start to: self size - sub size + 1 do:
  45626.         [:startIndex |
  45627.         (self at: startIndex) = first ifTrue:
  45628.             [index _ 1.
  45629.             [(self at: startIndex+index-1) = (sub at: index)]
  45630.                 whileTrue:
  45631.                 [index = sub size ifTrue: [^startIndex].
  45632.                 index _ index+1]]].
  45633.     ^ exceptionBlock value!
  45634. last
  45635.     "Answer the last element of the receiver. Create an error notification if 
  45636.     the receiver contains no elements."
  45637.  
  45638.     self emptyCheck.
  45639.     ^self at: self size!
  45640. replaceFrom: start to: stop with: replacement 
  45641.     "This destructively replaces elements from start to stop in the receiver. 
  45642.     Answer the receiver itself. Use copyReplaceFrom:to:with: for 
  45643.     insertion/deletion which may alter the size of the result."
  45644.  
  45645.     replacement size = (stop - start + 1)
  45646.         ifFalse: [self error: 'Size of replacement doesnt match'].
  45647.     ^self replaceFrom: start to: stop with: replacement startingAt: 1!
  45648. replaceFrom: start to: stop with: replacement startingAt: repStart 
  45649.     "This destructively replaces elements from start to stop in the receiver 
  45650.     starting at index, repStart, in the sequenceable collection, 
  45651.     replacementCollection. Answer the receiver. No range checks are 
  45652.     performed."
  45653.  
  45654.     | index repOff |
  45655.     repOff _ repStart - start.
  45656.     index _ start - 1.
  45657.     [(index _ index + 1) <= stop]
  45658.         whileTrue: [self at: index put: (replacement at: repOff + index)]!
  45659. size
  45660.  
  45661.     self subclassResponsibility! !
  45662.  
  45663. !SequenceableCollection methodsFor: 'removing'!
  45664. remove: oldObject ifAbsent: anExceptionBlock 
  45665.     "SequencableCollections cannot implement removing."
  45666.  
  45667.     self shouldNotImplement! !
  45668.  
  45669. !SequenceableCollection methodsFor: 'copying'!
  45670. , aSequenceableCollection 
  45671.     "Answer a copy of the receiver with each element of the argument, 
  45672.     aSequencableCollection, added, in order."
  45673.     
  45674.     ^self copyReplaceFrom: self size + 1
  45675.           to: self size
  45676.           with: aSequenceableCollection!
  45677. copyAt: anIndex put: anElement
  45678.     "Answer a copy of the receiver with anElement inserted at anIndex."
  45679.  
  45680.     ^(self copyFrom: 1 to: anIndex - 1), 
  45681.         (Array with: anElement),
  45682.         (self copyFrom: anIndex to: self size)!
  45683. copyFrom: start to: stop 
  45684.     "Answer a copy of a subset of the receiver, starting from element at 
  45685.     index start until element at index stop."
  45686.  
  45687.     | newSize |
  45688.     newSize _ stop - start + 1.
  45689.     ^(self species new: newSize)
  45690.         replaceFrom: 1
  45691.         to: newSize
  45692.         with: self
  45693.         startingAt: start!
  45694. copyReplaceAll: oldSubstring with: newSubstring 
  45695.     "Default is not to do token matching.
  45696.     See also String copyReplaceTokens:with:"
  45697.     ^ self copyReplaceAll: oldSubstring with: newSubstring asTokens: false
  45698.     "'How now brown cow?' copyReplaceAll: 'ow' with: 'ello'"
  45699.     "'File asFile Files File''s File' copyReplaceTokens: 'File' with: 'Pile'"!
  45700. copyReplaceFrom: start to: stop with: replacementCollection 
  45701.     "Answer a copy of the receiver satisfying the following conditions: If 
  45702.     stop is less than start, then this is an insertion; stop should be exactly 
  45703.     start-1, start = 1 means insert before the first character, start = size+1 
  45704.     means append after last character. Otherwise, this is a replacement; start 
  45705.     and stop have to be within the receiver's bounds."
  45706.  
  45707.     | newSequenceableCollection newSize endReplacement |
  45708.     newSize _ self size - (stop - start + 1) + replacementCollection size.
  45709.     endReplacement _ start - 1 + replacementCollection size.
  45710.     newSequenceableCollection _ self species new: newSize.
  45711.     newSequenceableCollection
  45712.         replaceFrom: 1
  45713.         to: start - 1
  45714.         with: self
  45715.         startingAt: 1.
  45716.     newSequenceableCollection
  45717.         replaceFrom: start
  45718.         to: endReplacement
  45719.         with: replacementCollection
  45720.         startingAt: 1.
  45721.     newSequenceableCollection
  45722.         replaceFrom: endReplacement + 1
  45723.         to: newSize
  45724.         with: self
  45725.         startingAt: stop + 1.
  45726.     ^newSequenceableCollection!
  45727. copyWith: newElement 
  45728.     "Answer a copy of the receiver that is 1 bigger than the receiver and has 
  45729.     newElement at the last element."
  45730.  
  45731.     | newIC |
  45732.     newIC _ self species new: self size + 1.
  45733.     newIC 
  45734.         replaceFrom: 1
  45735.         to: self size
  45736.         with: self
  45737.         startingAt: 1.
  45738.     newIC at: newIC size put: newElement.
  45739.     ^newIC!
  45740. copyWithout: oldElement 
  45741.     "Answer a copy of the receiver in which all occurrences of oldElement 
  45742.     have been left out."
  45743.  
  45744.     | aStream |
  45745.     aStream _ WriteStream on: (self species new: self size).
  45746.     self do: [:each | oldElement = each ifFalse: [aStream nextPut: each]].
  45747.     ^aStream contents!
  45748. copyWithoutAll: aList
  45749.     "Answer a copy of the receiver in which all occurrences of all elements in aList have been removed.  6/17/96 sw"
  45750.  
  45751.     | aStream |
  45752.     aStream _ WriteStream on: (self species new: self size).
  45753.     self do: [:each | (aList includes: each) ifFalse: [aStream nextPut: each]].
  45754.     ^ aStream contents!
  45755. forceTo: length paddingWith: elem
  45756.     "Force the length of the collection to length, padding if necissary
  45757.     with elem.  Note that this makes a copy."
  45758.     | newCollection copyLen |
  45759.     newCollection _ self species new: length.
  45760.     copyLen _ self size.
  45761.     1 to: length do: [ :index |
  45762.         (index <= copyLen) ifTrue: [
  45763.             newCollection at: index put: (self at: index) ]
  45764.         ifFalse: [
  45765.             newCollection at: index put: elem ] ].
  45766.     ^ newCollection!
  45767. shallowCopy
  45768.  
  45769.     ^self copyFrom: 1 to: self size!
  45770. shuffled
  45771.     | copy random max |  "($A to: $Z) shuffled"
  45772.     copy _ self shallowCopy.
  45773.     random _ Random new.
  45774.     max _ self size.
  45775.     1 to: max do: [:i | copy swap: i with: (random next * max) asInteger + 1].
  45776.     ^ copy!
  45777. sortBy: aBlock
  45778.     "Create a copy that is sorted.  Sort criteria is the block that accepts two arguments.  When the block is true, the first arg goes first ([:a :b | a > b] sorts in descending order)."
  45779.     | sorted other |
  45780.     sorted _ (SortedCollection sortBlock: aBlock) addAll: self.
  45781.     other _ self copy.
  45782.     1 to: self size do: [:index |  other at: index put: 
  45783.         (sorted at: index)].
  45784.     ^ other! !
  45785.  
  45786. !SequenceableCollection methodsFor: 'enumerating'!
  45787. adjacent: aBlock2
  45788.     "Evaluate aBlock with adjacent pairs of elements of the receiver. 
  45789.     Collect the resulting values into a collection like the receiver.
  45790.     Answer the new collection."
  45791.     | result |
  45792.     self size < 2 ifTrue: [^ self species new].
  45793.     result _ self species new: self size-1.
  45794.     1 to: self size-1 do:
  45795.         [:index | result at: index put:
  45796.         (aBlock2 value: (self at: index)
  45797.                 value: (self at: index+1))].
  45798.     ^ result!
  45799. collect: aBlock 
  45800.     "Refer to the comment in Collection|collect:."
  45801.     | result |
  45802.     result _ self species new: self size.
  45803.     1 to: self size do:
  45804.         [:index | result at: index put: (aBlock value: (self at: index))].
  45805.     ^ result!
  45806. collectWithIndex: aBlock 
  45807.     "Just like collect: except that an index is supplied along with the object
  45808.     in the collection.  Be sure to use a block that expects two arguments.
  45809.         #(5 2 1 4 3) collectWithIndex: [:each :index | (each - index) abs].   "
  45810.  
  45811.     | aStream index length |
  45812.     aStream _ WriteStream on: (self species new: self size).
  45813.     index _ 0.
  45814.     length _ self size.
  45815.     [(index _ index + 1) <= length]
  45816.         whileTrue: [aStream nextPut: (aBlock value: (self at: index) value: index)].
  45817.     ^aStream contents!
  45818. do: aBlock 
  45819.     "Refer to the comment in Collection|do:."
  45820.     1 to: self size do:
  45821.         [:index | aBlock value: (self at: index)]!
  45822. doWithIndex: aBlock 
  45823.     "Just like do: except that the index is supplied also.
  45824.     Beware -- the block must accept two arguments, the object
  45825.     in the collection and its index."
  45826.  
  45827.     | index length |
  45828.     index _ 0.
  45829.     length _ self size.
  45830.     [(index _ index + 1) <= length]
  45831.         whileTrue: [aBlock value: (self at: index) value: index]
  45832.  
  45833. "compute the sum of the distances from the right places in a permutation.
  45834.     | sum |  sum _ 0.  #(3 5 4 1 2) doWithIndex: [:each :index |
  45835.         sum _ sum + (each - index) abs].
  45836.     sum    "!
  45837. findFirst: aBlock
  45838.     "Return the index of my first element for which aBlock evaluates as true."
  45839.  
  45840.     | index |
  45841.     index _ 0.
  45842.     [(index _ index + 1) <= self size] whileTrue:
  45843.         [(aBlock value: (self at: index)) ifTrue: [^index]].
  45844.     ^ 0!
  45845. findLast: aBlock
  45846.     "Return the index of my last element for which aBlock evaluates as true."
  45847.  
  45848.     | index |
  45849.     index _ self size + 1.
  45850.     [(index _ index - 1) >= 1] whileTrue:
  45851.         [(aBlock value: (self at: index)) ifTrue: [^index]].
  45852.     ^ 0!
  45853. reverseDo: aBlock
  45854.     "Evaluate aBlock with each of the receiver's elements as the argument, 
  45855.     starting with the last element and taking each in sequence up to the 
  45856.     first. For SequenceableCollections, this is the reverse of the enumeration 
  45857.     for do:."
  45858.  
  45859.     self size to: 1 by: -1 do: [:index | aBlock value: (self at: index)]!
  45860. reverseWith: aSequenceableCollection do: aBlock 
  45861.     "Evaluate aBlock with each of the receiver's elements, in reverse order, 
  45862.     along with the  
  45863.     corresponding element, also in reverse order, from 
  45864.     aSequencableCollection. "
  45865.  
  45866.     self size ~= aSequenceableCollection size ifTrue: [^ self errorNoMatch].
  45867.     self size
  45868.         to: 1
  45869.         by: -1
  45870.         do: [:index | aBlock value: (self at: index)
  45871.                 value: (aSequenceableCollection at: index)]!
  45872. select: aBlock 
  45873.     "Refer to the comment in Collection|select:."
  45874.     | aStream |
  45875.     aStream _ WriteStream on: (self species new: self size).
  45876.     1 to: self size do: 
  45877.         [:index |
  45878.         (aBlock value: (self at: index))
  45879.             ifTrue: [aStream nextPut: (self at: index)]].
  45880.     ^ aStream contents!
  45881. with: aSequenceableCollection do: aBlock 
  45882.     "Evaluate aBlock with each of the receiver's elements along with the 
  45883.     corresponding element from aSequencableCollection."
  45884.  
  45885.     | otherCollection |
  45886.     self size ~= aSequenceableCollection size ifTrue: [^self errorNoMatch].
  45887.     otherCollection _ ReadStream on: aSequenceableCollection.
  45888.     self do: [:each | aBlock value: each value: otherCollection next]! !
  45889.  
  45890. !SequenceableCollection methodsFor: 'converting'!
  45891. asArray
  45892.     "Answer an Array whose elements are the elements of the receiver, in 
  45893.     the same order."
  45894.  
  45895.     | newArray |
  45896.     newArray _ Array new: self size.
  45897.     1 to: self size do: [:index | newArray at: index put: (self at: index)].
  45898.     ^newArray!
  45899. asDictionary
  45900.     "Answer a Dictionary whose keys are string versions of my indices and whose values are my elements.  6/12/96 sw"
  45901.  
  45902.     | aDictionary |
  45903.     aDictionary _ Dictionary new.
  45904.     1 to: self size do:
  45905.         [:i | aDictionary add:
  45906.             (Association key: i printString value: (self at: i))].
  45907.     ^ aDictionary!
  45908. asSortedArray
  45909.     1 to: (self size - 1) do:
  45910.         [:i | (self at: i) >= (self at: (i+1)) ifTrue: 
  45911.                 [self flag: #developmentNote.
  45912.                 "The optimization used here is, I HOPE, really an optimization.  The idea is that most collections processed will already be sorted, so we don't bother going through the double-transformation of the next line until we're sure that it is necessary.  On the other hand, the test for need-to-sort is itself not free.  sw"
  45913.                 ^ self asSortedCollection asArray]].
  45914.     ^ self asArray!
  45915. asStringWithCr
  45916.     "Convert to a string with returns between items.  Elements are usually strings.
  45917.      Useful for labels for PopUpMenus."
  45918.     | labelStream |
  45919.     labelStream _ WriteStream on: (String new: 200).
  45920.     self do: [:each |
  45921.         (each isKindOf: String)
  45922.             ifTrue: [labelStream nextPutAll: each; cr]
  45923.             ifFalse: [each printOn: labelStream; cr]].
  45924.     self size > 0 ifTrue: [labelStream skip: -1].
  45925.     ^ labelStream contents!
  45926. mappedBy: aSequenceableCollection 
  45927.     "Answer a MappedCollection whose contents is the receiver and whose 
  45928.     map is the argument, aSequencableCollection."
  45929.  
  45930.     ^(MappedCollection collection: self map: aSequenceableCollection) contents!
  45931. reversed
  45932.     "Answer a copy of the receiver with element order reversed.  1/26/96 sw"
  45933.     | newCol |
  45934.     newCol _ self species new.
  45935.     self reverseDo:
  45936.         [:elem | newCol add: elem].
  45937.     ^ newCol
  45938.  
  45939.  
  45940. "#(2 3 4 'fred') reversed"! !
  45941.  
  45942. !SequenceableCollection methodsFor: 'private'!
  45943. copyReplaceAll: oldSubstring with: newSubstring asTokens: ifTokens
  45944.     "Answer a copy of the receiver in which all occurrences of
  45945.     oldSubstring have been replaced by newSubstring.
  45946.     ifTokens (valid for Strings only) specifies that the characters
  45947.     surrounding the recplacement must not be alphanumeric."
  45948.     | aString startSearch currentIndex endIndex |
  45949.     (ifTokens and: [(self isKindOf: String) not])
  45950.         ifTrue: [self error: 'Token replacement only valid for Strings'].
  45951.     aString _ self.
  45952.     startSearch _ 1.
  45953.     [(currentIndex _ aString indexOfSubCollection: oldSubstring startingAt: startSearch)
  45954.              > 0]
  45955.         whileTrue: 
  45956.         [endIndex _ currentIndex + oldSubstring size - 1.
  45957.         (ifTokens not
  45958.             or: [(currentIndex = 1
  45959.                     or: [(aString at: currentIndex-1) isAlphaNumeric not])
  45960.                 and: [endIndex = aString size
  45961.                     or: [(aString at: endIndex+1) isAlphaNumeric not]]])
  45962.             ifTrue: [aString _ aString
  45963.                     copyReplaceFrom: currentIndex
  45964.                     to: endIndex
  45965.                     with: newSubstring].
  45966.         startSearch _ currentIndex + newSubstring size].
  45967.     ^ aString!
  45968. errorOutOfBounds
  45969.  
  45970.     self error: 'indices are out of bounds'!
  45971. swap: oneIndex with: anotherIndex 
  45972.     "Move the element at oneIndex to anotherIndex, and vice-versa."
  45973.  
  45974.     | element |
  45975.     element _ self at: oneIndex.
  45976.     self at: oneIndex put: (self at: anotherIndex).
  45977.     self at: anotherIndex put: element! !
  45978. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  45979.  
  45980. SequenceableCollection class
  45981.     instanceVariableNames: ''!
  45982.  
  45983. !SequenceableCollection class methodsFor: 'As yet unclassified'!
  45984. streamContents: blockWithArg
  45985.     | stream |
  45986.     stream _ WriteStream on: (self new: 100).
  45987.     blockWithArg value: stream.
  45988.     ^stream contents! !AbstractSound subclass: #SequentialSound
  45989.     instanceVariableNames: 'sounds currentIndex '
  45990.     classVariableNames: ''
  45991.     poolDictionaries: ''
  45992.     category: 'Sound'!
  45993.  
  45994. !SequentialSound methodsFor: 'initialization'!
  45995. initialize
  45996.  
  45997.     sounds _ Array new.
  45998.     currentIndex _ 0.
  45999. ! !
  46000.  
  46001. !SequentialSound methodsFor: 'sound generation'!
  46002. doControl
  46003.  
  46004.     currentIndex > 0 ifTrue: [
  46005.         (sounds at: currentIndex) doControl.
  46006.     ].
  46007. !
  46008. mixSampleCount: n into: aSoundBuffer startingAt: startIndex pan: pan
  46009.     "Play a collection of sounds in sequence."
  46010.     "PluckedSound chromaticScale play"
  46011.  
  46012.     | finalIndex thisIndex snd cnt |
  46013.     currentIndex = 0 ifTrue: [ ^ self ].  "already done"
  46014.     finalIndex _ (startIndex + n) - 1.
  46015.     thisIndex _ startIndex.
  46016.     [thisIndex <= finalIndex] whileTrue: [
  46017.         snd _ (sounds at: currentIndex).
  46018.         [snd samplesRemaining <= 0] whileTrue: [
  46019.             "find next undone sound"
  46020.             currentIndex < sounds size ifTrue: [
  46021.                 currentIndex _ currentIndex + 1.
  46022.                 snd _ (sounds at: currentIndex).
  46023.             ] ifFalse: [
  46024.                 currentIndex _ 0.
  46025.                 ^ self  "no more sounds"
  46026.             ].
  46027.         ].
  46028.         cnt _ snd samplesRemaining min: (finalIndex - thisIndex) + 1.
  46029.         snd mixSampleCount: cnt into: aSoundBuffer startingAt: thisIndex pan: pan.
  46030.         thisIndex _ thisIndex + cnt.
  46031.     ].
  46032. !
  46033. reset
  46034.  
  46035.     super reset.
  46036.     sounds do: [ :snd | snd reset ].
  46037.     sounds size > 0 ifTrue: [ currentIndex _ 1 ].!
  46038. samplesRemaining
  46039.  
  46040.     currentIndex = 0
  46041.         ifTrue: [ ^ 0 ]
  46042.         ifFalse: [ ^ 1000000 ].! !
  46043.  
  46044. !SequentialSound methodsFor: 'composition'!
  46045. , aSound
  46046.     "Return the concatenation of the receiver and the argument sound."
  46047.  
  46048.     ^ self add: aSound
  46049. !
  46050. add: aSound
  46051.  
  46052.     sounds _ sounds copyWith: aSound.! !Collection subclass: #Set
  46053.     instanceVariableNames: 'tally array '
  46054.     classVariableNames: ''
  46055.     poolDictionaries: ''
  46056.     category: 'Collections-Unordered'!
  46057.  
  46058. !Set methodsFor: 'testing'!
  46059. = aSet
  46060.     (aSet isKindOf: Set) ifFalse: [^ false].
  46061.     self size = aSet size ifFalse: [^ false].
  46062.     self do: [:each | (aSet includes: each) ifFalse: [^ false]].
  46063.     ^ true!
  46064. includes: anObject 
  46065.     ^ (array at: (self findElementOrNil: anObject)) ~~ nil!
  46066. occurrencesOf: anObject 
  46067.     (self includes: anObject) ifTrue: [^1] ifFalse: [^0]! !
  46068.  
  46069. !Set methodsFor: 'adding'!
  46070. add: newObject 
  46071.     | index |
  46072.     newObject == nil ifTrue: [self halt: 'Sets cannot meaningfully contain nil as an element'].
  46073.     index _ self findElementOrNil: newObject.
  46074.     (array at: index) == nil ifTrue:
  46075.         [self atNewIndex: index put: newObject].
  46076.     ^ newObject! !
  46077.  
  46078. !Set methodsFor: 'removing'!
  46079. remove: oldObject ifAbsent: aBlock
  46080.  
  46081.     | index |
  46082.     index _ self findElementOrNil: oldObject.
  46083.     (array at: index) == nil ifTrue: [ ^ aBlock value ].
  46084.     array at: index put: nil.
  46085.     tally _ tally - 1.
  46086.     self fixCollisionsFrom: index.
  46087.     ^ oldObject! !
  46088.  
  46089. !Set methodsFor: 'enumerating'!
  46090. collect: aBlock 
  46091.     "Return a Set containing the result of evaluating aBlock
  46092.     for each element of this set"
  46093.     | newSet |
  46094.     tally = 0 ifTrue: [^ Set new: 2].
  46095.     newSet _ Set new: self size.
  46096.     array do:
  46097.         [:element |
  46098.         element == nil ifFalse: [newSet add: (aBlock value: element)]].
  46099.     ^ newSet!
  46100. do: aBlock 
  46101.     tally = 0 ifTrue: [^ self].
  46102.     array do: 
  46103.         [:element | element == nil ifFalse: [aBlock value: element]]!
  46104. doWithIndex: aBlock2
  46105.     "Support Set enumeration with a counter, even though not ordered"
  46106.     | index |
  46107.     index _ 0.
  46108.     self do: [:item | aBlock2 value: item value: (index _ index+1)]! !
  46109.  
  46110. !Set methodsFor: 'private'!
  46111. array
  46112.     ^ array!
  46113. atNewIndex: index put: anObject
  46114.     array at: index put: anObject.
  46115.     tally _ tally + 1.
  46116.     self fullCheck!
  46117. copy
  46118.     ^ self shallowCopy withArray: array shallowCopy!
  46119. findElementOrNil: anObject
  46120.     "Answer the index of a first slot containing either a nil (indicating an empty slot) or an element that matches the given object. Answer the index of that slot or zero. Fail if neither a match nor an empty slot is found."
  46121.  
  46122.     | start index length |
  46123.     "search from (hash mod size) to the end"
  46124.     length _ array size.
  46125.     start _ (anObject hash \\ length) + 1.
  46126.     index _ self scanFor: anObject from: start to: length.
  46127.     index > 0 ifTrue: [ ^ index ].
  46128.  
  46129.     "search from 1 to where we started"
  46130.     index _ self scanFor: anObject from: 1 to: start - 1.
  46131.     index > 0 ifTrue: [ ^ index ].
  46132.  
  46133.     "Bad scene.  Neither have we found a matching element
  46134.     nor even an empty slot.  No hashed set is ever supposed to get
  46135.     completely full."
  46136.     self error: 'There is no free space in this set!!'.!
  46137. fixCollisionsFrom: index
  46138.     "The element at index has been removed and replaced by nil.
  46139.     This method moves forward from there, relocating any entries
  46140.     that had been placed below due to collisions with this one"
  46141.     | length oldIndex newIndex element |
  46142.     oldIndex _ index.
  46143.     length _ array size.
  46144.     [oldIndex = length
  46145.             ifTrue: [oldIndex _  1]
  46146.             ifFalse: [oldIndex _  oldIndex + 1].
  46147.     (element _ self keyAt: oldIndex) == nil]
  46148.         whileFalse: 
  46149.             [newIndex _ self findElementOrNil: element.
  46150.             oldIndex = newIndex ifFalse: [self swap: oldIndex with: newIndex]]!
  46151. fullCheck
  46152.     "Keep array at least 1/4 free for decent hash behavior"
  46153.     array size - tally < (array size // 4 + 1)
  46154.         ifTrue: [self grow]!
  46155. grow
  46156.     "Grow the elements array and reinsert the old elements"
  46157.     | oldElements |
  46158.     oldElements _ array.
  46159.     array _ Array new: array size + self growSize.
  46160.     tally _ 0.
  46161.     oldElements do:
  46162.         [:each | each == nil ifFalse: [self noCheckAdd: each]]!
  46163. growSize
  46164.     ^ array size max: 2!
  46165. init: n
  46166.     "Initialize array to an array size of n"
  46167.     array _ Array new: n.
  46168.     tally _ 0!
  46169. keyAt: index
  46170.     "May be overridden by subclasses so that fixCollisions will work"
  46171.     ^ array at: index!
  46172. noCheckAdd: anObject
  46173.     array at: (self findElementOrNil: anObject) put: anObject.
  46174.     tally _ tally + 1!
  46175. rehash
  46176.     | newSelf |
  46177.     newSelf _ self species new: self size.
  46178.     self do: [:each | newSelf noCheckAdd: each].
  46179.     array _ newSelf array!
  46180. scanFor: key from: start to: finish
  46181.     "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches the key. Answer the index of that slot or zero if no slot is found within the given range of indices. This method will be overridden in various subclasses that have different models for finding a matching element."
  46182.  
  46183.     | element |
  46184.     "this speeds up a common case: key is in the first slot"
  46185.     ((element _ array at: start) == nil or: [element = key])
  46186.         ifTrue: [ ^ start ].
  46187.  
  46188.     start + 1 to: finish do: [ :index |
  46189.         ((element _ array at: index) == nil or: [element = key])
  46190.             ifTrue: [ ^ index ].
  46191.     ].
  46192.     ^ 0
  46193. !
  46194. size
  46195.     ^ tally!
  46196. swap: oneIndex with: otherIndex
  46197.     "May be overridden by subclasses so that fixCollisions will work"
  46198.  
  46199.     array swap: oneIndex with: otherIndex
  46200. !
  46201. withArray: anArray
  46202.     "private -- for use only in copy"
  46203.     array _ anArray! !
  46204. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  46205.  
  46206. Set class
  46207.     instanceVariableNames: ''!
  46208.  
  46209. !Set class methodsFor: 'instance creation'!
  46210. fromBraceStack: itsSize 
  46211.     "Answer an instance of me with itsSize elements, popped in reverse order from
  46212.      the stack of thisContext sender.  Do not call directly: this is called by {1. 2. 3}
  46213.      constructs."
  46214.  
  46215.     ^ (self new: itsSize) fill: itsSize fromStack: thisContext sender!
  46216. new
  46217.     ^ self new: 4!
  46218. new: nElements
  46219.     "Create a Set large enough to hold nElements without growing"
  46220.     ^ super new init: (self sizeFor: nElements)!
  46221. newFrom: aCollection 
  46222.     "Answer an instance of me containing the same elements as aCollection."
  46223.     | newCollection |
  46224.     newCollection _ self new: aCollection size.
  46225.     newCollection addAll: aCollection.
  46226.     ^ newCollection
  46227. "
  46228.     Set newFrom: {1. 2. 3}
  46229.     {1. 2. 3} as: Set
  46230. "!
  46231. readDataFrom: aDataStream size: anInteger
  46232.     "Symbols have new hash in this world.  9/7/96 tk"
  46233.  
  46234.     | aSet |
  46235.     aSet _ super readDataFrom: aDataStream size: anInteger.
  46236.     aSet rehash.
  46237.     ^ aSet
  46238. !
  46239. sizeFor: nElements
  46240.     "Large enough size to hold nElements with some slop (see fullCheck)"
  46241.     nElements <= 0 ifTrue: [^ 1].
  46242.     ^ nElements+1*4//3! !Object subclass: #SharedQueue
  46243.     instanceVariableNames: 'contentsArray readPosition writePosition accessProtect readSynch '
  46244.     classVariableNames: ''
  46245.     poolDictionaries: ''
  46246.     category: 'Kernel-Processes'!
  46247. SharedQueue comment:
  46248. 'I provide synchronized communication of arbitrary objects between Processes. An object is sent by sending the message nextPut: and received by sending the message next. If no object has been sent when a next message is sent, the Process requesting the object will be suspended until one is sent.'!
  46249.  
  46250. !SharedQueue methodsFor: 'initialize-release'!
  46251. release 
  46252.     "Refer to the comment in Object|release."
  46253.  
  46254.     contentsArray _ nil! !
  46255.  
  46256. !SharedQueue methodsFor: 'accessing'!
  46257. next
  46258.     "Answer the object that was sent through the receiver first and has not 
  46259.     yet been received by anyone. If no object has been sent, suspend the 
  46260.     requesting process until one is."
  46261.  
  46262.     | value |
  46263.     readSynch wait.
  46264.     accessProtect
  46265.         critical: [readPosition = writePosition
  46266.                     ifTrue: 
  46267.                         [self error: 'Error in SharedQueue synchronization'.
  46268.                          value _ nil]
  46269.                     ifFalse: 
  46270.                         [value _ contentsArray at: readPosition.
  46271.                          contentsArray at: readPosition put: nil.
  46272.                          readPosition _ readPosition + 1]].
  46273.     ^value!
  46274. nextPut: value 
  46275.     "Send value through the receiver. If a Process has been suspended 
  46276.     waiting to receive a value through the receiver, allow it to proceed."
  46277.  
  46278.     accessProtect
  46279.         critical: [writePosition > contentsArray size
  46280.                         ifTrue: [self makeRoomAtEnd].
  46281.                  contentsArray at: writePosition put: value.
  46282.                  writePosition _ writePosition + 1].
  46283.     readSynch signal.
  46284.     ^value!
  46285. peek
  46286.     "Answer the object that was sent through the receiver first and has not 
  46287.     yet been received by anyone but do not remove it from the receiver. If 
  46288.     no object has been sent, suspend the requesting process until one is."
  46289.  
  46290.     | value |
  46291.     accessProtect
  46292.         critical: [readPosition >= writePosition
  46293.                     ifTrue: [readPosition _ 1.
  46294.                             writePosition _ 1.
  46295.                             value _ nil]
  46296.                     ifFalse: [value _ contentsArray at: readPosition]].
  46297.     ^value!
  46298. size
  46299.     "Answer the number of objects that have been sent through the
  46300.     receiver and not yet received by anyone."
  46301.  
  46302.     ^writePosition - readPosition! !
  46303.  
  46304. !SharedQueue methodsFor: 'testing'!
  46305. isEmpty
  46306.     "Answer whether any objects have been sent through the receiver and 
  46307.     not yet received by anyone."
  46308.  
  46309.     ^readPosition = writePosition! !
  46310.  
  46311. !SharedQueue methodsFor: 'private'!
  46312. init: size
  46313.  
  46314.     contentsArray _ Array new: size.
  46315.     readPosition _ 1.
  46316.     writePosition _ 1.
  46317.     accessProtect _ Semaphore forMutualExclusion.
  46318.     readSynch _ Semaphore new!
  46319. makeRoomAtEnd
  46320.     | contentsSize |
  46321.     readPosition = 1
  46322.         ifTrue: 
  46323.             [contentsArray _ contentsArray , (Array new: 10)]
  46324.         ifFalse: 
  46325.             [contentsSize _ writePosition - readPosition.
  46326.             1 to: contentsSize do: 
  46327.                 [:index | 
  46328.                 contentsArray 
  46329.                     at: index 
  46330.                     put: (contentsArray at: index + readPosition - 1)].
  46331.             readPosition _ 1.
  46332.             writePosition _ contentsSize + 1]! !
  46333. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  46334.  
  46335. SharedQueue class
  46336.     instanceVariableNames: ''!
  46337.  
  46338. !SharedQueue class methodsFor: 'instance creation'!
  46339. new
  46340.     "Answer a new instance of SharedQueue that has 10 elements."
  46341.  
  46342.     ^self new: 10!
  46343. new: anInteger 
  46344.     ^super new init: anInteger! !Integer subclass: #SmallInteger
  46345.     instanceVariableNames: ''
  46346.     classVariableNames: 'Digitbuffer '
  46347.     poolDictionaries: ''
  46348.     category: 'Numeric-Numbers'!
  46349. SmallInteger comment:
  46350. 'My instances are 15 or 16-bit numbers, stored in twos complement form. The allowable range is from -16384 to 16383. You can type an instance of me in octal representation by typing a leading radix specification, such as in 8r377.'!
  46351.  
  46352. !SmallInteger methodsFor: 'arithmetic'!
  46353. * aNumber 
  46354.     "Primitive. Multiply the receiver by the argument and answer with the
  46355.     result if it is a SmallInteger. Fail if the argument or the result is not a
  46356.     SmallInteger. Essential. No Lookup. See Object documentation
  46357.     whatIsAPrimitive."
  46358.  
  46359.     <primitive: 9>
  46360.     self = 0 ifTrue: [^0].
  46361.     "This eliminates the need for a self=0 check in LargeInteger *"
  46362.     ^super * aNumber!
  46363. + aNumber 
  46364.     "Primitive. Add the receiver to the argument and answer with the result
  46365.     if it is a SmallInteger. Fail if the argument or the result is not a
  46366.     SmallInteger  Essential  No Lookup. See Object documentation
  46367.     whatIsAPrimitive."
  46368.  
  46369.     <primitive: 1>
  46370.     ^super + aNumber!
  46371. - aNumber 
  46372.     "Primitive. Subtract the argument from the receiver and answer with the
  46373.     result if it is a SmallInteger. Fail if the argument or the result is not a
  46374.     SmallInteger. Essential. No Lookup. See Object documentation
  46375.     whatIsAPrimitive."
  46376.  
  46377.     <primitive: 2>
  46378.     ^super - aNumber!
  46379. / aNumber 
  46380.     "Primitive. This primitive (for /) divides the receiver by the argument
  46381.     and returns the result if the division is exact. Fail if the result is not a
  46382.     whole integer. Fail if the argument is 0 or is not a SmallInteger. Optional.
  46383.     No Lookup. See Object documentation whatIsAPrimitive."
  46384.  
  46385.     <primitive: 10>
  46386.     aNumber = 0 ifTrue: [^self error: 'division by 0'].
  46387.     (aNumber isMemberOf: SmallInteger)
  46388.         ifTrue: [^(Fraction numerator: self denominator: aNumber) reduced]
  46389.         ifFalse: [^super / aNumber]!
  46390. // aNumber 
  46391.     "Primitive. Divide the receiver by the argument and answer with the
  46392.     result. Round the result down towards negative infinity to make it a
  46393.     whole integer. Fail if the argument is 0 or is not a SmallInteger.
  46394.     Essential. No Lookup. See Object documentation whatIsAPrimitive. "
  46395.  
  46396.     <primitive: 12>
  46397.     ^super // aNumber"Do with quo: if primitive fails"!
  46398. quo: aNumber 
  46399.     "Primitive. Divide the receiver by the argument and answer with the
  46400.     result. Round the result down towards zero to make it a whole integer.
  46401.     Fail if the argument is 0 or is not a SmallInteger. Optional. See Object
  46402.     documentation whatIsAPrimitive."
  46403.  
  46404.     <primitive: 13>
  46405.     aNumber = 0 ifTrue: [^self error: 'Attempt to divide by zero'].
  46406.     (aNumber isMemberOf: SmallInteger)
  46407.         ifTrue: [self primitiveFailed]
  46408.         ifFalse: [^super quo: aNumber]!
  46409. \\ aNumber 
  46410.     "Primitive. Take the receiver modulo the argument. The result is the
  46411.     remainder rounded towards negative infinity, of the receiver divided by
  46412.     the argument Fail if the argument is 0 or is not a SmallInteger. Optional.
  46413.     No Lookup. See Object documentation whatIsAPrimitive."
  46414.  
  46415.     <primitive: 11>
  46416.     ^super \\ aNumber"Do with // if primitive fails"! !
  46417.  
  46418. !SmallInteger methodsFor: 'bit manipulation'!
  46419. bitAnd: arg 
  46420.     "Primitive. Answer an Integer whose bits are the logical AND of the
  46421.     receiver's bits and those of the argument, arg.
  46422.     Negative numbers are interpreted as a 32-bit 2's-complement.
  46423.     Essential.  See Object documentation whatIsAPrimitive."
  46424.  
  46425.     <primitive: 14>
  46426.     self < 0 ifTrue: [^ 16rFFFFFFFF + (self+1) bitAnd: arg].
  46427.     ^arg bitAnd: self!
  46428. bitOr: arg 
  46429.     "Primitive. Answer an Integer whose bits are the logical OR of the
  46430.     receiver's bits and those of the argument, arg.
  46431.     Negative numbers are interpreted as a 32-bit 2's-complement.
  46432.     Essential.  See Object documentation whatIsAPrimitive."
  46433.  
  46434.     <primitive: 15>
  46435.     self < 0 ifTrue: [^ 16rFFFFFFFF + (self+1) bitOr: arg].
  46436.     ^arg bitOr: self!
  46437. bitShift: arg 
  46438.     "Primitive. Answer an Integer whose value is the receiver's value shifted
  46439.     left by the number of bits indicated by the argument. Negative arguments
  46440.     shift right.
  46441.     Essential.  See Object documentation whatIsAPrimitive."
  46442.  
  46443.     <primitive: 17>
  46444.     self < 0 ifTrue: [^ -1 - (-1-self bitShift: arg)].
  46445.     ^ super bitShift: arg!
  46446. bitXor: arg 
  46447.     "Primitive. Answer an Integer whose bits are the logical XOR of the
  46448.     receiver's bits and those of the argument, arg.
  46449.     Negative numbers are interpreted as a 32-bit 2's-complement.
  46450.     Essential.  See Object documentation whatIsAPrimitive."
  46451.  
  46452.     <primitive: 16>
  46453.     self < 0 ifTrue: [^ 16rFFFFFFFF + (self+1) bitXor: arg].
  46454.     ^arg bitXor: self!
  46455. highBit   "10 highBit 4"
  46456.     "Returns the number of the highest 1-bit.  Note that they
  46457.     are numbered with 1248 being 1234 -- NOT zero-based.
  46458.     Also note that 0 highBit returns 0"
  46459.     | shifted bitNo |
  46460.     self < 0 ifTrue: [^ (0 - self) highBit].
  46461.     shifted _ self.
  46462.     bitNo _ 0.
  46463.     [shifted = 0] whileFalse:
  46464.         [shifted _ shifted bitShift: -1.
  46465.         bitNo _ bitNo + 1].
  46466.     ^ bitNo
  46467. ! !
  46468.  
  46469. !SmallInteger methodsFor: 'testing'!
  46470. even
  46471.  
  46472.     ^(self bitAnd: 1) = 0!
  46473. odd
  46474.  
  46475.     ^(self bitAnd: 1) = 1! !
  46476.  
  46477. !SmallInteger methodsFor: 'comparing'!
  46478. < aNumber 
  46479.     "Primitive. Compare the receiver with the argument and answer with
  46480.     true if the receiver is less than the argument. Otherwise answer false.
  46481.     Fail if the argument is not a SmallInteger. Essential. No Lookup. See
  46482.     Object documentation whatIsAPrimitive."
  46483.  
  46484.     <primitive: 3>
  46485.     ^super < aNumber!
  46486. <= aNumber 
  46487.     "Primitive. Compare the receiver with the argument and answer true if
  46488.     the receiver is less than or equal to the argument. Otherwise answer
  46489.     false. Fail if the argument is not a SmallInteger. Optional. No Lookup.
  46490.     See Object documentation whatIsAPrimitive. "
  46491.  
  46492.     <primitive: 5>
  46493.     ^super <= aNumber!
  46494. = aNumber 
  46495.     "Primitive. Compare the receiver with the argument and answer true if
  46496.     the receiver is equal to the argument. Otherwise answer false. Fail if the
  46497.     argument is not a SmallInteger. Essential. No Lookup. See Object
  46498.     documentation whatIsAPrimitive. "
  46499.  
  46500.     <primitive: 7>
  46501.     ^super = aNumber!
  46502. > aNumber 
  46503.     "Primitive. Compare the receiver with the argument and answer true if
  46504.     the receiver is greater than the argument. Otherwise answer false. Fail if
  46505.     the argument is not a SmallInteger. Essential. No Lookup. See Object
  46506.     documentation whatIsAPrimitive."
  46507.  
  46508.     <primitive: 4>
  46509.     ^super > aNumber!
  46510. >= aNumber 
  46511.     "Primitive. Compare the receiver with the argument and answer true if
  46512.     the receiver is greater than or equal to the argument. Otherwise answer
  46513.     false. Fail if the argument is not a SmallInteger. Optional. No Lookup.
  46514.     See Object documentation whatIsAPrimitive."
  46515.  
  46516.     <primitive: 6>
  46517.     ^super >= aNumber!
  46518. hash
  46519.  
  46520.     ^self!
  46521. ~= aNumber 
  46522.     "Primitive. Compare the receiver with the argument and answer true if
  46523.     the receiver is not equal to the argument. Otherwise answer false. Fail if
  46524.     the argument is not a SmallInteger. Essential. No Lookup. See Object
  46525.     documentation whatIsAPrimitive."
  46526.  
  46527.     <primitive: 8>
  46528.     ^super ~= aNumber! !
  46529.  
  46530. !SmallInteger methodsFor: 'copying'!
  46531. deepCopy!
  46532. shallowCopy! !
  46533.  
  46534. !SmallInteger methodsFor: 'coercing'!
  46535. coerce: n
  46536.  
  46537.     ^n asInteger!
  46538. generality
  46539.  
  46540.     ^20! !
  46541.  
  46542. !SmallInteger methodsFor: 'converting'!
  46543. asFloat
  46544.     "Primitive. Answer a Float that represents the value of the receiver.
  46545.     Essential. See Object documentation whatIsAPrimitive."
  46546.  
  46547.     <primitive: 40>
  46548.     self primitiveFailed! !
  46549.  
  46550. !SmallInteger methodsFor: 'printing'!
  46551. printOn: aStream base: b "SmallInteger maxVal printStringBase: 2"
  46552.     "Refer to the comment in Integer|printOn:base:."
  46553.     | i x digitsInReverse |
  46554.     (x _ self) < 0 ifTrue: 
  46555.             [aStream nextPut: $-.
  46556.             ^ self negated printOn: aStream base: b].
  46557.     b = 10 ifFalse: [aStream print: b; nextPut: $r].
  46558.     digitsInReverse _ Array new: 32.
  46559.     i _ 0.
  46560.     [x >= b]
  46561.         whileTrue: 
  46562.             [digitsInReverse at: (i _ i + 1) put: x \\ b.
  46563.             x _ x // b].
  46564.     digitsInReverse at: (i _ i + 1) put: x.
  46565.     i to: 1 by: -1 do:
  46566.         [:j | aStream nextPut: (Character digitValue: (digitsInReverse at: j))]! !
  46567.  
  46568. !SmallInteger methodsFor: 'system primitives'!
  46569. asOop
  46570.     "Answer an object pointer as an integer, return negative number for SmallInteger"
  46571.  
  46572.     ^ self!
  46573. digitAt: n 
  46574.     "Answer the value of an indexable field in the receiver. Fail if the 
  46575.     argument (the index) is not an Integer or is out of bounds."
  46576.     n>4 ifTrue: [^ 0].
  46577.     self < 0
  46578.         ifTrue: 
  46579.             [self = SmallInteger minVal ifTrue:
  46580.                 ["Can't negate minVal -- treat specially"
  46581.                 ^ #(0 0 0 64) at: n].
  46582.             ^ ((0-self) bitShift: (1-n)*8) bitAnd: 16rFF]
  46583.         ifFalse: [^ (self bitShift: (1-n)*8) bitAnd: 16rFF]!
  46584. digitAt: n put: value 
  46585.     "Fails. The digits of a small integer can not be modified."
  46586.  
  46587.     self error: 'You cant store in a SmallInteger'!
  46588. digitLength
  46589.     "Answer the number of indexable fields in the receiver. This value is the 
  46590.     same as the largest legal subscript. Included so that a SmallInteger can 
  46591.     behave like a LargePositiveInteger or LargeNegativeInteger."
  46592.  
  46593.     (self < 16r100 and: [self > -16r100]) ifTrue: [^ 1].
  46594.     (self < 16r10000 and: [self > -16r10000]) ifTrue: [^ 2].
  46595.     (self < 16r1000000 and: [self > -16r1000000]) ifTrue: [^ 3].
  46596.     ^ 4!
  46597. instVarAt: i 
  46598.     "Small integer has to be specially handled."
  46599.  
  46600.     i = 1 ifTrue: [^self].
  46601.     self error: 'argument too big for small integer instVarAt:'! !
  46602.  
  46603. !SmallInteger methodsFor: 'private'!
  46604. fromString: str radix: radix
  46605.  
  46606.     | maxdigit c val |
  46607.     maxdigit _ 
  46608.         radix + (radix > 10
  46609.                     ifTrue: [55 - 1]
  46610.                     ifFalse: [48 - 1]).
  46611.     val _ 0.
  46612.     1 to: str size do: 
  46613.         [:i | 
  46614.         c _ str at: i.
  46615.         (c < 48 ifFalse: [c > maxdigit])
  46616.             ifTrue: [^false].
  46617.         val _ val * radix + (c <= 57
  46618.                             ifTrue: [c - 48]
  46619.                             ifFalse: 
  46620.                                 [c < 65 ifTrue: [^false].
  46621.                                 c - 55])].
  46622.     ^val! !
  46623. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  46624.  
  46625. SmallInteger class
  46626.     instanceVariableNames: ''!
  46627.  
  46628. !SmallInteger class methodsFor: 'class initialization'!
  46629. initialize
  46630.     "Initialize the digit buffer."
  46631.  
  46632.     Digitbuffer _ Array new: 16    
  46633.     "SmallInteger initialize."
  46634. ! !
  46635.  
  46636. !SmallInteger class methodsFor: 'instance creation'!
  46637. new
  46638.  
  46639.     self error: 'SmallIntegers can only be created by performing arithmetic'! !
  46640.  
  46641. !SmallInteger class methodsFor: 'constants'!
  46642. maxVal
  46643.     "Answer the maximum value for a SmallInteger."
  46644.     ^ 16r3FFFFFFF!
  46645. minVal
  46646.     "Answer the minimum value for a SmallInteger."
  46647.     ^ -16r40000000! !
  46648.  
  46649. !SmallInteger class methodsFor: 'documentation'!
  46650. guideToDivision
  46651.     "Handy guide to the kinds of Integer division: 
  46652.     /  exact division, returns a fraction if result is not a whole integer. 
  46653.     //  returns an Integer, rounded towards negative infinity. 
  46654.     \\ is modulo rounded towards negative infinity. 
  46655.     quo:  truncated division, rounded towards zero."! !
  46656.  
  46657. SmallInteger initialize!
  46658. OrderedCollection subclass: #SortedCollection
  46659.     instanceVariableNames: 'sortBlock '
  46660.     classVariableNames: ''
  46661.     poolDictionaries: ''
  46662.     category: 'Collections-Sequenceable'!
  46663. NewSortedCollection comment:
  46664. 'I represent a collection of objects ordered by some property of the objects themselves. The ordering is specified in a BlockContext.'!
  46665.  
  46666. !SortedCollection methodsFor: 'accessing'!
  46667. at: anInteger put: anObject 
  46668.     "Storing into a SortedCollection with at:put: is not allowed."
  46669.  
  46670.     self error: 'to add to a sorted collection, you must use add:'!
  46671. sortBlock
  46672.     "Answer the blockContext which is the criterion for sorting elements of 
  46673.     the receiver."
  46674.  
  46675.     ^sortBlock!
  46676. sortBlock: aBlock 
  46677.     "Make the argument, aBlock, be the criterion for ordering elements of the 
  46678.     receiver."
  46679.  
  46680.     sortBlock _ aBlock fixTemps.
  46681.     "The sortBlock must copy its home context, so as to avoid circularities!!"
  46682.     "Therefore sortBlocks with side effects may not work right"
  46683.     self size > 0 ifTrue: [self reSort]! !
  46684.  
  46685. !SortedCollection methodsFor: 'comparing'!
  46686. = aSortedCollection
  46687.     "Answer true if my and aSortedCollection's species are the same,
  46688.     and if our blocks are the same, and if our elements are the same."
  46689.  
  46690.     self species = aSortedCollection species ifFalse: [^ false].
  46691.     sortBlock = aSortedCollection sortBlock
  46692.         ifTrue: [^ super = aSortedCollection]
  46693.         ifFalse: [^ false]! !
  46694.  
  46695. !SortedCollection methodsFor: 'copying'!
  46696. copy
  46697.  
  46698.     | newCollection |
  46699.     newCollection _ self species sortBlock: sortBlock.
  46700.     newCollection addAll: self.
  46701.     ^newCollection!
  46702. copyEmpty
  46703.     "Answer a copy of the receiver without any of the receiver's elements."
  46704.  
  46705.     ^SortedCollection sortBlock: sortBlock! !
  46706.  
  46707. !SortedCollection methodsFor: 'adding'!
  46708. add: newObject
  46709.  
  46710.     | nextIndex |
  46711.     self isEmpty ifTrue: [^self addLast: newObject].
  46712.     nextIndex _ self indexForInserting: newObject.
  46713.     self insert: newObject before: nextIndex.
  46714.     ^newObject!
  46715. addAll: aCollection
  46716.  
  46717.     aCollection size > (self size // 3)
  46718.         ifTrue: 
  46719.             ["Faster to add the new elements and resort"
  46720.             aCollection do: [:each | self addLast: each].
  46721.             self reSort]
  46722.         ifFalse: ["Faster to add the elements individually in their proper places"
  46723.             aCollection do: [:each | self add: each]]! !
  46724.  
  46725. !SortedCollection methodsFor: 'enumerating'!
  46726. collect: aBlock 
  46727.     "Evaluate aBlock with each of my elements as the argument. Collect the 
  46728.     resulting values into an OrderedCollection. Answer the new collection. 
  46729.     Override the superclass in order to produce an OrderedCollection instead
  46730.     of a SortedCollection."
  46731.  
  46732.     | newCollection | 
  46733.     newCollection _ OrderedCollection new.
  46734.     self do: [:each | newCollection add: (aBlock value: each)].
  46735.     ^newCollection! !
  46736.  
  46737. !SortedCollection methodsFor: 'private'!
  46738. indexForInserting: newObject
  46739.  
  46740.     | index low high |
  46741.     low _ firstIndex.
  46742.     high _ lastIndex.
  46743.     [index _ high + low // 2.
  46744.     low > high]
  46745.         whileFalse: 
  46746.             [(sortBlock value: (array at: index) value: newObject)
  46747.                 ifTrue: [low _ index + 1]
  46748.                 ifFalse: [high _ index - 1]].
  46749.     ^low!
  46750. reSort
  46751.  
  46752.     self sort: firstIndex to: lastIndex!
  46753. sort: i to: j 
  46754.     "Sort elements i through j of self to be nondescending according to
  46755.     sortBlock."
  46756.  
  46757.     | di dij dj tt ij k l n |
  46758.     "The prefix d means the data at that index."
  46759.     (n _ j + 1  - i) <= 1 ifTrue: [^self].    "Nothing to sort." 
  46760.      "Sort di,dj."
  46761.     di _ array at: i.
  46762.     dj _ array at: j.
  46763.     (sortBlock value: di value: dj) "i.e., should di precede dj?"
  46764.         ifFalse: 
  46765.             [array swap: i with: j.
  46766.              tt _ di.
  46767.              di _ dj.
  46768.              dj _ tt].
  46769.     n > 2
  46770.         ifTrue:  "More than two elements."
  46771.             [ij _ (i + j) // 2.  "ij is the midpoint of i and j."
  46772.              dij _ array at: ij.  "Sort di,dij,dj.  Make dij be their median."
  46773.              (sortBlock value: di value: dij) "i.e. should di precede dij?"
  46774.                ifTrue: 
  46775.                 [(sortBlock value: dij value: dj) "i.e., should dij precede dj?"
  46776.                   ifFalse: 
  46777.                     [array swap: j with: ij.
  46778.                      dij _ dj]]
  46779.                ifFalse:  "i.e. di should come after dij"
  46780.                 [array swap: i with: ij.
  46781.                  dij _ di].
  46782.             n > 3
  46783.               ifTrue:  "More than three elements."
  46784.                 ["Find k>i and l<j such that dk,dij,dl are in reverse order.
  46785.                 Swap k and l.  Repeat this procedure until k and l pass each other."
  46786.                  k _ i.
  46787.                  l _ j.
  46788.                  [[l _ l - 1.  k <= l and: [sortBlock value: dij value: (array at: l)]]
  46789.                    whileTrue.  "i.e. while dl succeeds dij"
  46790.                   [k _ k + 1.  k <= l and: [sortBlock value: (array at: k) value: dij]]
  46791.                    whileTrue.  "i.e. while dij succeeds dk"
  46792.                   k <= l]
  46793.                    whileTrue:
  46794.                     [array swap: k with: l]. 
  46795.     "Now l<k (either 1 or 2 less), and di through dl are all less than or equal to dk
  46796.     through dj.  Sort those two segments."
  46797.                 self sort: i to: l.
  46798.                 self sort: k to: j]]! !
  46799. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  46800.  
  46801. SortedCollection class
  46802.     instanceVariableNames: ''!
  46803.  
  46804. !SortedCollection class methodsFor: 'instance creation'!
  46805. new: anInteger 
  46806.     "The default sorting function is a <= comparison on elements."
  46807.  
  46808.     ^(super new: anInteger) sortBlock: [:x :y | x <= y]!
  46809. sortBlock: aBlock 
  46810.     "Answer an instance of me such that its elements are sorted according to 
  46811.     the criterion specified in aBlock."
  46812.  
  46813.     ^(super new: 10) sortBlock: aBlock! !ArrayedCollection variableWordSubclass: #SoundBuffer
  46814.     instanceVariableNames: ''
  46815.     classVariableNames: ''
  46816.     poolDictionaries: ''
  46817.     category: 'Sound'!
  46818.  
  46819. !SoundBuffer methodsFor: 'accessing'!
  46820. sampleCount
  46821.     "Return the number of 32-bit sound samples that fit in this sound buffer. For stereo, 16-bit left and right channel samples are packed into each 32-bit word. For mono, samples are still 32-bits, but only the low-order 16 bits of each sample are played."
  46822.  
  46823.     ^ super size!
  46824. size
  46825.     "Return the number of 16-bit sound samples that fit in this sound buffer."
  46826.  
  46827.     ^ super size * 2! !
  46828.  
  46829. !SoundBuffer methodsFor: 'primitives'!
  46830. at: index
  46831.  
  46832.     <primitive: 143>
  46833.     index isInteger ifTrue: [ self errorSubscriptBounds: index ].
  46834.     index isNumber ifTrue: [ ^ self at: index truncated ].
  46835.     self errorNonIntegerIndex.!
  46836. at: index put: value
  46837.  
  46838.     <primitive: 144>
  46839.     index isInteger ifTrue: [
  46840.         (index >= 1 and: [index <= self size])
  46841.                 ifTrue: [ self errorImproperStore ]
  46842.                 ifFalse: [ self errorSubscriptBounds: index ].
  46843.     ].
  46844.     index isNumber ifTrue: [ ^ self at: index truncated put: value ].
  46845.     self errorNonIntegerIndex.
  46846. !
  46847. primFill: aPositiveInteger
  46848.     "Fill the receiver, an indexable bytes or words object, with the given positive integer. The range of possible fill values is [0..255] for byte arrays and [0..(2^32 - 1)] for word arrays."
  46849.  
  46850.     <primitive: 145>
  46851.     self errorImproperStore.! !
  46852. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  46853.  
  46854. SoundBuffer class
  46855.     instanceVariableNames: ''!
  46856.  
  46857. !SoundBuffer class methodsFor: 'instance creation'!
  46858. new: anInteger
  46859.     "Return a SoundBuffer large enough to hold the given number of 16-bit values. (That is, an array of 32-bit words half the requested size)."
  46860.  
  46861.     ^ self basicNew: (anInteger // 2)!
  46862. sampleCount: anInteger
  46863.     "Return a SoundBuffer large enough to hold the given number of stereo samples (i.e., 32-bit words)."
  46864.  
  46865.     ^ self basicNew: anInteger! !Object subclass: #SoundPlayer
  46866.     instanceVariableNames: ''
  46867.     classVariableNames: 'Stereo SamplingRate ActiveSounds BufferReady Buffer PlayerSemaphore BufferIndex PlayerProcess '
  46868.     poolDictionaries: ''
  46869.     category: 'Sound'!
  46870.  
  46871. !SoundPlayer methodsFor: 'no messages'! !
  46872. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  46873.  
  46874. SoundPlayer class
  46875.     instanceVariableNames: ''!
  46876.  
  46877. !SoundPlayer class methodsFor: 'initialization'!
  46878. initialize
  46879.  
  46880.     SamplingRate _ 22050.! !
  46881.  
  46882. !SoundPlayer class methodsFor: 'accessing'!
  46883. samplingRate
  46884.  
  46885.     ^ SamplingRate! !
  46886.  
  46887. !SoundPlayer class methodsFor: 'snapshotting'!
  46888. shutDown
  46889.     "Stop player process, for example before snapshotting."
  46890.  
  46891.     self stopPlayerProcess.!
  46892. startUp
  46893.     "Start up the player process."
  46894.  
  46895.     SoundPlayer startPlayerProcessBufferSize: 5000 rate: 22050 stereo: true.
  46896. ! !
  46897.  
  46898. !SoundPlayer class methodsFor: 'playing'!
  46899. pauseSound: aSound
  46900.     "Stop playing the given sound. Playing can be resumed from this point later."
  46901.  
  46902.     PlayerSemaphore critical: [
  46903.         ActiveSounds remove: aSound ifAbsent: [].
  46904.     ].!
  46905. playSound: aSound
  46906.     "Reset and start playing the given sound from its beginning."
  46907.  
  46908.     aSound reset.
  46909.     self resumeSound: aSound.!
  46910. resumeSound: aSound
  46911.     "Start playing the given sound without resetting it; it will resume playing from where it last stopped."
  46912.  
  46913.     PlayerProcess == nil ifTrue: [
  46914.         (self confirm: 'Start the sound player process?') ifFalse: [ ^ self ].
  46915.         self startUp.
  46916.     ].
  46917.  
  46918.     PlayerSemaphore critical: [
  46919.         (ActiveSounds includes: aSound) ifFalse: [
  46920.             ActiveSounds add: aSound.
  46921.         ].
  46922.     ].! !
  46923.  
  46924. !SoundPlayer class methodsFor: 'player process'!
  46925. playLoop
  46926.  
  46927.     [true] whileTrue: [
  46928.         [self primSoundAvailableSpace > 0] whileFalse: [
  46929.             (Delay forMilliseconds: 1) wait.
  46930.         ].
  46931.  
  46932.         PlayerSemaphore critical: [
  46933.             BufferReady ifTrue: [
  46934.                 self primSoundPlaySamples: Buffer sampleCount from: Buffer startingAt: 1.
  46935.                 Buffer primFill: 0.
  46936.                 BufferReady _ false.
  46937.             ] ifFalse: [
  46938.                 self primSoundPlaySilence.
  46939.             ].
  46940.         ].
  46941.  
  46942.         PlayerSemaphore critical: [
  46943.             BufferReady ifFalse: [
  46944.                 ActiveSounds copy do: [ :snd |
  46945.                     snd samplesRemaining <= 0 ifTrue: [ ActiveSounds remove: snd ].
  46946.                 ].
  46947.                 ActiveSounds do: [ :snd |
  46948.                     snd playSampleCount: Buffer sampleCount into: Buffer startingAt: 1 stereo: Stereo.
  46949.                     BufferReady _ true.
  46950.                 ].
  46951.             ].
  46952.         ].
  46953.     ].
  46954.  
  46955.     PlayerProcess _ nil.!
  46956. startPlayerProcessBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag
  46957.     "Start the sound player process. Terminate the old process, if any."
  46958.     "SoundPlayer startPlayerProcessBufferSize: 1000 rate: 11025 stereo: false"
  46959.  
  46960.     self stopPlayerProcess.
  46961.     ActiveSounds _ OrderedCollection new.
  46962.     Buffer _ SoundBuffer sampleCount: bufferSize.
  46963.     BufferReady _ false.
  46964.     PlayerProcess _ [SoundPlayer playLoop] newProcess.
  46965.     PlayerProcess priority: Processor userInterruptPriority.
  46966.     PlayerSemaphore _ Semaphore forMutualExclusion.
  46967.     SamplingRate _ samplesPerSecond.
  46968.     Stereo _ stereoFlag.
  46969.     self primSoundStartBufferSize: Buffer sampleCount rate: samplesPerSecond stereo: Stereo.
  46970.     PlayerProcess resume.
  46971. !
  46972. stopPlayerProcess
  46973.     "Stop the sound player process."
  46974.     "SoundPlayer stopPlayerProcess"
  46975.  
  46976.     self primSoundStop.
  46977.     PlayerProcess == nil ifFalse: [ PlayerProcess terminate ].
  46978.     PlayerProcess _ nil.
  46979.     PlayerSemaphore _ nil.
  46980.     Buffer _ nil.
  46981.     ActiveSounds _ OrderedCollection new.
  46982. ! !
  46983.  
  46984. !SoundPlayer class methodsFor: 'primitive test'!
  46985. boinkPitch: p dur: d loudness: l waveTable: waveTable pan: pan
  46986.     "Play a decaying note on the given stream using the given wave table. Used for testing only."
  46987.  
  46988.     | decay tableSize amplitude increment cycles i |
  46989.     decay _ 0.96.
  46990.     tableSize _ waveTable size.
  46991.     amplitude _ l asInteger min: 1000.
  46992.     increment _ ((p asFloat * tableSize asFloat) / SamplingRate asFloat) asInteger.
  46993.     increment _ (increment max: 1) min: (tableSize // 2).
  46994.     cycles _ (d * SamplingRate asFloat) asInteger.
  46995.  
  46996.     i _ 1.
  46997.     1 to: cycles do: [ :cycle |
  46998.         (cycle \\ 100) = 0 ifTrue: [
  46999.             amplitude _ (decay * amplitude asFloat) asInteger.
  47000.         ].
  47001.         i _ (((i - 1) + increment) \\ tableSize) + 1.
  47002.         self playTestSample: (amplitude * (waveTable at: i)) // 1000 pan: pan.
  47003.     ].
  47004. !
  47005. boinkScale
  47006.     "Tests the sound output primitives by playing a scale."
  47007.     "SoundPlayer boinkScale"
  47008.  
  47009.     | sineTable pan |
  47010.     self shutDown.
  47011.     SamplingRate _ 11025.
  47012.     Stereo _ true.
  47013.     sineTable _ self sineTable: 1000.
  47014.     Buffer _ SoundBuffer sampleCount: 1000.
  47015.     BufferIndex _ 1.
  47016.     self primSoundStartBufferSize: Buffer sampleCount rate: SamplingRate stereo: Stereo.
  47017.     self primSoundPlaySilence.
  47018.     pan _ 0.
  47019.     #(261.626 293.665 329.628 349.229 391.996 440.001 493.884 523.252) do: [ :p |
  47020.         self boinkPitch: p dur: 0.3 loudness: 300 waveTable: sineTable pan: pan.
  47021.         pan _ pan + 125.
  47022.     ].
  47023.     self boinkPitch: 261.626 dur: 1.0 loudness: 300 waveTable: sineTable pan: 500.
  47024.     self primSoundStop.
  47025. !
  47026. playTestSample: s pan: pan
  47027.     "Append the given sample in the range [-32767..32767] to the output buffer, playing the output buffer when it is full. Used for testing only."
  47028.  
  47029.     | sample leftSample |
  47030.     BufferIndex >= Buffer size ifTrue: [
  47031.         "current buffer is full; play it"
  47032.         [self primSoundAvailableSpace > 0] whileFalse: [
  47033.             "wait for space to be available"
  47034.             (Delay forMilliseconds: 1) wait.
  47035.         ].
  47036.         self primSoundPlaySamples: Buffer sampleCount from: Buffer startingAt: 1.
  47037.         Buffer primFill: 0.
  47038.         BufferIndex _ 1.
  47039.     ].
  47040.     sample _ s.
  47041.     sample >  32767 ifTrue: [ sample _  32767 ]. 
  47042.     sample < -32767 ifTrue: [ sample _ -32767 ].
  47043.  
  47044.     Stereo ifTrue: [
  47045.         leftSample _ (sample * pan) // 1000.
  47046.         Buffer at: BufferIndex        put: sample - leftSample.
  47047.         Buffer at: BufferIndex + 1    put: leftSample.
  47048.     ] ifFalse: [
  47049.         Buffer at: BufferIndex + 1 put: sample.
  47050.     ].
  47051.     BufferIndex _ BufferIndex + 2.
  47052. !
  47053. sineTable: size
  47054.     "Compute a sine table of the given size. Used for testing only."
  47055.  
  47056.     | radiansPerStep table |
  47057.     table _ Array new: size.
  47058.     radiansPerStep _ (2.0 * Float pi) / table size asFloat.
  47059.     1 to: table size do: [ :i |
  47060.         table at: i put:
  47061.             (32767.0 * (radiansPerStep * i) sin) asInteger.
  47062.     ].
  47063.     ^ table! !
  47064.  
  47065. !SoundPlayer class methodsFor: 'primitives'!
  47066. primSoundAvailableSpace
  47067.     "Return the number of bytes of available space in the sound output buffer."
  47068.  
  47069.     <primitive: 173>
  47070.     ^ self primitiveFailed!
  47071. primSoundPlaySamples: count from: aByteArray startingAt: index
  47072.     "Copy count bytes from the given byte array starting at the given index to the current sound output buffer."
  47073.  
  47074.     <primitive: 174>
  47075.     ^ self primitiveFailed!
  47076. primSoundPlaySilence
  47077.     "Fill the current sound output buffer with silence."
  47078.  
  47079.     <primitive: 175>
  47080.     ^ self primitiveFailed!
  47081. primSoundStartBufferSize: bufferSize rate: samplesPerSecond stereo: stereoFlag
  47082.     "Start double-buffered sound output with the given buffer size and sampling rate."
  47083.  
  47084.     <primitive: 170>
  47085.     ^ self primitiveFailed!
  47086. primSoundStop
  47087.     "Stop double-buffered sound output."
  47088.  
  47089.     <primitive: 172>
  47090.     ^ self primitiveFailed! !
  47091.  
  47092. SoundPlayer initialize!
  47093. Path subclass: #Spline
  47094.     instanceVariableNames: 'coefficients '
  47095.     classVariableNames: ''
  47096.     poolDictionaries: ''
  47097.     category: 'Graphics-Paths'!
  47098. Spline comment:
  47099. 'I represent a collection of Points through which a cubic spline curve is fitted.'!
  47100.  
  47101. !Spline methodsFor: 'accessing'!
  47102. coefficients
  47103.     "Answer an eight-element Array of Arrays each of which is the length 
  47104.     of the receiver. The first four arrays are the values, first, second and 
  47105.     third derivatives, respectively, for the parametric spline in x. The last 
  47106.     four elements are for y."
  47107.  
  47108.     ^coefficients! !
  47109.  
  47110. !Spline methodsFor: 'displaying'!
  47111. computeCurve
  47112.     "Compute an array for the coefficients."
  47113.  
  47114.     | length extras |
  47115.     length _ self size.
  47116.     extras _ 0.
  47117.     coefficients _ Array new: 8.
  47118.     1 to: 8 do: [:i | coefficients at: i put: (Array new: length + extras)].
  47119.     1 to: 5 by: 4 do: 
  47120.         [:k | 
  47121.         1 to: length do:
  47122.             [:i | (coefficients at: k)
  47123.                     at: i put: (k = 1
  47124.                         ifTrue: [(self at: i) x asFloat]
  47125.                         ifFalse: [(self at: i) y asFloat])].
  47126.             1 to: extras do: [:i | (coefficients at: k)
  47127.                     at: length + i put: ((coefficients at: k)
  47128.                         at: i + 1)].
  47129.             self derivs: (coefficients at: k)
  47130.                 first: (coefficients at: k + 1)
  47131.                 second: (coefficients at: k + 2)
  47132.                 third: (coefficients at: k + 3)].
  47133.     extras > 0 
  47134.         ifTrue: [1 to: 8 do: 
  47135.                     [:i | 
  47136.                     coefficients at: i put: ((coefficients at: i)
  47137.                                             copyFrom: 2 to: length + 1)]]!
  47138. displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm 
  47139.     "Display the receiver, a spline curve, approximated by straight line
  47140.     segments."
  47141.  
  47142.     | n line t x y x1 x2 x3 y1 y2 y3 |
  47143.     collectionOfPoints size < 1 ifTrue: [self error: 'a spline must have at least one point'].
  47144.     line _ Line new.
  47145.     line form: self form.
  47146.     line beginPoint: 
  47147.         (x _ (coefficients at: 1) at: 1) rounded @ (y _ (coefficients at: 5) at: 1) rounded.
  47148.     1 to: (coefficients at: 1) size - 1 do: 
  47149.         [:i | 
  47150.         "taylor series coefficients"
  47151.         x1 _ (coefficients at: 2) at: i.
  47152.         y1 _ (coefficients at: 6) at: i.
  47153.         x2 _ ((coefficients at: 3) at: i) / 2.0.
  47154.         y2 _ ((coefficients at: 7) at: i) / 2.0.
  47155.         x3 _ ((coefficients at: 4) at: i) / 6.0.
  47156.         y3 _ ((coefficients at: 8) at: i) / 6.0.
  47157.         "guess n"
  47158.         n _ 5 max: (x2 abs + y2 abs * 2.0 + ((coefficients at: 3)
  47159.                             at: i + 1) abs + ((coefficients at: 7)
  47160.                             at: i + 1) abs / 100.0) rounded.
  47161.         1 to: n - 1 do: 
  47162.             [:j | 
  47163.             t _ j asFloat / n.
  47164.             line endPoint: 
  47165.                 (x3 * t + x2 * t + x1 * t + x) rounded 
  47166.                             @ (y3 * t + y2 * t + y1 * t + y) rounded.
  47167.             line
  47168.                 displayOn: aDisplayMedium
  47169.                 at: aPoint
  47170.                 clippingBox: clipRect
  47171.                 rule: anInteger
  47172.                 fillColor: aForm.
  47173.             line beginPoint: line endPoint].
  47174.         line beginPoint: 
  47175.                 (x _ (coefficients at: 1) at: i + 1) rounded 
  47176.                     @ (y _ (coefficients at: 5) at: i + 1) rounded.
  47177.         line
  47178.             displayOn: aDisplayMedium
  47179.             at: aPoint
  47180.             clippingBox: clipRect
  47181.             rule: anInteger
  47182.             fillColor: aForm]!
  47183. displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm 
  47184.     "Get the scaled and translated path of newKnots."
  47185.  
  47186.     | newKnots newSpline |
  47187.     newKnots _ aTransformation applyTo: self.
  47188.     newSpline _ Spline new.
  47189.     newKnots do: [:knot | newSpline add: knot].
  47190.     newSpline form: self form.
  47191.     newSpline
  47192.         displayOn: aDisplayMedium
  47193.         at: 0 @ 0
  47194.         clippingBox: clipRect
  47195.         rule: anInteger
  47196.         fillColor: aForm! !
  47197.  
  47198. !Spline methodsFor: 'private'!
  47199. derivs: a first: point1 second: point2 third: point3
  47200.     "Compute the first, second and third derivitives (in coefficients) from
  47201.     the Points in this Path (coefficients at: 1 and coefficients at: 5)."
  47202.  
  47203.     | l v anArray |
  47204.     l _ a size.
  47205.     l < 2 ifTrue: [^self].
  47206.     l > 2
  47207.       ifTrue:
  47208.         [v _ Array new: l.
  47209.          v  at:  1 put: 4.0.
  47210.          anArray _ Array new: l.
  47211.          anArray  at:  1 put: (6.0 * ((a  at:  1) - ((a  at:  2) * 2.0) + (a  at:  3))).
  47212.          2 to: l - 2 do:
  47213.             [:i | 
  47214.             v  at:  i put: (4.0 - (1.0 / (v  at:  (i - 1)))).
  47215.             anArray
  47216.                 at:  i 
  47217.                 put: (6.0 * ((a  at:  i) - ((a  at:  (i + 1)) * 2.0) + (a  at:  (i + 2)))
  47218.                         - ((anArray  at:  (i - 1)) / (v  at:  (i - 1))))].
  47219.          point2  at: (l - 1) put: ((anArray  at:  (l - 2)) / (v  at:  (l - 2))).
  47220.          l - 2 to: 2 by: 0-1 do: 
  47221.             [:i | 
  47222.             point2 
  47223.                 at: i 
  47224.                 put: ((anArray  at:  (i - 1)) - (point2  at:  (i + 1)) / (v  at:  (i - 1)))]].
  47225.     point2 at: 1 put: (point2  at:  l put: 0.0).
  47226.     1 to: l - 1 do:
  47227.         [:i | point1 
  47228.                 at: i 
  47229.                 put: ((a at: (i + 1)) - (a  at:  i) - 
  47230.                         ((point2  at:  i) * 2.0 + (point2  at:  (i + 1)) / 6.0)).
  47231.               point3 at: i put: ((point2  at:  (i + 1)) - (point2  at:  i))]! !
  47232. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  47233.  
  47234. Spline class
  47235.     instanceVariableNames: ''!
  47236.  
  47237. !Spline class methodsFor: 'examples'!
  47238. example
  47239.     "Designate points on the Path by clicking the red button. Terminate by
  47240.     pressing any other button. A curve will be displayed, through the
  47241.     selected points, using a long black form."
  47242.  
  47243.     | splineCurve aForm flag|
  47244.     aForm _ Form extent: 1@40.
  47245.     aForm  fillBlack.
  47246.     splineCurve _ Spline new.
  47247.     splineCurve form: aForm.
  47248.     flag _ true.
  47249.     [flag] whileTrue:
  47250.         [Sensor waitButton.
  47251.          Sensor redButtonPressed
  47252.             ifTrue: 
  47253.                 [splineCurve add: Sensor waitButton. 
  47254.                  Sensor waitNoButton.
  47255.                  aForm displayOn: Display at: splineCurve last]
  47256.             ifFalse: [flag_false]].
  47257.     splineCurve computeCurve.
  47258.     splineCurve isEmpty 
  47259.         ifFalse: [splineCurve displayOn: Display.
  47260.                 Sensor waitNoButton].
  47261.  
  47262.     "Spline example"! !FileStream subclass: #StandardFileStream
  47263.     instanceVariableNames: 'name fileID buffer1 sizeCache '
  47264.     classVariableNames: ''
  47265.     poolDictionaries: ''
  47266.     category: 'System-Files'!
  47267. StandardFileStream comment:
  47268. 'Provides a simple, platform-independent, interface to a file system.  This initial version ignores issues of Directories etc.  The instance-variable fallbackStream at the moment holds an instance of HFSMacFileStream, to bridge us to the new world while in the old.  The instance variable rwmode, inherited from class PositionableStream, here is used to hold a Boolean -- true means opened for read-write, false means opened for read-only.  2/12/96 sw'!
  47269.  
  47270. !StandardFileStream methodsFor: 'open/close'!
  47271. close
  47272.     "Close the receiver.  12/12/96 sw"
  47273.  
  47274.     self primClose: fileID.
  47275.     closed _ true!
  47276. open
  47277.     "For compatibility with a few existing things.  2/14/96 sw"
  47278.  
  47279.     ^ self reopen!
  47280. open: aFileName forWrite: writeMode 
  47281.     "Open the receiver.  If writeMode is true, allow write, else access will be read-only.  2/12/96 sw"
  47282.     fileID _ self primOpen: aFileName writable: writeMode.
  47283.     fileID == nil ifTrue: [^ nil].
  47284.     name _ aFileName.
  47285.     rwmode _ writeMode.
  47286.     buffer1 _ String new: 1.
  47287.     closed _ false!
  47288. openReadOnly
  47289.     "Open the receiver as a read-only file.  1/31/96 sw"
  47290.  
  47291.     ^ self open: name forWrite: false!
  47292. reopen
  47293.     "Reopen the receiver, in the same mode as previously, first closing it if applicable.  1/31/96 sw"
  47294.  
  47295.     closed ifFalse: [self close].
  47296.     self open: name forWrite: rwmode! !
  47297.  
  47298. !StandardFileStream methodsFor: 'properties-setting'!
  47299. ascii
  47300.     "opposite of binary"
  47301.     buffer1 _ String new: 1!
  47302. asHtml
  47303.     "Convert me in to an HtmlFileStream. 4/11/96 tk"
  47304.  
  47305.     ^ self as: HtmlFileStream 
  47306. !
  47307. binary
  47308.     buffer1 _ ByteArray new: 1!
  47309. insertLineFeeds
  47310.     "(FileStream oldFileNamed: 'BBfix2.st') insertLineFeeds"
  47311.     | s crLf f |
  47312.     crLf _ String with: Character cr with: (Character value: 10).
  47313.     s _ ReadStream on: (self next: self size).
  47314.     self close.
  47315.     f _ FileStream newFileNamed: self name.
  47316.     [s atEnd] whileFalse: 
  47317.         [f nextPutAll: (s upTo: Character cr); nextPutAll: crLf].
  47318.     f close!
  47319. isBinary
  47320.     ^ buffer1 class == ByteArray!
  47321. readOnly
  47322.     "Set the receiver to be read-only"
  47323.  
  47324.     rwmode _ false!
  47325. setType: tString creator: cString
  47326.     "Mac-specific; set the type and creator of the corresponding file; for the moment, we only define this where we have the backward-compatible implementation via fallback stream.  Ultimately, for this to work, some new primitive will need to be added to StandardFileStream.  2/14/96 sw"
  47327. !
  47328. writing
  47329.     "Answer whether the receiver is in the process of writing.  Probably obsolete -- only sender outside of HFS-specific code is in FileStream>>close, which is, in effect, abstract, and not actually reached now.  I THINK.  2/12/96 sw"
  47330.  
  47331.     ^ rwmode! !
  47332.  
  47333. !StandardFileStream methodsFor: 'access'!
  47334. file
  47335.     "Answer the object representing the receiver's file.  Need for compatibility with some calls -- check senders.  2/14/96 sw"
  47336.  
  47337.     ^ self!
  47338. fileID
  47339.     "Return the fileID that was handed returned by the file-opening primitive.  This id needs to be handed on to the other file-related primitives.  2/12/96 sw"
  47340.  
  47341.     ^ fileID!
  47342. fullName
  47343.     ^ name!
  47344. isDirectory
  47345.     "Answer whether the receiver represents a directory.  For the post-transition case, uncertain what to do.  2/14/96 sw"
  47346.     ^ false!
  47347. name
  47348.     "Answer the receiver's name, which is the same as the formal filename on disk.  1/31/96 sw"
  47349.  
  47350.     ^ name!
  47351. peekFor: item 
  47352.     "Answer false and do not move over the next element if it is not equal to 
  47353.     the argument, anObject, or if the receiver is at the end. Answer true 
  47354.     and increment the position for accessing elements, if the next element is 
  47355.     equal to anObject..  Copied over from HFS versino.  2/14/96 sw"
  47356.  
  47357.     | next |
  47358.  
  47359.     self atEnd ifTrue: [^ false].
  47360.     next _ self next.
  47361.     item = next ifTrue: [^ true].
  47362.     self skip: -1.
  47363.     ^ false!
  47364. printOn: aStream
  47365.     "Put a printed version of the receiver onto aStream.  1/31/96 sw"
  47366.  
  47367.     aStream nextPutAll: self class name; nextPutAll: ': '; print: name!
  47368. reset
  47369.     ^ self reopen!
  47370. size
  47371.     "Answer the size of the file in characters.  2/12/96 sw"
  47372.  
  47373.     ^ self primSize: fileID! !
  47374.  
  47375. !StandardFileStream methodsFor: 'read, write, position'!
  47376. atEnd
  47377.     "Answer whether the receiver is at its end.  2/12/96 sw"
  47378. "
  47379.     ^ self primAtEnd: fileID
  47380. "
  47381.     "Cache the file size"
  47382.     sizeCache == nil ifTrue: [sizeCache _ self primSize: fileID].
  47383.     (self primGetPosition: fileID) >= sizeCache
  47384.         ifTrue: ["If the cache says we're at end,
  47385.                 check it again, in case we have written some"
  47386.                 sizeCache _ self primSize: fileID.
  47387.                 ^ (self primGetPosition: fileID) >= sizeCache]
  47388.         ifFalse: [^ false]!
  47389. flush
  47390.     "In some OS's seeking to 0 and back will do a flush"
  47391.     | p |
  47392.     p _ self position.
  47393.     self position: 0; position: p!
  47394. next
  47395.     "Read the next object from the file. 2/12/96 sw"
  47396.     self primRead: fileID into: buffer1 startingAt: 1 count: 1.
  47397.     ^ buffer1 at: 1!
  47398. next: n
  47399.     "Return a string with the next n characters of the filestream in it.  1/31/96 sw"
  47400.     ^ self nextInto: (buffer1 class new: n)!
  47401. nextInto: aString
  47402.     "Fill aString, whose size dictates the size of the read, with characters from the receiver.  1/31/96 sw"
  47403.     | count wanted |
  47404.     count _ self primRead: fileID into: aString
  47405.                 startingAt: 1 count: (wanted _ aString size).
  47406.     count < wanted ifTrue: [^ aString copyFrom: 1 to: count].
  47407.     ^ aString!
  47408. nextPut: char
  47409.     "Put char on the receiver stream.  2/12/96 sw"
  47410.     buffer1 at: 1 put: char.
  47411.     self primWrite: fileID from: buffer1
  47412.         startingAt: 1 count: 1.
  47413.     ^ char!
  47414. nextPutAll: aString
  47415.     "Write all the characters of aString into the receiver's file.  2/12/96 sw"
  47416.     self primWrite: fileID from: aString startingAt: 1 count: aString size.
  47417.     ^ aString!
  47418. peek
  47419.     "Answer what would be returned if the message next were sent to the receiver. If the receiver is at the end, answer nil.  1/31/96 sw"
  47420.     | next |
  47421.     self atEnd ifTrue: [^ nil].
  47422.     next _ self next.
  47423.     self position: self position - 1.
  47424.     ^ next!
  47425. position
  47426.     "Return the receiver's current file position.  2/12/96 sw"
  47427.  
  47428.     ^ self primGetPosition: fileID!
  47429. position: pos
  47430.     "Set the receiver's position as indicated.  2/12/96 sw"
  47431.  
  47432.     ^ self primSetPosition: fileID to: pos!
  47433. readInto: byteArray startingAt: startIndex count: count
  47434.     "Read into the given array as specified, and return the count
  47435.     actually transferred.  index and count are in units of bytes or
  47436.     longs depending on whether the array is Bitmap, String or ByteArray"
  47437.     ^ self primRead: fileID into: byteArray
  47438.             startingAt: startIndex count: count
  47439. !
  47440. readOnlyCopy
  47441.     ^ StandardFileStream readOnlyFileNamed: self name!
  47442. setToEnd
  47443.     "Set the position of the receiver to the end of file.  1/31/96 sw"
  47444.  
  47445.     self position: self size!
  47446. skip: n
  47447.     "Set the character position to n characters from the current position.
  47448.     Error if not enough characters left in the file.  1/31/96 sw"
  47449.  
  47450.     self position: self position + n!
  47451. upTo: delim 
  47452.     "Fast version to speed up nextChunk"
  47453.     | pos buffer count |
  47454.     pos _ self position.
  47455.     buffer _ self next: 2000.
  47456.     (count _ buffer indexOf: delim) > 0 ifTrue: 
  47457.         ["Found the delimiter part way into buffer"
  47458.         self position: pos + count.
  47459.         ^ buffer copyFrom: 1 to: count - 1].
  47460.     self atEnd ifTrue:
  47461.         ["Never found it, and hit end of file"
  47462.         ^ buffer].
  47463.     "Never found it, but there's more..."
  47464.     ^ buffer , (self upTo: delim)! !
  47465.  
  47466. !StandardFileStream methodsFor: 'primitives'!
  47467. primAtEnd: id
  47468.     "Answer whether the receiver is currently at its end.  2/12/96 sw"
  47469.  
  47470.     <primitive: 150>
  47471.     ^ self primitiveFailed!
  47472. primClose: anID
  47473.     "Primitive call to close the receiver.  2/12/96 sw"
  47474.     <primitive: 151>
  47475.     ^ self primitiveFailed!
  47476. primGetPosition: id
  47477.     "Get the receiver's current file position.  2/12/96 sw"
  47478.     <primitive: 152>
  47479.     ^ self primitiveFailed!
  47480. primOpen: fileName writable: aBoolean
  47481.     "Open a file of the given name, and return the file id obtained.
  47482.     If writable is true, then
  47483.         if there is none with this name, then create one
  47484.         else prepare to overwrite from the beginning
  47485.     otherwise open readonly,
  47486.         or return nil if there is no file with this name"
  47487.  
  47488.     <primitive: 153>
  47489.     ^ nil!
  47490. primRead: id into: byteArray startingAt: startIndex count: count
  47491.     "read from the receiver's file into the given area of storage, starting at the given index, as many as count bytes; return the number of bytes actually read.  2/12/96 sw"
  47492.  
  47493.     <primitive: 154>
  47494.  
  47495.     self halt: 'error reading file'!
  47496. primSetPosition: id to: aNumber
  47497.     "Set the receiver's file position to be a Number.  2/12/96 sw"
  47498.     <primitive: 155>
  47499.     ^ self primitiveFailed!
  47500. primSize: id
  47501.     "Return the size of the receiver's file.  2/12/96 sw"
  47502.     <primitive: 157>
  47503.     ^ self primitiveFailed!
  47504. primWrite: id from: byteArray startingAt: startIndex count: count
  47505.     "Write into the receiver's file from the given area of storage, starting at the given index, as many as count bytes; return the number of bytes actually written. 2/12/96 sw"
  47506.  
  47507.     <primitive: 158>
  47508.  
  47509.     closed ifTrue: [^ self halt: 'Write error: File not open'].
  47510.     rwmode ifFalse: [^ self halt: 'Error-attempt to write to a read-only file.'].
  47511.     self halt: 'File write error'! !
  47512. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  47513.  
  47514. StandardFileStream class
  47515.     instanceVariableNames: ''!
  47516.  
  47517. !StandardFileStream class methodsFor: 'file creation'!
  47518. fileNamed: aFileName 
  47519.      "Open a file in the default directory (or in the directory contained
  47520.     in the input arg); by default, it's available for writing.  2/12/96 sw
  47521.     Prior contents will be overwritten, but not truncated on close.  3/18 di"
  47522.  
  47523.     ^ self new open: aFileName forWrite: true!
  47524. isAFileNamed: fName
  47525.     | f |
  47526.     f _ self new open: fName forWrite: false.
  47527.     f == nil ifTrue: [^ false].
  47528.     f close.
  47529.     ^ true!
  47530. newFileNamed: aFileName
  47531.      "create a file in the default directory (or in the directory contained in the input arg), set for write access.  2/12/96 sw.  Fixed 6/13/96 sw so that if deletion of old conflicting file fails, the error raised is more helpful."
  47532.  
  47533.     | result |
  47534.     (self isAFileNamed: aFileName)
  47535.         ifTrue:
  47536.             [(self confirm: (self localNameFor: aFileName) , ' already exists.
  47537. Do you want to overwrite it?')
  47538.                 ifTrue: [result _ FileDirectory default deleteFileNamed: aFileName.
  47539.                     result == nil ifTrue: "deletion failed"
  47540.                         [self halt: 'Sorry - deletion failed']]
  47541.                 ifFalse: [self halt]].
  47542.     ^ self new open: aFileName forWrite: true!
  47543. oldFileNamed: aFileName 
  47544.      "Open a file in the default directory (or in the directory contained
  47545.     in the input arg); by default, it's available for reading.  2/12/96 sw
  47546.     Prior contents will be overwritten, but not truncated on close.  3/18 di"
  47547.  
  47548.     (self isAFileNamed: aFileName) ifFalse:
  47549.         [(self confirm: 'Could not find ' , (self localNameFor: aFileName) , '.
  47550. Do you want to create it?')
  47551.             ifFalse: [self halt]].
  47552.     ^ self new open: aFileName forWrite: true!
  47553. readOnlyFileNamed: aFileName
  47554.     "Open a file of the given name for read-only access.  1/31/96 sw"
  47555.     | f |
  47556.     f _ self new open: aFileName forWrite: false.
  47557.     f == nil ifTrue: [self halt: 'Could not find ' , (self localNameFor: aFileName)].
  47558.     ^ f! !MouseMenuController subclass: #StandardSystemController
  47559.     instanceVariableNames: 'status '
  47560.     classVariableNames: 'ScheduledBlueButtonMessages ScheduledBlueButtonMenu '
  47561.     poolDictionaries: ''
  47562.     category: 'Interface-Support'!
  47563. StandardSystemController comment:
  47564. 'I am a controller for StandardSystemViews, that is, those views that are at the top level of a project in the system user interface. I am a kind of MouseMenuController that creates a blue button menu for moving, framing, collapsing, and closing ScheduledViews, and for selecting views under the view of my instance.'!
  47565.  
  47566. !StandardSystemController methodsFor: 'initialize-release'!
  47567. initialize
  47568.  
  47569.     super initialize.
  47570.     status _ #inactive.
  47571.     self initializeBlueButtonMenu!
  47572. initializeBlueButtonMenu
  47573.     "Initialize the blue button pop-up menu and corresponding array of
  47574.     messages for the receiver."
  47575.  
  47576.     self blueButtonMenu: ScheduledBlueButtonMenu 
  47577.         blueButtonMessages: ScheduledBlueButtonMessages! !
  47578.  
  47579. !StandardSystemController methodsFor: 'control defaults'!
  47580. controlActivity
  47581.     self checkForReframe.
  47582.     ^ super controlActivity!
  47583. isControlActive
  47584.     status == #active ifFalse: [^ false].
  47585.     sensor anyButtonPressed ifFalse: [^ true].
  47586.     self viewHasCursor
  47587.         ifTrue: [^ true]
  47588.         ifFalse: [ScheduledControllers noteNewTop.
  47589.                 ^ false]!
  47590. modelUnchanged
  47591.     "Answer true if the receiver's model is unchanged, and hence able to be closed without great ceremony, if necessary.  2/5/96 sw"
  47592.  
  47593.     ^ model hasBeenChanged not! !
  47594.  
  47595. !StandardSystemController methodsFor: 'basic control sequence'!
  47596. controlInitialize
  47597.     view displayEmphasized.
  47598.     sensor waitNoButton.
  47599.     status _ #active!
  47600. controlTerminate
  47601.     status == #closed
  47602.         ifTrue: 
  47603.             [view ~~ nil ifTrue: [view release].
  47604.             ScheduledControllers unschedule: self.
  47605.             ^self].
  47606.     view deEmphasize; cacheBits!
  47607. redButtonActivity
  47608.     "If cursor is in label of a window when red button is pushed ,
  47609.     check for closeBox or growBox, else drag the window frame.
  47610.     5/10/96 sw: factored mouse-tracking-within-boxes into 
  47611.         awaitMouseUpIn:ifSucceed:
  47612.     5/12/96 sw: instead, call Utilities awaitMouseUpIn:repeating:ifSucceed:"
  47613.     | box p inside |
  47614.     p _ sensor cursorPoint.
  47615.     self labelHasCursor ifFalse: [super redButtonActivity. ^ self].
  47616.     sensor blueButtonPressed & self viewHasCursor 
  47617.         ifTrue: [^ self blueButtonActivity].
  47618.     ((box _ view closeBoxFrame) containsPoint: p)
  47619.         ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed: [self close. ^ self].
  47620.                 ^ self].
  47621.     ((box _ view growBoxFrame) containsPoint: p)
  47622.         ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed:
  47623.                     [^ view isCollapsed
  47624.                         ifTrue: [self expand]
  47625.                         ifFalse: [self collapse]].
  47626.                 ^ self].
  47627.     ((box _ view labelTextRegion expandBy: 1) containsPoint: p)
  47628.         ifTrue: [Utilities awaitMouseUpIn: box repeating: [] ifSucceed:
  47629.                     [^ self label].
  47630.                 ^ self].
  47631.     self move.
  47632. ! !
  47633.  
  47634. !StandardSystemController methodsFor: 'menu messages'!
  47635. chooseColor
  47636.     "Allow the user to specify a new background color for the receiver's window.  5/6/96 sw.
  47637.      7/31/96 sw: use Color fromUser"
  47638.  
  47639.     view backgroundColor: Color fromUser; uncacheBits; display!
  47640. close
  47641.     "The receiver's view should be removed from the screen and from the 
  47642.     collection of scheduled views."
  47643.  
  47644.     model okToChange ifFalse: [^self].
  47645.     status _ #closed.
  47646.     view erase!
  47647. collapse
  47648.     "Get the receiver's view to change to a collapsed view on the screen."
  47649.     | collapsePoint |
  47650.     collapsePoint _ view chooseCollapsePoint.
  47651.     view collapse.
  47652.     view align: view displayBox topLeft with: collapsePoint.
  47653.     view displayEmphasized!
  47654. expand
  47655.     "The receiver's view was collapsed; open it again and ask the user to 
  47656.     designate its rectangular area."
  47657.     view expand; emphasize!
  47658. label
  47659.     | newLabel |
  47660.     FillInTheBlank
  47661.         request: 'Edit the label, then type RETURN.'
  47662.         displayAt: Sensor cursorPoint - (0@8)
  47663.         centered: true
  47664.         action: [:x | newLabel _ x]
  47665.         initialAnswer: view label.
  47666.     newLabel isEmpty ifFalse:
  47667.         [view relabel: newLabel]!
  47668. macPaint
  47669.     "Create a MacPaint diskfile of the view's contents.  The resulting diskfile can be printed using MacPaint."
  47670.     | f menuIndex |
  47671.     menuIndex _ (PopUpMenu labels: 'cancel printing
  47672. show label
  47673. hide label') startUpWithCaption: 'Should the label tag be included?'.
  47674.     menuIndex <= 1 ifTrue: [^self].
  47675.     f _ FileStream fileNamed: (view label,'.paint').
  47676.     menuIndex == 2
  47677.         ifTrue: [view deEmphasizeLabel.
  47678.                 (Form fromDisplay: view displayBox)
  47679.                     bigMacPaintOn: f label: view labelDisplayBox.
  47680.                 view emphasizeLabel.]
  47681.         ifFalse: [(Form fromDisplay: view displayBox) bigMacPaintOn: f].
  47682.     f close!
  47683. menuMessageReceiver
  47684.     "Answer the object that should receive the message corresponding to
  47685.     a menu selection."
  47686.  
  47687.     ^self!
  47688. move
  47689.     "Ask the user to designate a new origin position for the receiver's view.
  47690.     6/10/96 sw: tell the view that it has moved"
  47691.  
  47692.     | oldBox | 
  47693.     oldBox _ view windowBox.
  47694.     view uncacheBits.
  47695.     view align: view windowBox topLeft
  47696.         with: view chooseMoveRectangle topLeft.
  47697.     view displayEmphasized.
  47698.     view moved.  "In case its model wishes to take note."
  47699.     (oldBox areasOutside: view windowBox) do:
  47700.         [:rect | ScheduledControllers restore: rect]!
  47701. under
  47702.     "Deactive the receiver's scheduled view and pass control to any view that 
  47703.     might be positioned directly underneath it and the cursor."
  47704.  
  47705.     status _ #inactive! !
  47706.  
  47707. !StandardSystemController methodsFor: 'scheduling'!
  47708. closeAndUnschedule
  47709.     "Erase the receiver's view and remove it from the collection of scheduled 
  47710.     views."
  47711.  
  47712.     status _ #closed.
  47713.     view erase.
  47714.     view release.
  47715.     ScheduledControllers unschedule: self!
  47716. closeAndUnscheduleNoErase
  47717.     "Remove the scheduled view from the collection of scheduled views. Set 
  47718.     its status to closed but do not erase."
  47719.  
  47720.     status _ #closed.
  47721.     view release.
  47722.     ScheduledControllers unschedule: self!
  47723. open
  47724.     "Create an area on the screen in which the receiver's scheduled view can 
  47725.     be displayed. Make it the active view."
  47726.  
  47727.     view resizeInitially.
  47728.     status _ #open.
  47729.     ScheduledControllers scheduleActive: self!
  47730. openDisplayAt: aPoint 
  47731.     "Create an area with origin aPoint in which the receiver's scheduled 
  47732.     view can be displayed. Make it the active view."
  47733.  
  47734.     view align: view viewport center with: aPoint.
  47735.     view translateBy:
  47736.         (view displayBox amountToTranslateWithin: Display boundingBox).
  47737.     status _ #open.
  47738.     ScheduledControllers scheduleActive: self!
  47739. openNoTerminate
  47740.     "Create an area in which the receiver's scheduled view can be displayed. 
  47741.     Make it the active view. Do not terminate the currently active process."
  47742.  
  47743.     view resize.
  47744.     status _ #open.
  47745.     ScheduledControllers scheduleActiveNoTerminate: self!
  47746. openNoTerminateDisplayAt: aPoint 
  47747.     "Create an area with origin aPoint in which the receiver's scheduled 
  47748.     view can be displayed. Make it the active view. Do not terminate the 
  47749.     currently active process."
  47750.  
  47751.     view resizeMinimumCenteredAt: aPoint.
  47752.     status _ #open.
  47753.     ScheduledControllers scheduleActiveNoTerminate: self!
  47754. status: aSymbol
  47755.     status _ aSymbol! !
  47756.  
  47757. !StandardSystemController methodsFor: 'borders'!
  47758. checkForReframe
  47759.     | box cornerBox clicked p |
  47760.     view isCollapsed ifTrue: [^ self].
  47761.     box _ view windowBox.
  47762.     #(topLeft topRight bottomRight bottomLeft)
  47763.         with: #(topLeft: topRight: bottomRight: bottomLeft:)
  47764.         do: [:readCorner :writeCorner |
  47765.             cornerBox _ (box perform: readCorner) - (8@8) extent: 16@16.
  47766.             (cornerBox containsPoint: (p _ sensor cursorPoint))
  47767.                 & (box containsPoint: p) not
  47768.                 ifTrue: 
  47769.                 [clicked _ false.
  47770.                 (Cursor perform: readCorner) showWhile:
  47771.                     [[(cornerBox containsPoint: (p _ sensor cursorPoint))
  47772.                         & (box containsPoint: p) not
  47773.                         and: [(clicked _ sensor anyButtonPressed) not]]
  47774.                         whileTrue.
  47775.                 clicked ifTrue:
  47776.                     [view newFrame:
  47777.                         [:f | f copy perform: writeCorner with: sensor cursorPoint]]]]]!
  47778. fullScreen
  47779.     "Make the receiver's window occupy jes' about the full screen.  6/10/96 sw"
  47780.  
  47781.     view fullScreen! !
  47782.  
  47783. !StandardSystemController methodsFor: 'cursor'!
  47784. labelHasCursor
  47785.     "Answer true if the cursor is within the window's label"
  47786.     ^view labelContainsPoint: sensor cursorPoint! !
  47787. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  47788.  
  47789. StandardSystemController class
  47790.     instanceVariableNames: ''!
  47791.  
  47792. !StandardSystemController class methodsFor: 'class initialization'!
  47793. initialize
  47794.     "Set up the menus for standard windows.  
  47795.      6/6/96 sw: added fullScreen"
  47796.  
  47797.     self flag: #noteToDan.   "
  47798. 1.  note that I added a fullScreen command.
  47799. 2.  the old macPaint command appears to be broken.  We should presumably fix it or discard it.
  47800. 3.  the frame command seems no longer to allow you to reframe an open window, and of course its functionality has now been overtaken by the drag-corners stuff.
  47801. 4.  move and label and collapse and close are all redundant with title-bar controls.
  47802.  
  47803. With the above in mind, I've for the moment removed macPaint and frame, but kept the four redundant commands to use in those cases where owing to some bug you can't see a window's title bar.  
  47804.  
  47805. 6/10/96 sw"
  47806.  
  47807.     ScheduledBlueButtonMenu _ PopUpMenu labels: 'label
  47808. color...
  47809. move
  47810. full screen
  47811. collapse
  47812. close' 
  47813.  
  47814. "frame 
  47815. macPaint"
  47816.  
  47817.     lines: #(2).  "6"
  47818.  
  47819.     ScheduledBlueButtonMessages _ #(label chooseColor move "expand" fullScreen collapse close "macPaint")
  47820.  
  47821.     "StandardSystemController initialize.
  47822.     ScheduledControllers scheduledControllers
  47823.         do: [:c | (c isKindOf: ScreenController)
  47824.             ifFalse: [c initializeBlueButtonMenu]]"! !
  47825.  
  47826. StandardSystemController initialize!
  47827. View subclass: #StandardSystemView
  47828.     instanceVariableNames: 'labelFrame labelText isLabelComplemented savedSubViews minimumSize maximumSize collapsedViewport expandedViewport labelBits windowBits bitsValid '
  47829.     classVariableNames: 'CacheBits '
  47830.     poolDictionaries: ''
  47831.     category: 'Interface-Support'!
  47832. StandardSystemView comment:
  47833. 'I represent a view that has a label above its top left corner. The text in the label identifies the kind of view. In addition to a label, I add control over the maximum and minimum size of the display box of my instance. My default controller is StandardSystemController. The elements of ScheduledControllers, the sole instance of ControlManager, are usually controllers for instances of me.'!
  47834.  
  47835. !StandardSystemView methodsFor: 'initialize-release'!
  47836. initialize 
  47837.     "Refer to the comment in View|initialize."
  47838.     super initialize.
  47839.     labelFrame _ Quadrangle new.
  47840.     labelFrame region: (Rectangle origin: 0 @ 0 extent: 50 @ 18).
  47841.     labelFrame borderWidthLeft: 2 right: 2 top: 2 bottom: 0.
  47842.     self label: nil.
  47843.     isLabelComplemented _ false.
  47844.     minimumSize _ 50 @ 50.
  47845.     maximumSize _ Display extent.
  47846.     collapsedViewport _ nil.
  47847.     expandedViewport _ nil.
  47848.     bitsValid _ false.!
  47849. model: aModel
  47850.     "Set the receiver's model.  For a Standard System View, we also at this time get the default background color set up.  7/30/96 sw"
  47851.     super model: aModel.
  47852.     self setDefaultBackgroundColor! !
  47853.  
  47854. !StandardSystemView methodsFor: 'testing'!
  47855. closeBoxFrame
  47856.     ^ Rectangle origin: (self labelDisplayBox origin + (10@4)) extent: (11@11)!
  47857. containsPoint: aPoint 
  47858.     "Refer to the comment in View|containsPoint:."
  47859.  
  47860.     ^(super containsPoint: aPoint) | (self labelContainsPoint: aPoint)!
  47861. growBoxFrame
  47862.     ^ Rectangle origin: (self labelDisplayBox topRight + (-22@4)) extent: (11@11)!
  47863. isCollapsed
  47864.     "Answer whether the receiver is collapsed (true) or expanded (false)."
  47865.  
  47866.     ^savedSubViews ~~ nil!
  47867. labelContainsPoint: aPoint 
  47868.     "Answer TRUE if aPoint is in the label box."
  47869.  
  47870.     ^self labelDisplayBox containsPoint: aPoint! !
  47871.  
  47872. !StandardSystemView methodsFor: 'label access'!
  47873. deEmphasizeLabel
  47874.     "Clear the racing stripes."
  47875.     | labelDisplayBox top bottom left box right |
  47876.     labelDisplayBox _ self labelDisplayBox.
  47877.     top _ labelDisplayBox top + 3.
  47878.     bottom _ labelDisplayBox bottom - 3.
  47879.  
  47880.     left _ labelDisplayBox left + 3.
  47881.     box _ self labelTextRegion.
  47882.     right _ box left - 3.
  47883.     Display fill: (Rectangle left: left right: right top: top bottom: bottom)
  47884.             fillColor: self labelColor.
  47885.  
  47886.     left _ box right + 2.
  47887.     right _ labelDisplayBox right - 3.
  47888.     Display fill: (Rectangle left: left right: right top: top bottom: bottom)
  47889.             fillColor: self labelColor!
  47890. emphasizeLabel
  47891.     "Highlight the label."
  47892.     self displayLabelBoxes.
  47893.     self displayRacingStripes!
  47894. label
  47895.     "Answer the string that appears in the receiver's label."
  47896.  
  47897.     ^labelText isNil
  47898.         ifTrue: [^'']
  47899.         ifFalse: [labelText asString]!
  47900. label: aString 
  47901.     "Set aString to be the receiver's label."
  47902.  
  47903.     aString == nil
  47904.         ifTrue:
  47905.             [labelText _ nil.
  47906.             labelFrame region: (0 @ 0 extent: 0 @ 0)]
  47907.         ifFalse:
  47908.             [labelText _ (Text string: aString emphasis: "11"8) asParagraph.
  47909.             insetDisplayBox == nil ifTrue: [^ self].  "wait for further initialization"
  47910.             self setLabelRegion]!
  47911. labelColor
  47912.     "Answer the color to use as the background for the receiver's label.  By default, this is the same as the background color of the window, but need not be.  7/16/96 sw"
  47913.  
  47914.     ^ self backgroundColor!
  47915. labelDisplayBox
  47916.     "Answer the rectangle that borders the visible parts of the receiver's label 
  47917.     on the display screen."
  47918.  
  47919.     ^ labelFrame region
  47920.         align: (self isCollapsed
  47921.                 ifTrue: [labelFrame topLeft]
  47922.                 ifFalse: [labelFrame bottomLeft])
  47923.         with: self displayBox topLeft!
  47924. labelTextRegion
  47925.     | topLeft |
  47926.     labelText == nil ifTrue: [^ self labelDisplayBox center extent: 0@0].
  47927.     topLeft _ self labelDisplayBox center
  47928.         + (labelText boundingBox topLeft - labelText boundingBox center).
  47929.     ^ topLeft extent: labelText boundingBox extent!
  47930. relabel: aString 
  47931.     "A new string for the label.  Window is assumed to be active.
  47932.     Window will redisplay only if label bar has to grow."
  47933.     | oldRegion oldWidth |
  47934.     oldRegion _ self labelTextRegion.
  47935.     oldWidth _ self insetDisplayBox width.
  47936.     self label: aString.
  47937.     Display fill: ((oldRegion merge: self labelTextRegion) expandBy: 3@0)
  47938.             fillColor: self labelColor.
  47939.     self insetDisplayBox width = oldWidth
  47940.         ifTrue: [self displayLabelText; emphasizeLabel]
  47941.         ifFalse: [self uncacheBits; displayEmphasized].
  47942. ! !
  47943.  
  47944. !StandardSystemView methodsFor: 'size'!
  47945. maximumSize
  47946.     "Answer a point representing the maximum width and height of the 
  47947.     receiver."
  47948.  
  47949.     ^maximumSize!
  47950. maximumSize: aPoint 
  47951.     "Set the argument, aPoint, to be the maximum width and height of the 
  47952.     receiver."
  47953.  
  47954.     maximumSize _ aPoint!
  47955. minimumSize
  47956.     "Answer a point representing the minimum width and height of the 
  47957.     receiver."
  47958.  
  47959.     ^minimumSize!
  47960. minimumSize: aPoint 
  47961.     "Set the argument, aPoint, to be the minimum width and height of the 
  47962.     receiver."
  47963.  
  47964.     minimumSize _ aPoint! !
  47965.  
  47966. !StandardSystemView methodsFor: 'framing'!
  47967. chooseCollapsePoint
  47968.     "Answer the point at which to place the collapsed window."
  47969.     | p1 labelForm beenDown offset |
  47970.     labelForm _ Form fromDisplay: self labelDisplayBox.
  47971.     self uncacheBits.
  47972.     self erase.
  47973.     beenDown _ Sensor anyButtonPressed.
  47974.     self isCollapsed | collapsedViewport isNil
  47975.         ifTrue: [offset _ self labelDisplayBox topLeft - self growBoxFrame topLeft.
  47976.                 labelForm follow: [p1 _ (Sensor cursorPoint + offset max: 0@0) truncateTo: 8]
  47977.                     while: [Sensor anyButtonPressed
  47978.                                 ifTrue: [beenDown _ true]
  47979.                                 ifFalse: [beenDown not]] ]
  47980.         ifFalse: [labelForm slideFrom: self labelDisplayBox origin
  47981.                     to: collapsedViewport origin nSteps: 10.
  47982.                 p1 _ collapsedViewport topLeft].
  47983.     ^ p1!
  47984. chooseFrame
  47985.     "Answer a new frame, depending on whether the view is currently 
  47986.     collapsed or not."
  47987.     | labelForm f |
  47988.     self isCollapsed & expandedViewport notNil
  47989.         ifTrue:
  47990.             [labelForm _ bitsValid
  47991.                 ifTrue: [windowBits]
  47992.                 ifFalse: [Form fromDisplay: self labelDisplayBox].
  47993.             bitsValid _ false.
  47994.             self erase.
  47995.             labelForm slideFrom: self labelDisplayBox origin
  47996.                     to: expandedViewport origin-(0@labelFrame height)
  47997.                     nSteps: 10.
  47998.             ^ expandedViewport]
  47999.         ifFalse:
  48000.             [f _ self getFrame.
  48001.             bitsValid _ false.
  48002.             self erase.
  48003.             ^ f topLeft + (0@ labelFrame height) extent: f extent]!
  48004. chooseMoveRectangle
  48005.     "Ask the user to designate a new window rectangle."
  48006.     | offset p |
  48007.     offset _ Sensor anyButtonPressed "Offset if draggin, eg, label"
  48008.         ifTrue: [self windowBox topLeft - Sensor cursorPoint]
  48009.         ifFalse: [0@0].
  48010.     self isCollapsed
  48011.         ifTrue: [^ self labelDisplayBox newRectFrom:
  48012.                     [:f | p _ Sensor cursorPoint + offset.
  48013.                     p _ (p max: 0@0) truncateTo: 8.
  48014.                     p extent: f extent]]
  48015.         ifFalse: [^ self windowBox newRectFrom:
  48016.                     [:f | p _ Sensor cursorPoint + offset.
  48017.                     self constrainFrame: (p extent: f extent)]]!
  48018. collapse
  48019.     "If the receiver is not already collapsed, change its view to be that of its 
  48020.     label only."
  48021.  
  48022.     self isCollapsed
  48023.         ifFalse:
  48024.             [expandedViewport _ self viewport.
  48025.             savedSubViews _ subViews.
  48026.             self resetSubViews.
  48027.             labelText isNil ifTrue: [self label: 'No Label'.  bitsValid _ false.].
  48028.             self window: (self inverseDisplayTransform: 
  48029.                 (0@0 extent: labelText extent x + 70 @ 19)).
  48030.                 "Why is the above necessary???  What does it do?".
  48031.             labelFrame borderWidthLeft: 2 right: 2 top: 2 bottom: 2]!
  48032. constrainFrame: aRectangle
  48033.     "Constrain aRectangle, to the minimum and maximum size
  48034.     for this window"
  48035.  
  48036.     ^ aRectangle origin extent:
  48037.         ((aRectangle extent max: minimumSize) min: maximumSize)!
  48038. expand
  48039.     "If the receiver is collapsed, change its view to be that of all of its 
  48040.     subviews, not its label alone. "
  48041.     | newFrame |
  48042.     self isCollapsed
  48043.         ifTrue:
  48044.             [newFrame _ self chooseFrame.
  48045.             collapsedViewport _ self viewport.
  48046.             subViews _ savedSubViews.
  48047.             self window: self defaultWindow.
  48048.             labelFrame borderWidthLeft: 2 right: 2 top: 2 bottom: 0.
  48049.             savedSubViews _ nil.
  48050.             self resizeTo: newFrame.
  48051.             self displayDeEmphasized]!
  48052. fullScreen
  48053.     "Expand the receiver to fill the screen (except for modest allowances).  6/6/96 sw"
  48054.  
  48055.     self isCollapsed ifFalse:
  48056.         [self reframeTo: (Rectangle origin: (40@2) extent: (DisplayScreen actualScreenSize - (42@4)))]!
  48057. getFrame
  48058.     "Ask the user to designate a rectangular area in which
  48059.     the receiver should be displayed."
  48060.     | minFrame |
  48061.     minFrame _ Cursor origin showWhile: 
  48062.         [(Sensor cursorPoint extent: self minimumSize) newRectFrom:
  48063.             [:f | Sensor cursorPoint extent: self minimumSize]].
  48064.     self maximumSize <= self minimumSize ifTrue: [^ minFrame].
  48065.     ^ Cursor corner showWhile:
  48066.         [minFrame newRectFrom:
  48067.             [:f | self constrainFrame: (f origin corner: Sensor cursorPoint)]]!
  48068. initialExtent
  48069.     "Answer the desired extent for the receiver when it is first opened on the screen.  1/22/96 sw"
  48070.  
  48071.     ^ model initialExtent!
  48072. initialFrame
  48073.     "Find a plausible initial screen area for the receiver, taking into account user preference, the size needed, and other windows currently on the screen.  5/22/96 sw: let RealEstateAgent do it for us"
  48074.  
  48075.     ^ RealEstateAgent initialFrameFor: self!
  48076. moved
  48077.     "The user has moved the receiver; after a new view rectangle is chosen, this method is called to allow certain views to take note of the change.  6/10/96 sw" !
  48078. newFrame: frameChangeBlock
  48079.     self reframeTo: (self windowBox newRectFrom:
  48080.         [:f | self constrainFrame: (frameChangeBlock value: f)])!
  48081. reframeTo: newFrame
  48082.     "Reframe the receiver to the given screen rectangle.  1/26/96 sw
  48083.     Repaint difference after the change.  5/8/96 di"
  48084.     | oldBox newBox portRect |
  48085.     self uncacheBits.
  48086.     oldBox _ self windowBox.
  48087.     portRect _ newFrame topLeft + (0@labelFrame height)
  48088.                 corner: newFrame corner.
  48089.     self window: self window viewport: portRect.
  48090.     self setLabelRegion.
  48091.     newBox _ self windowBox.
  48092.     (oldBox areasOutside: newBox) do:
  48093.         [:rect | ScheduledControllers restore: rect].
  48094.     self displayEmphasized!
  48095. resize
  48096.     "Determine the rectangular area for the receiver, adjusted to the 
  48097.     minimum and maximum sizes."
  48098.     | f |
  48099.     f _ self getFrame.
  48100.     self resizeTo: (f topLeft + (0@ labelFrame height) extent: f extent)
  48101. !
  48102. resizeInitially
  48103.     "Determine the rectangular area for the receiver, adjusted to the 
  48104.     minimum and maximum sizes."
  48105.     self resizeTo: self initialFrame
  48106. !
  48107. resizeMinimumCenteredAt: aPoint 
  48108.     "Determine the rectangular area for the receiver, adjusted so that it is 
  48109.     centered a position, aPoint."
  48110.  
  48111.     | aRectangle |
  48112.     aRectangle _ 0 @ 0 extent: self minimumSize.
  48113.     aRectangle _ aRectangle align: aRectangle center with: aPoint.
  48114.     self window: self window viewport: aRectangle!
  48115. resizeTo: aRectangle
  48116.     "Resize this view to aRectangle"
  48117.  
  48118.     self window: self window viewport: aRectangle.!
  48119. setLabelRegion
  48120.     "Always follows view width or label's text width"
  48121.     | aRect desiredWidth realWidth |
  48122.     aRect _ 0 @ 0 extent: 
  48123.         (self isCollapsed
  48124.             ifFalse: [
  48125.                 desiredWidth _ labelText width + 70.
  48126.                 realWidth _ self displayBox width.
  48127.                 realWidth < desiredWidth ifTrue: [
  48128.                     self window: self window viewport: 
  48129.                         (self displayBox width: desiredWidth).
  48130.                     realWidth _ desiredWidth].
  48131.                 realWidth @ 18]  "width of window"
  48132.             ifTrue: [labelText extent x + 70 @ 19] "room for buttons"
  48133.             ).
  48134.     labelFrame region: aRect.
  48135.     ^ aRect!
  48136. standardWindowOffset
  48137.     ^ Preferences standardWindowOffset!
  48138. windowBox
  48139.     ^ self displayBox merge: self labelDisplayBox! !
  48140.  
  48141. !StandardSystemView methodsFor: 'controller access'!
  48142. defaultControllerClass 
  48143.     "Refer to the comment in View|defaultControllerClass."
  48144.  
  48145.     ^StandardSystemController! !
  48146.  
  48147. !StandardSystemView methodsFor: 'displaying'!
  48148. cacheBits
  48149.     | oldLabelState |
  48150.     CacheBits ifFalse: [^ self uncacheBits].
  48151.     (oldLabelState _ isLabelComplemented) ifTrue: [ self deEmphasize ].
  48152.     self cacheBitsAsIs.
  48153.     (isLabelComplemented _ oldLabelState) ifTrue: [ self emphasize ].
  48154. !
  48155. cacheBitsAsIs
  48156.     CacheBits ifFalse: [^ self uncacheBits].
  48157.     windowBits _ (self cacheBitsAsTwoTone and: [Display depth > 1])
  48158.         ifTrue: [TwoToneForm fromDisplay: self windowBox
  48159.                         using: windowBits
  48160.                         backgroundColor: self backgroundColor]
  48161.         ifFalse: [Form fromDisplay: self windowBox using: windowBits].
  48162.     bitsValid _ true.
  48163. !
  48164. cacheBitsAsTwoTone
  48165.     ^ true!
  48166. display
  48167.     isLabelComplemented
  48168.         ifTrue: [self displayEmphasized]
  48169.         ifFalse: [self displayDeEmphasized]!
  48170. displayDeEmphasized
  48171.     "Display this view with emphasis off.
  48172.     If windowBits is not nil, then simply BLT"
  48173.     bitsValid
  48174.         ifTrue:
  48175.         [self lock.
  48176.         windowBits displayAt: (self isCollapsed
  48177.             ifTrue: [self displayBox origin]
  48178.             ifFalse: [self displayBox origin - (0@labelFrame height)])]
  48179.         ifFalse:
  48180.         [super display.
  48181.         CacheBits ifTrue: [self cacheBitsAsIs]]
  48182. !
  48183. displayEmphasized
  48184.     "Display with label highlighted to indicate that it is active."
  48185.  
  48186.     self displayDeEmphasized; emphasize.
  48187.     isLabelComplemented _ true!
  48188. displayLabelBoxes
  48189.     "closeBox, growBox."
  48190.     | aRect smallRect backColor |
  48191.     aRect _ self closeBoxFrame.
  48192.     backColor _ self labelColor.
  48193.     Display fill: (aRect insetBy: -2) fillColor: backColor.
  48194.     Display fillBlack: aRect.
  48195.     Display fill: (aRect insetBy: 1) fillColor: backColor.
  48196.  
  48197.     aRect _ self growBoxFrame.
  48198.     smallRect _ aRect origin extent: 7@7.
  48199.     Display fill: (aRect insetBy: -2) fillColor: backColor.
  48200.     aRect _ aRect insetOriginBy: 2@2 cornerBy: 0@0.
  48201.     Display fillBlack: aRect.
  48202.     Display fill: (aRect insetBy: 1) fillColor: backColor.
  48203.     Display fillBlack: smallRect.
  48204.     Display fill: (smallRect insetBy: 1) fillColor: backColor!
  48205. displayLabelText
  48206.     "The label goes in the center of the window"
  48207.     labelText foregroundColor: self foregroundColor
  48208.             backgroundColor: self labelColor;
  48209.         displayOn: Display at: self labelTextRegion topLeft.
  48210. !
  48211. displayOn: aPort
  48212.     bitsValid ifFalse: [^ self].
  48213.     windowBits displayOnPort: aPort
  48214.         at: (self isCollapsed
  48215.             ifTrue: [self displayBox origin]
  48216.             ifFalse: [self displayBox origin - (0@labelFrame height)])!
  48217. displayRacingStripes
  48218.     "Display Racing Stripes in the label"
  48219.     | labelDisplayBox stripes top bottom left box right |
  48220.     labelDisplayBox _ self labelDisplayBox.
  48221.     top _ labelDisplayBox top + 3.
  48222.     bottom _ labelDisplayBox bottom - 3.
  48223.     stripes _ Array with: self labelColor
  48224.                     with: Form black.
  48225.     top even ifFalse: [stripes swap: 1 with: 2].
  48226.     stripes _ Pattern extent: 1@2 colors: stripes.
  48227.  
  48228.     left _ labelDisplayBox left + 3.
  48229.  
  48230.     box _ self closeBoxFrame.
  48231.     right _ box left - 2.
  48232.     Display fill: (Rectangle left: left right: right top: top bottom: bottom)
  48233.             fillColor: stripes.
  48234.     left _ box right + 2.
  48235.  
  48236.     box _ self labelTextRegion.
  48237.     right _ box left - 3.
  48238.     Display fill: (Rectangle left: left right: right top: top bottom: bottom)
  48239.             fillColor: stripes.
  48240.     left _ box right + 2.
  48241.  
  48242.     box _ self growBoxFrame.
  48243.     right _ box left - 2.
  48244.     Display fill: (Rectangle left: left right: right top: top bottom: bottom)
  48245.             fillColor: stripes.
  48246.     left _ box right + 2.
  48247.  
  48248.     right _ labelDisplayBox right - 3.
  48249.     Display fill: (Rectangle left: left right: right top: top bottom: bottom)
  48250.             fillColor: stripes.
  48251. !
  48252. displayView
  48253.     "Refer to the comment in View|displayView. "
  48254.     | label |
  48255.     self displayBox width = labelFrame width ifFalse:
  48256.         ["recompute label width when window changes size"
  48257.         self setLabelRegion].
  48258.     label _ labelFrame
  48259.             align: (self isCollapsed
  48260.                 ifTrue: [labelFrame topLeft]
  48261.                 ifFalse: [labelFrame bottomLeft])
  48262.             with: self displayBox topLeft.
  48263.     label insideColor: self labelColor;
  48264.         displayOn: Display.
  48265.     self displayLabelText!
  48266. erase
  48267.     "Clear the display box of the receiver to be gray, as the screen background."
  48268.     | oldValid |
  48269.     CacheBits
  48270.         ifTrue:
  48271.             [oldValid _ bitsValid.
  48272.             bitsValid _ false.
  48273.             ScheduledControllers restore: self windowBox without: self.
  48274.             bitsValid _ oldValid.]
  48275.         ifFalse:
  48276.             [self clear: Color gray.
  48277.             Display fillGray: self windowBox]!
  48278. uncacheBits
  48279.     windowBits _ nil.
  48280.     bitsValid _ false.! !
  48281.  
  48282. !StandardSystemView methodsFor: 'deEmphasizing'!
  48283. deEmphasizeView 
  48284.     "Refer to the comment in View|deEmphasizeView."
  48285.  
  48286.     self deEmphasizeLabel.
  48287.     isLabelComplemented _ false!
  48288. emphasizeView 
  48289.     "Refer to the comment in View|emphasizeView."
  48290.  
  48291.     self emphasizeLabel! !
  48292.  
  48293. !StandardSystemView methodsFor: 'clipping box access'!
  48294. clippingBox
  48295.     "Answer the rectangular area in which the receiver can show its label."
  48296.  
  48297.     ^self isTopView
  48298.         ifTrue: [self labelDisplayBox]
  48299.         ifFalse: [super insetDisplayBox]! !
  48300.  
  48301. !StandardSystemView methodsFor: 'private'!
  48302. setTransformation: aTransformation 
  48303.     "Override to support label size changes "
  48304.     super setTransformation: aTransformation.
  48305.     self label: self label! !
  48306. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  48307.  
  48308. StandardSystemView class
  48309.     instanceVariableNames: ''!
  48310.  
  48311. !StandardSystemView class methodsFor: 'class initialization'!
  48312. doCacheBits
  48313.     "StandardSystemView doCacheBits - Enable fast window repaint feature"
  48314.     CacheBits _ true.
  48315.     ScheduledControllers unCacheWindows.
  48316.     ScheduledControllers restore!
  48317. dontCacheBits
  48318.     "StandardSystemView dontCacheBits - Disable fast window repaint feature.
  48319.     Return true iff bits were cached, ie if space was been recovered"
  48320.     CacheBits ifFalse: [^ false].
  48321.     CacheBits _ false.
  48322.     ScheduledControllers unCacheWindows.
  48323.     ^ true!
  48324. initialize
  48325.     self dontCacheBits! !
  48326.  
  48327. StandardSystemView initialize!
  48328. Object subclass: #Stream
  48329.     instanceVariableNames: ''
  48330.     classVariableNames: ''
  48331.     poolDictionaries: ''
  48332.     category: 'Collections-Streams'!
  48333. Stream comment:
  48334. 'I am an abstract class that represents an accessor for a sequence of objects. This sequence is referred to as my "contents".'!
  48335.  
  48336. !Stream methodsFor: 'accessing'!
  48337. contents
  48338.     "Answer all of the contents of the receiver."
  48339.  
  48340.     self subclassResponsibility!
  48341. next
  48342.     "Answer the next object accessible by the receiver."
  48343.  
  48344.     self subclassResponsibility!
  48345. next: anInteger 
  48346.     "Answer the next anInteger number of objects accessible by the receiver."
  48347.  
  48348.     | aCollection |
  48349.     aCollection _ OrderedCollection new.
  48350.     anInteger timesRepeat: [aCollection addLast: self next].
  48351.     ^aCollection!
  48352. next: anInteger put: anObject 
  48353.     "Make anObject be the next anInteger number of objects accessible by the 
  48354.     receiver. Answer anObject."
  48355.  
  48356.     anInteger timesRepeat: [self nextPut: anObject].
  48357.     ^anObject!
  48358. nextMatchAll: aColl
  48359.     "Answer true if next N objects are the ones in aColl,
  48360.      else false.  Advance stream of true, leave as was if false."
  48361.     | save |
  48362.     save _ self position.
  48363.     aColl do: [:each |
  48364.        (self next) = each ifFalse: [
  48365.             self position: save.
  48366.             ^ false]
  48367.         ].
  48368.     ^ true!
  48369. nextMatchFor: anObject 
  48370.     "Gobble the next object and answer whether it is equal to the argument, 
  48371.     anObject."
  48372.  
  48373.     ^anObject = self next!
  48374. nextPut: anObject 
  48375.     "Insert the argument, anObject, as the next object accessible by the 
  48376.     receiver. Answer anObject."
  48377.  
  48378.     self subclassResponsibility!
  48379. nextPutAll: aCollection 
  48380.     "Append the elements of aCollection to the sequence of objects accessible 
  48381.     by the receiver. Answer aCollection."
  48382.  
  48383.     aCollection do: [:v | self nextPut: v].
  48384.     ^aCollection! !
  48385.  
  48386. !Stream methodsFor: 'testing'!
  48387. atEnd
  48388.     "Answer whether the receiver can access any more objects."
  48389.  
  48390.     self subclassResponsibility! !
  48391.  
  48392. !Stream methodsFor: 'enumerating'!
  48393. do: aBlock 
  48394.     "Evaluate aBlock for each of the objects accessible by receiver."
  48395.  
  48396.     [self atEnd]
  48397.         whileFalse: [aBlock value: self next]! !
  48398. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  48399.  
  48400. Stream class
  48401.     instanceVariableNames: ''!
  48402.  
  48403. !Stream class methodsFor: 'instance creation'!
  48404. new
  48405.  
  48406.     self error: 'Streams are created with on: and with:'! !Object subclass: #StrikeFont
  48407.     instanceVariableNames: 'xTable glyphs name stopConditions type minAscii maxAscii maxWidth strikeLength ascent descent xOffset raster subscript superscript emphasis '
  48408.     classVariableNames: ''
  48409.     poolDictionaries: 'TextConstants '
  48410.     category: 'Graphics-Support'!
  48411. StrikeFont comment:
  48412. 'I represent a compact encoding of a set of Forms corresponding to characters in the ASCII character set. All the forms are placed side by side in a large form whose height is the font height, and whose width is the sum of all the character widths. The xTable variable gives the left-x coordinates of the subforms corresponding to the characters.'!
  48413.  
  48414. !StrikeFont methodsFor: 'accessing'!
  48415. ascent
  48416.     "Answer the receiver's maximum extent of characters above the baseline."
  48417.  
  48418.     ^ascent!
  48419. characterFormAt: character 
  48420.     "Answer a Form copied out of the glyphs for the argument, character."
  48421.     | ascii leftX rightX characterForm |
  48422.     ascii _ character asciiValue.
  48423.     leftX _ xTable at: ascii + 1.
  48424.     rightX _ xTable at: ascii + 2.
  48425.     characterForm _ Form extent: (rightX-leftX) @ self height.
  48426.     characterForm copy: characterForm boundingBox
  48427.         from: leftX@0 in: glyphs rule: Form over.
  48428.     ^ characterForm!
  48429. characterFormAt: character put: characterForm
  48430.     "Copy characterForm over the glyph for the argument, character."
  48431.     | ascii leftX rightX widthDif newGlyphs |
  48432.     ascii _ character asciiValue.
  48433.     leftX _ xTable at: ascii + 1.
  48434.     rightX _ xTable at: ascii + 2.
  48435.     widthDif _ characterForm width - (rightX - leftX).
  48436.     widthDif ~= 0 ifTrue:
  48437.         ["Make new glyphs with more or less space for this char"
  48438.         newGlyphs _ Form extent: (glyphs width + widthDif) @ glyphs height.
  48439.         newGlyphs copy: (0@0 corner: leftX@glyphs height)
  48440.             from: 0@0 in: glyphs rule: Form over.
  48441.         newGlyphs copy: ((rightX+widthDif)@0 corner: newGlyphs width@glyphs height)
  48442.             from: rightX@0 in: glyphs rule: Form over.
  48443.         glyphs _ newGlyphs.
  48444.         "adjust further entries on xTable"
  48445.         ascii+2 to: xTable size
  48446.             do: [:i | xTable at: i put: (xTable at: i) + widthDif]].
  48447.     glyphs copy: (leftX @ 0 corner: rightX @ self height)
  48448.         from: 0@0 in: characterForm rule: Form over
  48449. "
  48450. | f |  f _ TextStyle default fontAt: 1.
  48451. f characterFormAt: $  put: (Form extent: (f widthOf: $ )+10@f height)
  48452. "!
  48453. descent
  48454.     "Answer the receiver's maximum extent of characters below the baseline."
  48455.  
  48456.     ^descent!
  48457. familySizeFace
  48458.     "Answer an array with familyName, a String, pointSize, an Integer, and
  48459.     faceCode, an Integer."
  48460.  
  48461.     | fontName firstDigit lastDigit |
  48462.     fontName_ name asUppercase.
  48463.     firstDigit _ fontName findFirst: [:char | char isDigit].
  48464.     lastDigit _ fontName findLast: [:char | char isDigit].
  48465.     ^Array with: (fontName copyFrom: 1 to: firstDigit-1)
  48466.         with: (Integer readFromString: (fontName copyFrom: firstDigit to: lastDigit))
  48467.         with: (#('' 'B' 'I' 'BI') indexOf:
  48468.                     (fontName copyFrom: lastDigit+1 to: fontName size))
  48469.  
  48470.     "(1 to: 12) collect: [:x | (TextStyle default fontAt: x) familySizeFace]"!
  48471. glyphs
  48472.     "Answer a Form containing the bits representing the characters of the 
  48473.     receiver."
  48474.  
  48475.     ^glyphs!
  48476. height
  48477.     "Answer the height of the receiver, total of maximum extents of 
  48478.     characters above and below the baseline."
  48479.  
  48480.     ^self ascent + self descent!
  48481. lineGrid
  48482.     ^ ascent + descent!
  48483. maxAscii
  48484.     "Answer the integer that is the last Ascii character value of the receiver."
  48485.  
  48486.     ^maxAscii!
  48487. maxWidth
  48488.     "Answer the integer that is the width of the receiver's widest character."
  48489.  
  48490.     ^maxWidth!
  48491. minAscii
  48492.     "Answer the integer that is the first Ascii character value of the receiver."
  48493.  
  48494.     ^minAscii!
  48495. name
  48496.     "Answer the receiver's name."
  48497.  
  48498.     ^name!
  48499. name: aString
  48500.     "Set the receiver's name."
  48501.  
  48502.     name _ aString!
  48503. raster
  48504.     "Answer an integer that specifies the layout of the glyphs' form."
  48505.  
  48506.     ^raster!
  48507. stopConditions
  48508.     "Answer the array of selectors to be performed in scanning text made up 
  48509.     of the receiver's characters."
  48510.  
  48511.     ^stopConditions!
  48512. subscript
  48513.     "Answer an integer that is the further vertical offset relative to the 
  48514.     baseline for positioning characters as subscripts."
  48515.  
  48516.     ^subscript!
  48517. superscript
  48518.     "Answer an integer that is the further vertical offset relative to the 
  48519.     baseline for positioning characters as superscripts."
  48520.  
  48521.     ^superscript!
  48522. widthOf: aCharacter 
  48523.     "Answer the width of the argument as a character in the receiver."
  48524.  
  48525.     | ascii |
  48526.     ascii _ (aCharacter asciiValue min: maxAscii + 1) max: minAscii.
  48527.     ^(xTable at: ascii + 2) - (xTable at: ascii + 1)!
  48528. xTable
  48529.     "Answer an Array of the left x-coordinate of characters in glyphs."
  48530.  
  48531.     ^xTable! !
  48532.  
  48533. !StrikeFont methodsFor: 'testing'!
  48534. checkCharacter: character 
  48535.     "Answer a Character that is within the ascii range of the receiver--either 
  48536.     character or the last character in the receiver."
  48537.  
  48538.     | ascii |  
  48539.     ascii _ character asciiValue.
  48540.     ((ascii < minAscii) or: [ascii > maxAscii])
  48541.             ifTrue: [^maxAscii asCharacter]
  48542.             ifFalse:    [^character]
  48543. ! !
  48544.  
  48545. !StrikeFont methodsFor: 'displaying'!
  48546. characters: anInterval in: sourceString displayAt: aPoint 
  48547.     clippedBy: clippingRectangle rule: ruleInteger fillColor: aForm     "Simple, slow, primitive method for displaying a line of characters.
  48548.     No wrap-around is provided."
  48549.     | ascii destPoint bb leftX rightX sourceRect |
  48550.     destPoint _ aPoint.
  48551.     bb _ BitBlt toForm: Display.
  48552.     anInterval do: 
  48553.         [:i | 
  48554.         ascii _ (sourceString at: i) asciiValue.
  48555.         (ascii < minAscii or: [ascii > maxAscii])
  48556.             ifTrue: [ascii _ maxAscii].
  48557.         leftX _ xTable at: ascii + 1.
  48558.         rightX _ xTable at: ascii + 2.
  48559.         sourceRect _ leftX@0 extent: (rightX-leftX) @ self height.
  48560.         bb copyFrom: sourceRect in: glyphs to: destPoint.
  48561.         destPoint _ destPoint + ((rightX-leftX)@0)].
  48562.     ^ destPoint!
  48563. composeWord: aTextLineInterval in: sourceString beginningAt: xInteger 
  48564.     "Non-primitive composition of a word--add up widths of characters, add 
  48565.     sum to beginning x and answer the resulting x. Similar to performance 
  48566.     of scanning primitive, but without stop conditions."
  48567.  
  48568.     | character resultX |
  48569.     resultX _ xInteger.
  48570.     aTextLineInterval do: 
  48571.         [:i | 
  48572.         character _ sourceString at: i.
  48573.         resultX _ resultX + (self widthOf: character)].
  48574.     ^resultX!
  48575. displayLine: aString at: aPoint 
  48576.     "Display the characters in aString, starting at position aPoint."
  48577.  
  48578.     self characters: (1 to: aString size)
  48579.         in: aString
  48580.         displayAt: aPoint
  48581.         clippedBy: Display boundingBox
  48582.         rule: Form over
  48583.         fillColor: nil! !
  48584.  
  48585. !StrikeFont methodsFor: 'emphasis'!
  48586. emphasis
  48587.     "Answer the integer code for synthetic bold, italic, underline, and 
  48588.     strike-out."
  48589.  
  48590.     ^emphasis!
  48591. emphasis: code 
  48592.     "Set the integer code for synthetic bold, itallic, underline, and strike-out, 
  48593.     where bold=1, italic=2, underlined=4, and struck out=8."
  48594.  
  48595.     emphasis _ code!
  48596. emphasized: code 
  48597.     "Answer a copy of the receiver with emphasis set to code."
  48598.     ^self copy emphasis: code + emphasis
  48599.  
  48600.     "TextStyle default fontAt: 9 put: ((TextStyle default fontAt: 1) emphasized: 4)"!
  48601. emphasized: code named: aString
  48602.     "Answer a copy of the receiver with emphasis set to code."
  48603.  
  48604.     | copy |
  48605.     copy _ self copy emphasis: (code + emphasis).
  48606.     copy name: aString.
  48607.     ^copy
  48608.  
  48609.     "TextStyle default fontAt: 9
  48610.         put: ((TextStyle default fontAt: 1) emphasized: 4 named: 'TimesRoman10i')"! !
  48611.  
  48612. !StrikeFont methodsFor: 'private'!
  48613. newFromStrike: fileName
  48614.     "Build an instance from the strike font file name. The '.strike' extension
  48615.     is optional."
  48616.  
  48617.     | strike startName |
  48618.     name _ fileName copyUpTo: $..    "assumes extension (if any) is '.strike'".
  48619.     strike _ FileStream oldFileNamed: name, '.strike.'.
  48620.     strike binary.
  48621.     strike readOnly.
  48622.         "strip off direcory name if any"
  48623.     startName _ name size.
  48624.     [startName > 0 and: [((name at: startName) ~= $>) & ((name at: startName) ~= $])]]
  48625.         whileTrue: [startName _ startName - 1].
  48626.     name _ name copyFrom: startName+1 to: name size.
  48627.  
  48628.     type            _        strike nextWord.        "type is ignored now -- simplest
  48629.                                                 assumed.  Kept here to make
  48630.                                                 writing and consistency more
  48631.                                                 straightforward."
  48632.     minAscii        _        strike nextWord.
  48633.     maxAscii        _        strike nextWord.
  48634.     maxWidth        _        strike nextWord.
  48635.     strikeLength    _        strike nextWord.
  48636.     ascent            _        strike nextWord.
  48637.     descent            _        strike nextWord.
  48638.     xOffset            _        strike nextWord.     
  48639.     raster            _        strike nextWord.    
  48640.     superscript        _        ascent - descent // 3.    
  48641.     subscript        _        descent - ascent // 3.    
  48642.     emphasis        _        0.
  48643. self halt.  "This needs to be fixed up..."
  48644.     glyphs            _
  48645.         Form new setExtent: (raster * 16) @ (self height)  
  48646.                    offset: 0@0
  48647.                    bits: ((Bitmap new: raster * self height) fromByteStream: strike).
  48648.  
  48649.     xTable _ (Array new: maxAscii + 3) atAllPut: 0.
  48650.     (minAscii + 1 to: maxAscii + 3) do:
  48651.         [:index | xTable at: index put: strike nextWord].
  48652.  
  48653.     "Set up space character"
  48654.     ((xTable at: (Space asciiValue + 2))  = 0 or:
  48655.             [(xTable at: (Space asciiValue + 2)) = (xTable at: (Space asciiValue + 1))])
  48656.         ifTrue:    [(Space asciiValue + 2) to: xTable size do:
  48657.                     [:index | xTable at: index put: ((xTable at: index) + DefaultSpace)]].
  48658.     strike close.
  48659.  
  48660.     "This has to do with scanning characters, not with the font"
  48661.     stopConditions _ Array new: 258.
  48662.     stopConditions atAllPut: nil.
  48663.     1 to: (minAscii - 1) do:
  48664.         [:index | stopConditions at: index put: #characterNotInFont].
  48665.     (maxAscii + 3) to: stopConditions size do:
  48666.         [:index | stopConditions at: index put: #characterNotInFont]! !
  48667.  
  48668. !StrikeFont methodsFor: 'Mac reader'!
  48669. aComment
  48670.     "To read Mac font resources.  
  48671. 1) Use ResEdit in the Fonts folder in the System Folder.  Open the file of the Font you want.  (A screen font, not a TrueType outline font).
  48672. 2) Open the FOND resource and scroll down to the list of sizes and resource numbers. Note the resource number of the size you want.
  48673. 3) Open the NFNT resource.  Click on the number you have noted.
  48674. 4) Choose 'Open Using Hex Editor' from the resource editor.
  48675. 5) Copy all of the hex numbers and paste into a text editor.  Save the file into the Smalltalk folder under the name 'FontName 12 hex' (or other size).
  48676. 6) Enter the fileName below and execute: 
  48677.  
  48678. TextStyle default fontAt: 8 put: (StrikeFont new readMacFontHex: 'fileName').
  48679.  
  48680. Select text and type Command-7 to change it to your new font.
  48681.  
  48682. (There is some problem in the ParagraphEditor with the large size of Cairo 18.  Its line heights are not the right.)
  48683.     "!
  48684. fixKerning: extraWidth
  48685.     "Insert one pixel (extraWidth) between each character.  And add the bits for the space character"
  48686.     "Create a space character Form.  Estimate width by ascent / 2 - 1"
  48687.     | characterForm char leftX |
  48688.     characterForm _ Form extent: (ascent//2 - 1) @ self height.
  48689.     self characterFormAt: $  put: characterForm.
  48690.  
  48691.     "Put one pixel of space after every character.  Mac fonts have no space in the bitmap."
  48692.     extraWidth <= 0 ifTrue: [^ self].
  48693.     minAscii to: maxAscii do: [:ascii |
  48694.         char _ Character value: ascii.
  48695.         leftX _ xTable at: ascii + 1.
  48696.         characterForm _ Form extent: 
  48697.             ((self widthOf: char) + extraWidth) @ self height.
  48698.         characterForm 
  48699.             copy: (characterForm boundingBox extendBy: 
  48700.                 (0-extraWidth@0))
  48701.             from: leftX@0 in: glyphs rule: Form over.
  48702.         self characterFormAt: char put: characterForm.
  48703.         ].    !
  48704. objectToStoreOnDataStream
  48705.     "HyperSqueak is about to write me out.  See if I am a system object.  Write out just a name if so.  See SqueakSupport class.aComment.  8/13/96 tk"
  48706.  
  48707.     "Path or real thing, depending"
  48708.     ^ Smalltalk hyperSqueakSupportClass sysRef: self!
  48709. readMacFontHex: fileName
  48710.     "Read the hex version of a Mac FONT type resource.  See the method aComment for how to prepare the input file. 4/26/96 tk"
  48711.     | file hh fRectWidth |
  48712.     name _ fileName.    "Palatino 12"
  48713.     file _ FileStream readOnlyFileNamed: fileName, ' hex'.
  48714.  
  48715.     "See Inside Macintosh page IV-42 for this record"
  48716.     "FontType _ " Number readFrom: (file next: 4) base: 16.
  48717.     emphasis        _        0.
  48718.     minAscii _ Number readFrom: (file next: 4) base: 16.
  48719.     maxAscii _ Number readFrom: (file next: 4) base: 16.
  48720.     maxWidth        _ Number readFrom: (file next: 4) base: 16.
  48721.     "kernMax _ " Number readFrom: (file next: 4) base: 16.
  48722.     "NDescent _ " Number readFrom: (file next: 4) base: 16.
  48723.     fRectWidth _  Number readFrom: (file next: 4) base: 16.
  48724.     hh _  Number readFrom: (file next: 4) base: 16.
  48725.     "OWTLoc _ " Number readFrom: (file next: 4) base: 16.
  48726.     ascent            _ Number readFrom: (file next: 4) base: 16.
  48727.     descent            _ Number readFrom: (file next: 4) base: 16.
  48728.     "leading _ " Number readFrom: (file next: 4) base: 16.
  48729.     xOffset            _        0.     
  48730.     raster            _ Number readFrom: (file next: 4) base: 16.
  48731.  
  48732.     strikeLength    _        raster*16.
  48733.     superscript        _        ascent - descent // 3.    
  48734.     subscript        _        descent - ascent // 3.    
  48735.     self strikeFromHex: file width: raster height: hh.
  48736.     self xTableFromHex: file.
  48737.     file close.
  48738.  
  48739.     "Insert one pixel between each character.  And add space character."
  48740.     self fixKerning: (fRectWidth - maxWidth).    
  48741.  
  48742.     "This has to do with scanning characters, not with the font"
  48743.     stopConditions _ Array new: 258.
  48744.     stopConditions atAllPut: nil.
  48745.     1 to: (minAscii - 1) do:
  48746.         [:index | stopConditions at: index put: #characterNotInFont].
  48747.     (maxAscii + 3) to: stopConditions size do:
  48748.         [:index | stopConditions at: index put: #characterNotInFont]!
  48749. strikeFromHex: file width: w height: h
  48750.     "read in just the raw strike bits from a hex file.  No spaces or returns.  W is in words (2 bytes), h in pixels." 
  48751.     | newForm theBits offsetX offsetY str num cnt |
  48752.     offsetX  _ 0.
  48753.     offsetY _ 0.
  48754.     offsetX > 32767 ifTrue: [offsetX _ offsetX - 65536]. "stored two's-complement"
  48755.     offsetY > 32767 ifTrue: [offsetY _ offsetY - 65536]. "stored two's-complement"
  48756.     newForm _ Form extent: strikeLength @ h offset: offsetX @ offsetY.
  48757.     theBits _ newForm bits.
  48758.     cnt _ 0.        "raster may be 16 bits, but theBits width is 32" 
  48759.     1 to: theBits size do: [:i | 
  48760.         (cnt _ cnt + 32) > strikeLength 
  48761.           ifTrue: [cnt _ 0.
  48762.             num _ Number readFrom: (str _ file next: 4) base: 16]
  48763.           ifFalse: [
  48764.             cnt = strikeLength ifTrue: [cnt _ 0].
  48765.             num _ Number readFrom: (str _ file next: 8) base: 16].
  48766.         theBits at: i put: num].
  48767.     glyphs _ newForm.!
  48768. xTableFromHex: file
  48769.  
  48770.     | strike num str wid |
  48771.     strike _ file.
  48772.     xTable _ (Array new: maxAscii + 3) atAllPut: 0.
  48773.     (minAscii + 1 to: maxAscii + 3) do:
  48774.         [:index | 
  48775.             num _ Number readFrom: (str _ strike next: 4) base: 16. 
  48776.             xTable at: index put: num].
  48777.  
  48778.     1 to: xTable size - 1 do: [:ind |
  48779.         wid _ (xTable at: ind+1) - (xTable at: ind).
  48780.         (wid < 0) | (wid > 40) ifTrue: [
  48781.             file close.
  48782.             self error: 'illegal character width']].
  48783. ! !
  48784. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  48785.  
  48786. StrikeFont class
  48787.     instanceVariableNames: ''!
  48788.  
  48789. !StrikeFont class methodsFor: 'instance creation'!
  48790. fromStrike: fileName 
  48791.     "Answer an instance of me determined by reading the file whose name is 
  48792.     fileName followed by '.strike'."
  48793.  
  48794.     ^self new newFromStrike: fileName! !
  48795.  
  48796. !StrikeFont class methodsFor: 'examples'!
  48797. example
  48798.     "Displays a line of text on the display screen at the location of the cursor.
  48799.     Example depends on the strike font file, 'TimesRoman10.strike'. existing."
  48800.  
  48801.     | font |
  48802.     font _ StrikeFont fromStrike: 'TimesRoman10'.
  48803.     font displayLine: 'A line of text in times roman style' at: Sensor cursorPoint
  48804.      
  48805.     "StrikeFont example."! !ArrayedCollection variableByteSubclass: #String
  48806.     instanceVariableNames: ''
  48807.     classVariableNames: 'StringBlter '
  48808.     poolDictionaries: ''
  48809.     category: 'Collections-Text'!
  48810. String comment:
  48811. 'I am an indexed collection of Characters. I really store 8-bit bytes, but my access protocol translates between these and real Character instances.'!
  48812.  
  48813. !String methodsFor: 'accessing'!
  48814. at: index 
  48815.     "Primitive. Answer the Character stored in the field of the receiver
  48816.     indexed by the argument. Fail if the index argument is not an Integer or
  48817.     is out of bounds. Essential. See Object documentation whatIsAPrimitive."
  48818.  
  48819.     <primitive: 63>
  48820.     ^Character value: (super at: index)!
  48821. at: index put: aCharacter 
  48822.     "Primitive. Store the Character in the field of the receiver indicated by
  48823.     the index. Fail if the index is not an Integer or is out of bounds, or if
  48824.     the argument is not a Character. Essential. See Object documentation
  48825.     whatIsAPrimitive."
  48826.  
  48827.     <primitive: 64>
  48828.     (aCharacter isKindOf: Character)
  48829.         ifTrue: [self errorNonIntegerIndex]
  48830.         ifFalse: [self error: 'Strings only store Characters']!
  48831. endsWithDigit
  48832.     "Answer whether the receiver's final character represents a digit.  3/11/96 sw"
  48833.  
  48834.     ^ self size > 0 and: [self last isDigit]!
  48835. findDelimiters: delimiters startingAt: start 
  48836.     "Answer the index of the character within the receiver, starting at start, that matches one of the delimiters. If the receiver does not contain any of the delimiters, answer size + 1."
  48837.  
  48838.     start to: self size do: [:i |
  48839.         delimiters do: [:delim | delim = (self at: i) ifTrue: [^ i]]].
  48840.     ^ self size + 1!
  48841. findString: subString startingAt: start 
  48842.     "Answer the index of subString within the receiver, starting at start. If 
  48843.     the receiver does not contain subString, answer 0."
  48844.  
  48845.     ^ self indexOfSubCollection: subString startingAt: start
  48846.         ifAbsent: [0]!
  48847. findTokens: delimiters
  48848.  
  48849.     "Answer the collection of tokens that result from parsing self.  The tokens are seperated by delimiters, any of a string of characters."
  48850.  
  48851.     | tokens keyStart keyStop |
  48852.  
  48853.     tokens _ OrderedCollection new.
  48854.     keyStop _ 1.
  48855.     [keyStop <= self size] whileTrue:
  48856.         [keyStart _ self skipDelimiters: delimiters startingAt: keyStop.
  48857.         keyStop _ self findDelimiters: delimiters startingAt: keyStart.
  48858.         keyStart < keyStop
  48859.             ifTrue: [tokens add: (self copyFrom: keyStart to: (keyStop - 1))]].
  48860.     ^tokens!
  48861. hasPrefix: subString
  48862.     "Answer the remainder of the receiver if subString is the beginning of the receiver. If the receiver does not start with subString, answer nil."
  48863.  
  48864.     | aCharacter index |
  48865.     subString size > self size ifTrue: [^ nil].
  48866.     aCharacter _ subString first.
  48867.     index _ 1.
  48868.     [(self at: index) = (subString at: index)] whileTrue:
  48869.                 [index = subString size ifTrue: [
  48870.                     ^ self copyFrom: index+1 to: self size].
  48871.                 index _ index+1].
  48872.     ^ nil !
  48873. lineCorrespondingToIndex: anIndex
  48874.     "Answer a string containing the line at the given character position.  1/15/96 sw:  Inefficient first stab at this"
  48875.  
  48876.     | cr aChar answer |
  48877.     cr _ Character cr.
  48878.     answer _ ''.
  48879.     1 to: self size do:
  48880.         [:i | 
  48881.             aChar _ self at: i.
  48882.             aChar == cr
  48883.                 ifTrue:
  48884.                     [i > anIndex
  48885.                         ifTrue:
  48886.                             [^ answer]
  48887.                         ifFalse:
  48888.                             [answer _ '']]
  48889.                 ifFalse:
  48890.                     [answer _ answer copyWith: aChar]].
  48891.     ^ answer!
  48892. lineCount
  48893.     "Answer the number of lines represented by the receiver, where every cr adds one line.  5/10/96 sw"
  48894.  
  48895.     | cr count |
  48896.     cr _ Character cr.
  48897.     count _ 1  min: self size..
  48898.     1 to: self size do:
  48899.         [:i | (self at: i) == cr ifTrue: [count _ count + 1]].
  48900.     ^ count
  48901.  
  48902. "
  48903. 'Fred
  48904. the
  48905. Bear' lineCount
  48906. "!
  48907. lineNumber: anIndex
  48908.     "Answer a string containing the characters in the given line number.  5/10/96 sw"
  48909.  
  48910.     | crString pos finalPos |
  48911.     crString _ String with: Character cr.
  48912.     pos _ 0.
  48913.     1 to: anIndex - 1 do:
  48914.         [:i | pos _ self findString: crString startingAt: pos + 1.
  48915.             pos == 0 ifTrue: [^ nil]].
  48916.     finalPos _ self findString: crString startingAt: pos + 1.
  48917.     finalPos == 0 ifTrue: [finalPos _ self size + 1].
  48918.     ^ self copyFrom: pos + 1 to: finalPos - 1
  48919.  
  48920. "
  48921. 'Fred
  48922. the
  48923. Bear' lineNumber: 3
  48924. "!
  48925. size
  48926.     "Primitive. Answer the number of indexable fields in the receiver. This
  48927.     value is the same as the largest legal subscript. Essential. See Object
  48928.     documentation whatIsAPrimitive."
  48929.  
  48930.     <primitive: 62>
  48931.     ^self basicSize!
  48932. skipDelimiters: delimiters startingAt: start 
  48933.     "Answer the index of the character within the receiver, starting at start, that matches one of the delimiters. If the receiver does not contain any of the delimiters, answer size + 1.  Assumes the delimiters to be a non-empty string."
  48934.  
  48935.     start to: self size do: [:i |
  48936.         delimiters detect: [:delim | delim = (self at: i)]
  48937.                 ifNone: [^ i]].
  48938.     ^ self size + 1!
  48939. string
  48940.     "Answer the receiver itself. This is for compatibility with other textual 
  48941.     classes."
  48942.  
  48943.     ^self! !
  48944.  
  48945. !String methodsFor: 'comparing'!
  48946. < aString 
  48947.     "Answer whether the receiver collates before aString. The collation 
  48948.     sequence is ascii with case differences ignored."
  48949.  
  48950.     ^(self compare: aString) = 1!
  48951. <= aString 
  48952.     "Answer whether the receiver collates before aString or is the same as 
  48953.     aString. The collation sequence is ascii with case differences ignored."
  48954.  
  48955.     ^(self compare: aString) <= 2!
  48956. > aString 
  48957.     "Answer whether the receiver collates after aString. The collation 
  48958.     sequence is ascii with case differences ignored."
  48959.  
  48960.     ^(self compare: aString) = 3!
  48961. >= aString 
  48962.     "Answer whether the receiver collates after aString or is the same as 
  48963.     aString. The collation sequence is ascii with case differences ignored."
  48964.  
  48965.     ^(self compare: aString) >= 2!
  48966. alike: aString 
  48967.     "Answer some indication of how alike the receiver is to the argument,  0 is no match, twice aString size is best score.  Case is ignored."
  48968.  
  48969.     | i j k minSize bonus |
  48970.     minSize _ (j _ self size) min: (k _ aString size).
  48971.     bonus _ (j - k) abs < 2 ifTrue: [ 1 ] ifFalse: [ 0 ].
  48972.     i _ 1.
  48973.     [(i <= minSize) and: [((super at: i) bitAnd: 16rDF)  = ((aString at: i) asciiValue bitAnd: 16rDF)]]
  48974.         whileTrue: [ i _ i + 1 ].
  48975.     [(j > 0) and: [(k > 0) and:
  48976.         [((super at: j) bitAnd: 16rDF) = ((aString at: k) asciiValue bitAnd: 16rDF)]]]
  48977.             whileTrue: [ j _ j - 1.  k _ k - 1. ].
  48978.     ^ i - 1 + self size - j + bonus. !
  48979. charactersExactlyMatching: aString
  48980.     "Do a character-by-character comparison between the receiver and aString; return the index of the final character that matched exactly.  4/29/96 sw"
  48981.  
  48982.     | count |
  48983.     count _ self size min: aString size.
  48984.     count == 0 ifTrue: [^ 0].
  48985.     1 to: count do:
  48986.         [:i | (self at: i) == (aString at: i) ifFalse: [^ i - 1]] .
  48987.     ^ count!
  48988. endsWith: aString
  48989.     "Answer whether the tail end of the receiver is the same as aString.  Case-sensitive.  1/26/96 sw"
  48990.     | mySize |
  48991.     (mySize _ self size) < aString size ifTrue: [^ false].
  48992.     ^ (self copyFrom: (mySize - aString size + 1) to: mySize) = aString
  48993.  
  48994. "  'Elvis' endsWith: 'vis'"!
  48995. hash
  48996.  
  48997.     | l m |
  48998.     (l _ m _ self size) <= 2
  48999.       ifTrue:
  49000.         [l = 2
  49001.           ifTrue: [m _ 3]
  49002.           ifFalse:
  49003.             [l = 1
  49004.               ifTrue: [^((self at: 1) asciiValue bitAnd: 127) * 106].
  49005.             ^21845]].
  49006.     ^(self at: 1) asciiValue * 48 + ((self at: (m - 1)) asciiValue + l)!
  49007. hashMappedBy: map
  49008.     "My hash is independent of my oop."
  49009.  
  49010.     ^self hash!
  49011. match: text 
  49012.     "Answer whether text matches the pattern in the receiver. Matching 
  49013.     ignores upper/lower case differences. Where the receiver contains #, 
  49014.     text may contain any single character. Where the receiver contains *, 
  49015.     text may contain any sequence of characters."
  49016.  
  49017.     | pattern scanning p t back textStream startScan |
  49018.     pattern _ ReadStream on: self.
  49019.     textStream _ ReadStream on: text.
  49020.     scanning _ false.
  49021.     [pattern atEnd]
  49022.         whileFalse: 
  49023.             [p _ pattern next.
  49024.             p = $*
  49025.                 ifTrue: 
  49026.                     [pattern atEnd ifTrue: [^true].
  49027.                     scanning _ true.
  49028.                     startScan _ pattern position]
  49029.                 ifFalse: 
  49030.                     [textStream atEnd ifTrue: [^false].
  49031.                     t _ textStream next.
  49032.                     (t asUppercase = p asUppercase or: [p = $#])
  49033.                         ifFalse: 
  49034.                             [scanning ifFalse: [^false].
  49035.                             back _ startScan - pattern position.
  49036.                             pattern skip: back.
  49037.                             textStream skip: back + 1]].
  49038.             (scanning and: [pattern atEnd and: [textStream atEnd not]])
  49039.                 ifTrue: [back _ startScan - pattern position.
  49040.                         pattern skip: back.
  49041.                         textStream skip: back + 1]
  49042.             ].
  49043.     ^textStream atEnd
  49044.  
  49045.     " Examples: 
  49046.  
  49047.     'xyz' match: 'Xyz'  true
  49048.     'x#z' match: 'x@z' true 
  49049.     'x*z' match: 'x whyNot? z' true
  49050.     '*x' match: 'xx' true
  49051.     "!
  49052. prefixEqual: prefix | prefixSize |
  49053.     "Answer whether the receiver begins with the given prefix string."
  49054.  
  49055.     prefixSize _ prefix size.
  49056.  
  49057.     self size < prefixSize ifTrue: [^false].
  49058.     1 to: prefixSize do:
  49059.         [:index | (self at: index) = (prefix at: index) ifFalse: [^false]].
  49060.     ^true!
  49061. sameAs: aString 
  49062.     "Answer whether the receiver collates precisely with aString. The 
  49063.     collation sequence is ascii with case differences ignored."
  49064.  
  49065.     ^(self compare: aString) = 2! !
  49066.  
  49067. !String methodsFor: 'copying'!
  49068. copyReplaceTokens: oldSubstring with: newSubstring 
  49069.     "Replace all occurrences of oldSubstring that are surrounded
  49070.     by non-alphanumeric characters"
  49071.     ^ self copyReplaceAll: oldSubstring with: newSubstring asTokens: true
  49072.     "'File asFile Files File''s File' copyReplaceTokens: 'File' with: 'Snick'"!
  49073. copyUpTo: aCharacter 
  49074.     "Answer a copy of the receiver from index 1 to the first occurrence of 
  49075.     aCharacter, not including aCharacter."
  49076.  
  49077.     | index |
  49078.     index _ self indexOf: aCharacter ifAbsent: [^self].
  49079.     ^self copyFrom: 1 to: index-1!
  49080. deepCopy
  49081.     "DeepCopy would otherwise mean make a copy of the character;  since 
  49082.     characters are unique, just return a shallowCopy."
  49083.  
  49084.     ^self shallowCopy!
  49085. forRom
  49086.     "A 'primitive type' for Toolbox calls, if in range"
  49087.  
  49088.     self size > 255 ifTrue: [^nil]! !
  49089.  
  49090. !String methodsFor: 'converting'!
  49091. asByteArray
  49092.     "Convert to a ByteArray with the ascii values of the string"
  49093.     | array |
  49094.     array _ ByteArray new: self size.
  49095.     1 to: array size do: [:index |
  49096.         array at: index put: (self at: index) asciiValue].
  49097.     ^ array!
  49098. asDisplayText
  49099.     "Answer a DisplayText whose text string is the receiver."
  49100.  
  49101.     ^DisplayText text: self asText!
  49102. asFileName
  49103.     "Answer a String made up from the receiver that is an acceptable file 
  49104.     name."
  49105.  
  49106.     ^FileDirectory checkName: self fixErrors: true!
  49107. asHtml
  49108.     "Do the basic character conversion for HTML.  Leave all original return and tabs in place, so can conver back by simply removing bracked things.
  49109.     4/4/96 tk"
  49110.     | temp |
  49111.     temp _ self copyReplaceAll: '&' with: '&'.
  49112.     temp _ temp copyReplaceAll: '<' with: '<'.
  49113.     temp _ temp copyReplaceAll: '>' with: '>'.
  49114.  
  49115.     temp _ temp copyReplaceAll: '    ' 
  49116.             with: '    <IMG SRC="tab.gif" ALT="    ">'.
  49117.     temp _ temp copyReplaceAll: '
  49118.             with: '
  49119. <BR>'.
  49120.     ^ temp!
  49121. asLowercase
  49122.     "Answer a String made up from the receiver whose characters are all 
  49123.     lowercase."
  49124.  
  49125.     | aStream |
  49126.     aStream _ WriteStream on: (String new: self size).
  49127.     self do: [:aCharacter | aStream nextPut: aCharacter asLowercase].
  49128.     ^aStream contents!
  49129. asNumber 
  49130.     "Answer the Number created by interpreting the receiver as the string 
  49131.     representation of a number."
  49132.  
  49133.     ^Number readFromString: self!
  49134. asPacked
  49135.     "Convert to a longinteger that describes the string"
  49136.     ^ self inject: 0 into: [ :pack :next | pack _ pack * 256 + next asInteger ].!
  49137. asParagraph
  49138.     "Answer a Paragraph whose text string is the receiver."
  49139.  
  49140.     ^Paragraph withText: self asText!
  49141. asString
  49142.     "Answer the receiver itself."
  49143.  
  49144.     ^self!
  49145. asSymbol
  49146.     "Answer the unique Symbol whose characters are the characters of the 
  49147.     string."
  49148.  
  49149.     ^Symbol intern: self!
  49150. asText
  49151.     "Answer a Text whose string is the receiver."
  49152.  
  49153.     ^Text fromString: self!
  49154. asUnHtml
  49155.     "Strip out all Html stuff (commands in angle brackets <>) and convert the characters &<> back to their real value.  Leave actual cr and tab as they were in text.  4/12/96 tk"
  49156.     | in out char rest did |
  49157.     in _ ReadStream on: self.
  49158.     out _ WriteStream on: (String new: self size).
  49159.     [in atEnd] whileFalse: [
  49160.         in peek = $< ifTrue: [in unCommand].    "Absorb <...><...>"
  49161.         (char _ in next) = $&
  49162.             ifTrue: [
  49163.                 rest _ in upTo: $;.
  49164.                 did _ out position.
  49165.                 rest = 'lt' ifTrue: [out nextPut: $<].
  49166.                 rest = 'gt' ifTrue: [out nextPut: $>].
  49167.                 rest = 'amp' ifTrue: [out nextPut: $&].
  49168.                 did = out position ifTrue: [
  49169.                     self error: 'new HTML char encoding'.
  49170.                     "Please add it to this code"]]
  49171.             ifFalse: [out nextPut: char].
  49172.         ].
  49173.     ^ out contents!
  49174. asUppercase
  49175.     "Answer a String made up from the receiver whose characters are all 
  49176.     uppercase."
  49177.  
  49178.     | aStream |
  49179.     aStream _ WriteStream on: (String new: self size).
  49180.     self do: [:aCharacter | aStream nextPut: aCharacter asUppercase].
  49181.     ^aStream contents!
  49182. backwards
  49183.     "Answer the characters of the receiver in reversed order.  1/18/96 sw"
  49184.     | aStream |
  49185.     aStream _ ReadWriteStream on: ''.
  49186.     self size to: 1 by: -1 do:
  49187.         [:i | aStream nextPut: (self at: i)].
  49188.     ^ aStream contents
  49189.  
  49190. "'frog' backwards"!
  49191. compressWithTable: tokens
  49192.     "Return a string with all substrings that occur in tokens replaced
  49193.     by a character with ascii code = 127 + token index.
  49194.     This will work best if tokens are sorted by size.
  49195.     Assumes this string contains no characters > 127, or that they
  49196.     are intentionally there and will not interfere with this process."
  49197.     | str null finalSize start result ri c ts |
  49198.     null _ Character value: 0.
  49199.     str _ self copyFrom: 1 to: self size.  "Working string will get altered"
  49200.     finalSize _ str size.
  49201.     tokens doWithIndex:
  49202.         [:token :tIndex |
  49203.         start _ 1.
  49204.         [(start _ str findString: token startingAt: start) > 0]
  49205.             whileTrue:
  49206.             [ts _ token size.
  49207.             ((start + ts) <= str size
  49208.                 and: [(str at: start + ts) = $  and: [tIndex*2 <= 128]])
  49209.                 ifTrue: [ts _ token size + 1.  "include training blank"
  49210.                         str at: start put: (Character value: tIndex*2 + 127)]
  49211.                 ifFalse: [str at: start put: (Character value: tIndex + 127)].
  49212.             str at: start put: (Character value: tIndex + 127).
  49213.             1 to: ts-1 do: [:i | str at: start+i put: null].
  49214.             finalSize _ finalSize - (ts - 1).
  49215.             start _ start + ts]].
  49216.     result _ String new: finalSize.
  49217.     ri _ 0.
  49218.     1 to: str size do:
  49219.         [:i | (c _ str at: i) = null ifFalse: [result at: (ri _ ri+1) put: c]].
  49220.     ^ result!
  49221. contractTo: smallSize
  49222.     "return myself or a copy shortened by ellipsis to smallSize"
  49223.     | leftSize |
  49224.     self size <= smallSize
  49225.         ifTrue: [^ self].  "short enough"
  49226.     smallSize < 5
  49227.         ifTrue: [^ self copyFrom: 1 to: smallSize].    "First N characters"
  49228.     leftSize _ smallSize-2//2.
  49229.     ^ self copyReplaceFrom: leftSize+1        "First N/2 ... last N/2"
  49230.         to: self size - (smallSize - leftSize - 3)
  49231.         with: '...'!
  49232. correctAgainst: wordList
  49233.     "Correct the receiver: assume it is a misspelled word and return the (maximum of five) nearest words in the wordList.  Depends on the scoring scheme of alike:"
  49234.     | results |
  49235.     results _ self correctAgainst: wordList continuedFrom: nil.
  49236.     results _ self correctAgainst: nil continuedFrom: results.
  49237.     ^ results!
  49238. correctAgainst: wordList continuedFrom: oldCollection
  49239.     "Like correctAgainst:.  Use when you want to correct against several lists, give nil as the first oldCollection, and nil as the last wordList."
  49240.  
  49241.     ^ wordList isNil
  49242.         ifTrue: [ self correctAgainstEnumerator: nil
  49243.                     continuedFrom: oldCollection ]
  49244.         ifFalse: [ self correctAgainstEnumerator: [ :action | wordList do: action ]
  49245.                     continuedFrom: oldCollection ]!
  49246. correctAgainstDictionary: wordDict continuedFrom: oldCollection
  49247.     "Like correctAgainst:continuedFrom:.  Use when you want to correct against a dictionary."
  49248.  
  49249.     ^ wordDict isNil
  49250.         ifTrue: [ self correctAgainstEnumerator: nil
  49251.                     continuedFrom: oldCollection ]
  49252.         ifFalse: [ self correctAgainstEnumerator: [ :action | wordDict keysDo: action ]
  49253.                     continuedFrom: oldCollection ]!
  49254. keywords
  49255.     "Answer an array of the keywords that compose the receiver."
  49256.     | result aStream char |
  49257.     result _ WriteStream on: (Array new: 10).
  49258.     aStream _ WriteStream on: (String new: 16).
  49259.     1 to: self size do:
  49260.         [:i |
  49261.         aStream nextPut: (char _ self at: i).
  49262.         char = $: ifTrue: 
  49263.                 [result nextPut: aStream contents.
  49264.                 aStream reset]].
  49265.     aStream isEmpty ifFalse: [result nextPut: aStream contents].
  49266.     ^ result contents!
  49267. sansPeriodSuffix
  49268.     "Return a copy of the receiver up to, but not including, the first period.  If the receiver's *first* character is a period, then just return the entire receiver. "
  49269.  
  49270.     | likely |
  49271.     likely _ self copyUpTo: $..
  49272.     ^ likely size == 0
  49273.         ifTrue:    [self]
  49274.         ifFalse:    [likely]!
  49275. stemAndNumericSuffix
  49276.     "Parse the receiver into a string-valued stem and a numeric-valued suffix.  6/7/96 sw"
  49277.  
  49278.     | stem suffix position |
  49279.  
  49280.     stem _ self.
  49281.     suffix _ 0.
  49282.     position _ 1.
  49283.     [stem endsWithDigit and: [stem size > 1]] whileTrue:
  49284.         [suffix _  stem last digitValue * position + suffix.
  49285.         position _ position * 10.
  49286.         stem _ stem copyFrom: 1 to: stem size - 1].
  49287.     ^ Array with: stem with: suffix
  49288.  
  49289. "'Fred2305' stemAndNumericSuffix"!
  49290. truncateTo: smallSize
  49291.     "return myself or a copy shortened to smallSize.  1/18/96 sw"
  49292.  
  49293.     ^ self size <= smallSize
  49294.         ifTrue:
  49295.             [self]
  49296.         ifFalse:
  49297.             [self copyFrom: 1 to: smallSize]!
  49298. withBlanksTrimmed
  49299.     "Return a copy of the receiver from which leading and trailing blanks have been trimmed.   This is a quick-and-dirty, sledge-hammer implementation; improvements welcomed.  1/18/96 sw"
  49300.  
  49301.     | firstNonBlank lastNonBlank |
  49302.  
  49303.     firstNonBlank _ 1.
  49304.     [firstNonBlank < self size and: [(self at: firstNonBlank) isSeparator]] whileTrue:
  49305.         [firstNonBlank _ firstNonBlank + 1].
  49306.     
  49307.     lastNonBlank _ self size.
  49308.     [lastNonBlank > 0 and: [(self at: lastNonBlank) isSeparator]] whileTrue:
  49309.         [lastNonBlank _ lastNonBlank - 1].
  49310.     ^ lastNonBlank < firstNonBlank
  49311.         ifTrue:
  49312.             ['']
  49313.         ifFalse:
  49314.             [self copyFrom: firstNonBlank to: lastNonBlank]
  49315.  
  49316. "  ' abc  d   ' withBlanksTrimmed"! !
  49317.  
  49318. !String methodsFor: 'displaying'!
  49319. displayAt: aPoint 
  49320.     "Show a representation of the receiver as a DisplayText at location aPoint 
  49321.     on the display screen."
  49322.  
  49323.     self asDisplayText displayAt: aPoint!
  49324. displayOn: aDisplayMedium
  49325.     "Display the receiver on the given DisplayMedium.  5/16/96 sw"
  49326.  
  49327.     self displayOn: aDisplayMedium at: 0 @ 0!
  49328. displayOn: aDisplayMedium at: aPoint 
  49329.     "Show a representation of the receiver as a DisplayText at location
  49330.     aPoint on aDisplayMedium."
  49331.  
  49332.     self asDisplayText displayOn: aDisplayMedium at: aPoint!
  49333. displayOnScreen
  49334.     "For debugging. 2/14/96 sw"
  49335.     "'Fred the  Bear' displayOnScreen"
  49336.  
  49337.     self displayAt: Utilities directTextToScreenPoint!
  49338. displayProgressAt: aPoint from: minVal to: maxVal during: workBlock 
  49339.     "Display this string as a caption over a progress bar while workBlock is evaluated.
  49340.  
  49341. EXAMPLE (Select next 6 lines and Do It)
  49342. 'Now here''s some Real Progress'
  49343.     displayProgressAt: Sensor cursorPoint
  49344.     from: 0 to: 10
  49345.     during: [:bar |
  49346.     1 to: 10 do: [:x | bar value: x.
  49347.             (Delay forMilliseconds: 500) wait]].
  49348.  
  49349. HOW IT WORKS (Try this in any other language :-)
  49350. Since your code (the last 2 lines in the above example) is in a block,
  49351. this method gets control to display its heading before, and clean up 
  49352. the screen after, its execution.
  49353. The key, though, is that the block is supplied with an argument,
  49354. named 'bar' in the example, which will update the bar image every 
  49355. it is sent the message value: x, where x is in the from:to: range.
  49356. "
  49357.     | delta savedArea captionText textFrame barFrame outerFrame |
  49358.     barFrame _ aPoint - (75@10) corner: aPoint + (75@10).
  49359.     captionText _ DisplayText text: self asText allBold.
  49360.     textFrame _ captionText boundingBox insetBy: -4.
  49361.     textFrame _ textFrame align: textFrame bottomCenter
  49362.                     with: barFrame topCenter + (0@2).
  49363.     outerFrame _ barFrame merge: textFrame.
  49364.     delta _ outerFrame amountToTranslateWithin: Display boundingBox.
  49365.     barFrame moveBy: delta.  textFrame moveBy: delta.  outerFrame moveBy: delta.
  49366.     savedArea _ Form fromDisplay: outerFrame.
  49367.     Display fillBlack: barFrame; fillWhite: (barFrame insetBy: 2).
  49368.     Display fillBlack: textFrame; fillWhite: (textFrame insetBy: 2).
  49369.     captionText displayOn: Display at: textFrame topLeft + (4@4).
  49370.     workBlock value:  "Supply the bar-update block for evaluation in the work block"
  49371.         [:barVal | Display fillGray: (barFrame topLeft + (2@2) extent:
  49372.                     ((barFrame width-4) * (barVal-minVal) /(maxVal - minVal)@16))].
  49373.     savedArea displayOn: Display at: outerFrame topLeft.
  49374. ! !
  49375.  
  49376. !String methodsFor: 'printing'!
  49377. isLiteral
  49378.  
  49379.     ^true!
  49380. printOn: aStream 
  49381.     "Print inside string quotes, doubling inbedded quotes."
  49382.  
  49383.     ^self storeOn: aStream!
  49384. storeOn: aStream 
  49385.     "Print inside string quotes, doubling inbedded quotes."
  49386.     | x |
  49387.     aStream nextPut: $'.
  49388.     1 to: self size do:
  49389.         [:i |
  49390.         aStream nextPut: (x _ self at: i).
  49391.         x == $' ifTrue: [aStream nextPut: x]].
  49392.     aStream nextPut: $'!
  49393. stringRepresentation
  49394.     "Answer a string that represents the receiver.  For most objects this is simply its printString, but for strings themselves, it's themselves, to avoid the superfluous extra pair of quotes.  6/12/96 sw"
  49395.  
  49396.     ^ self ! !
  49397.  
  49398. !String methodsFor: 'private'!
  49399. compare: s 
  49400.     | len endResult u1 u2 mylen |
  49401.     mylen _ self size.
  49402.     len _ s size.
  49403.     mylen < len
  49404.         ifTrue: 
  49405.             [len _ mylen.
  49406.             endResult _ 1]
  49407.         ifFalse: [endResult _ mylen = len
  49408.                         ifTrue: [2]
  49409.                         ifFalse: [3]].
  49410.     1 to: len do:
  49411.         [:i |
  49412.         u1 _ self at: i.
  49413.         u2 _ s at: i.
  49414.         u1 = u2 ifFalse: 
  49415.             [u1 _ u1 asUppercase.
  49416.             u2 _ u2 asUppercase.
  49417.             u1 = u2 ifFalse:
  49418.                 [^ u1 < u2
  49419.                     ifTrue: [1]
  49420.                     ifFalse: [3]]]].
  49421.     ^ endResult!
  49422. correctAgainstEnumerator: wordBlock continuedFrom: oldCollection
  49423.     "The guts of correction, instead of a wordList, there is a block that should take abnother block and enumerate over some list with it."
  49424.  
  49425.     | choices scoreMin results score |
  49426.     scoreMin _ self size // 2 min: 3.
  49427.     oldCollection isNil
  49428.         ifTrue: [ choices _ SortedCollection sortBlock: [ :x :y | x value > y value ] ]
  49429.         ifFalse: [ choices _ oldCollection ].
  49430.     wordBlock isNil
  49431.         ifFalse:
  49432.             [ wordBlock value: [ :word |
  49433.                 (score _ self alike: word) >= scoreMin ifTrue:
  49434.                     [ choices add: (Association key: word value: score).
  49435.                         (choices size >= 5) ifTrue: [ scoreMin _ (choices at: 5) value] ] ].
  49436.             results _ choices ]
  49437.         ifTrue:
  49438.             [ results _ OrderedCollection new.
  49439.             1 to: (5 min: choices size) do: [ :i | results add: (choices at: i) key ] ].
  49440.     ^ results!
  49441. replaceFrom: start to: stop with: replacement startingAt: repStart 
  49442.     "Primitive. This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the collection, replacement. Answer the receiver. Range checks are performed in the primitive only. Optional. See Object documentation whatIsAPrimitive."
  49443.     <primitive: 105>
  49444.     super replaceFrom: start to: stop with: replacement startingAt: repStart!
  49445. stringhash
  49446.     ^self hash! !
  49447.  
  49448. !String methodsFor: 'system primitives'!
  49449. numArgs
  49450.     "Answer either the number of arguments that the receiver would take if considered a selector.  Answer -1 if it couldn't be a selector.  Note that currently this will answer -1 for anything begining with an uppercase letter even though the system will accept such symbols as selectors.  It is intended mostly for the assistance of spelling correction."
  49451.  
  49452.     | firstChar numColons |
  49453.     firstChar _ self at: 1.
  49454.     firstChar isLetter ifTrue:
  49455.         [ firstChar isUppercase ifTrue: [ ^ -1 ].
  49456.         numColons _ 0. 
  49457.         self do: [ :ch |
  49458.             ch tokenish ifFalse: [ ^ -1 ].
  49459.             (ch = $:) ifTrue: [numColons _ numColons + 1] ].
  49460.         ^ (self last = $:)
  49461.             ifTrue: [ numColons > 0 ifTrue: [ numColons ] ifFalse: [ -1 ] ]
  49462.             ifFalse: [ numColons > 0 ifTrue: [ -1 ] ifFalse: [ 0 ] ] ].
  49463.     firstChar isSpecial ifTrue:
  49464.         [self size = 1 ifTrue: [^ 1].
  49465.         self size > 2 ifTrue: [^ -1].
  49466.         ^ (self at: 2) isSpecial ifTrue: [1] ifFalse: [-1]].
  49467.     self = #- ifTrue: [ ^ 1 ].
  49468.     ^ -1.! !
  49469. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  49470.  
  49471. String class
  49472.     instanceVariableNames: ''!
  49473.  
  49474. !String class methodsFor: 'instance creation'!
  49475. fromPacked: aLong
  49476.     "Convert from a longinteger to a String of length 4."
  49477.  
  49478.     | s |
  49479.     s _ self new: 4.
  49480.     s at: 1 put: (aLong digitAt: 4) asCharacter.
  49481.     s at: 2 put: (aLong digitAt: 3) asCharacter.
  49482.     s at: 3 put: (aLong digitAt: 2) asCharacter.
  49483.     s at: 4 put: (aLong digitAt: 1) asCharacter.
  49484.     ^s
  49485.  
  49486. "String fromPacked: 'TEXT' asPacked"
  49487. !
  49488. fromString: aString 
  49489.     "Answer an instance of me that is a copy of the argument, aString."
  49490.     
  49491.     | newString |
  49492.     newString _ self new: aString size.
  49493.     aString size do: [:i | newString at: i put: (aString at: i)].
  49494.     ^newString!
  49495. readFrom: inStream
  49496.     "Answer an instance of me that is determined by reading the stream, 
  49497.     inStream. Embedded double quotes become the quote Character."
  49498.  
  49499.     | outStream char done |
  49500.     outStream _ WriteStream on: (String new: 16).
  49501.     "go to first quote"
  49502.     inStream skipTo: $'.
  49503.     done _ false.
  49504.     [done or: [inStream atEnd]]
  49505.         whileFalse: 
  49506.             [char _ inStream next.
  49507.             char = $'
  49508.                 ifTrue: 
  49509.                     [char _ inStream next.
  49510.                     char = $'
  49511.                         ifTrue: [outStream nextPut: char]
  49512.                         ifFalse: [done _ true]]
  49513.                 ifFalse: [outStream nextPut: char]].
  49514.     ^outStream contents! !
  49515.  
  49516. !String class methodsFor: 'examples'!
  49517. example
  49518.     "To see the string displayed at the cursor point, execute this expression
  49519.     and select a point by pressing a mouse button."
  49520.  
  49521.     'this is some text' displayOn: Display at: Sensor waitButton! !Model subclass: #StringHolder
  49522.     instanceVariableNames: 'contents isLocked '
  49523.     classVariableNames: 'Workspace '
  49524.     poolDictionaries: ''
  49525.     category: 'Interface-Support'!
  49526. StringHolder comment:
  49527. 'I represent a layer of structure in order to view an aspect of a model that includes a string as part of its information.'!
  49528.  
  49529. !StringHolder methodsFor: 'initialize-release'!
  49530. defaultBackgroundColor
  49531.     ^ #lightYellow!
  49532. initialize
  49533.     "Initialize the state of the receiver to be unlocked with default contents 
  49534.     (empty string)."
  49535.  
  49536.     isLocked _ false.
  49537.     contents _ self defaultContents! !
  49538.  
  49539. !StringHolder methodsFor: 'accessing'!
  49540. contents
  49541.     "Answer the contents that the receiver is holding--presumably a string."
  49542.  
  49543.     ^contents!
  49544. contents: aString 
  49545.     "Set aString to be the contents of the receiver."
  49546.  
  49547.     contents _ aString! !
  49548.  
  49549. !StringHolder methodsFor: 'code'!
  49550. doItContext
  49551.     "Answer the context in which a text selection can be evaluated."
  49552.  
  49553.     ^nil!
  49554. doItReceiver
  49555.     "Answer the object that should be informed of the result of evaluating a 
  49556.     text selection."
  49557.  
  49558.     ^nil! !
  49559.  
  49560. !StringHolder methodsFor: 'lock access'!
  49561. hasBeenChanged
  49562.     "Answer whether the receiver, serving as a model for some window, has been changed, and hence should not be blithely discarded without warning.  2/5/96 sw"
  49563.  
  49564.     ^ self isUnlocked not!
  49565. isLocked
  49566.     "Answer whether the receiver is locked, that is, has the contents of the 
  49567.     receiver been modified since the last time it was unlocked."
  49568.  
  49569.     ^isLocked!
  49570. isUnlocked
  49571.     "Answer whether the receiver is unlocked."
  49572.  
  49573.     ^isLocked not!
  49574. lock
  49575.     "Note that the receiver has been modified."
  49576.  
  49577.     isLocked _ true!
  49578. okToChange
  49579.     self isUnlocked ifTrue: [^ true].
  49580.     self changed: #wantToChange.  "Solicit cancel from view"
  49581.     ^ self isUnlocked!
  49582. unlock
  49583.     "Unlock the receiver. Any modification has presumably been saved."
  49584.  
  49585.     isLocked _ false! !
  49586.  
  49587. !StringHolder methodsFor: 'private'!
  49588. defaultContents
  49589.  
  49590.     ^''! !
  49591. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  49592.  
  49593. StringHolder class
  49594.     instanceVariableNames: ''!
  49595.  
  49596. !StringHolder class methodsFor: 'class initialization'!
  49597. initialize
  49598.     "The class variables were initialized once, and subsequently filled with
  49599.     information. Re-executing this method is therefore dangerous." 
  49600.      
  49601.     "workSpace _ StringHolder new"
  49602.  
  49603.     "StringHolder initialize"! !
  49604.  
  49605. !StringHolder class methodsFor: 'instance creation'!
  49606. new
  49607.  
  49608.     ^super new initialize! !
  49609.  
  49610. !StringHolder class methodsFor: 'workspace constants'!
  49611. originalWorkspaceContents 
  49612.     ^ self class firstCommentAt: #originalWorkspaceContents
  49613.  
  49614.  
  49615.     "             Smalltalk-80
  49616.              August 1st, 1985
  49617.   Copyright (c) 1981, 1982 Xerox Corp.
  49618.  Copyright (c) 1985 Apple Computer, Inc.
  49619.            All rights reserved.
  49620.  
  49621. Changes and Files
  49622. Smalltalk noChanges.
  49623. Smalltalk condenseChanges
  49624. DisplayScreen removeFromChanges.
  49625. Smalltalk changes asSortedCollection
  49626. Smalltalk browseChangedMessages
  49627. (FileStream fileNamed: 'changes.st') fileOutChanges.
  49628. FileStream fileNamed: 'PenChanges.st') fileOutChangesFor: Pen.
  49629. (FileStream oldFileNamed: 'Toothpaste.st') fileIn.
  49630. (FileStream fileNamed: 'Hello') edit.
  49631. FileDirectory filesMatching: '*.st'
  49632.  
  49633. Inquiry
  49634. InputState browseAllAccessesTo: 'deltaTime'.
  49635. Smalltalk browseAllCallsOn: #isEmpty.
  49636. Smalltalk browseAllImplementorsOf: #includes:
  49637. Smalltalk browseAllCallsOn:
  49638.     (Smalltalk associationAt: #Mac)
  49639. Smalltalk browseAllCallsOn:
  49640.     (Cursor classPool associationAt: #ReadCursor).
  49641. Smalltalk browseAllCallsOn:
  49642.     (Undeclared associationAt: #Disk)
  49643. Smalltalk browseAllMethodsInCategory: #examples
  49644. (Smalltalk collectPointersTo: StrikeFont someInstance) inspect.
  49645. Smalltalk garbageCollect.
  49646. FileStream instanceCount 4
  49647. FormView allInstances inspect.
  49648. Smalltalk browse:  Random
  49649.  
  49650. HouseCleaning
  49651. Undeclared _ Dictionary new.
  49652. Undeclared keys
  49653. Undeclared associationsDo:
  49654.     [:assn | Smalltalk browseAllCallsOn: assn]
  49655. (Object classPool at: #DependentsFields) keys
  49656. (Object classPool at: #DependentsFields) keysDo: 
  49657.     [:each | (each isKindOf: DisplayText)
  49658.         ifTrue: [each release]]
  49659. Transcript clear.
  49660. Smalltalk allBehaviorsDo: ""remove old do it code""
  49661.     [:class | class removeSelector: #DoIt; 
  49662.             removeSelector: #DoItIn:].
  49663. Smalltalk removeKey: #GlobalName.
  49664. Smalltalk declare: #GlobalName
  49665.     from: Undeclared.
  49666.  
  49667. Globals
  49668. Names in Smalltalk other than Classes and Pools:
  49669.     Display -- a DisplayScreen
  49670.     Processor --  a ProcessorScheduler 
  49671.     ScheduledControllers -- a ControlManager
  49672.     Sensor -- an InputSensor
  49673.     Transcript -- a TextCollector
  49674.     SourceFiles -- Array of FileStreams
  49675.     SystemOrganization -- a SystemOrganizer
  49676.     StartUpList -- an OrderedCollection
  49677.     ShutDownList -- an OrderedCollection
  49678. Variable Pools (Dictionaries)
  49679.     Smalltalk 
  49680.     FilePool
  49681.     BitMaskPool
  49682.     TextConstants
  49683.     Undeclared
  49684.  
  49685. System Files
  49686. SourceFiles _ Array                ""open source files""
  49687.     with: (FileStream oldFileNamed:
  49688.                 Smalltalk sourcesName) readOnly
  49689.     with: (FileStream oldFileNamed:
  49690.                 Smalltalk changesName).
  49691. (SourceFiles at: 1) close.            ""close source files""
  49692. (SourceFiles at: 2) close.
  49693. SourceFiles _ Array new: 2.
  49694.  
  49695. Measurements
  49696. Smalltalk spaceLeft '16381 objects, 104308 words.'
  49697. Symbol instanceCount 3697
  49698. BlockContext instanceCount 14
  49699. Time millisecondsToRun:
  49700.     [Smalltalk allCallsOn: #asOop] 11504
  49701. MessageTally spyOn: [Smalltalk allCallsOn: #asOop].
  49702.  
  49703. Crash recovery
  49704. Smalltalk recover: 5000."
  49705.  
  49706. "This is the string found in the image, Feb 91"!
  49707. systemWorkspaceContents: aString
  49708.     Workspace _ aString!
  49709. workspace
  49710.     "Answer the model for the system workspace."
  49711.  
  49712.     ^Workspace! !
  49713.  
  49714. StringHolder initialize!
  49715. ParagraphEditor subclass: #StringHolderController
  49716.     instanceVariableNames: 'isLockingOn '
  49717.     classVariableNames: 'CodeYellowButtonMessages CodeYellowButtonMenu '
  49718.     poolDictionaries: ''
  49719.     category: 'Interface-Support'!
  49720. StringHolderController comment:
  49721. 'I represent a ParagraphEditor for a single paragraph of text, omitting alignment commands. I provide items in the yellow button menu so that the text selection can be evaluated and so that the contents of the model can be stored or restored.
  49722.     doIt    evaluate the text selection as an expression
  49723.     printIt    same as doIt but insert a description of the result after the selection
  49724.     accept    store the contents of the StringHolder into the model
  49725.     cancel    store the contents of the model into the StringHolder'!
  49726.  
  49727. !StringHolderController methodsFor: 'initialize-release'!
  49728. initialize
  49729.  
  49730.     super initialize.
  49731.     isLockingOn _ true! !
  49732.  
  49733. !StringHolderController methodsFor: 'lock access'!
  49734. isLockingOff
  49735.     "Answer whether no unsaved modifications have been carried out using 
  49736.     the receiver."
  49737.  
  49738.     ^isLockingOn not!
  49739. isLockingOn
  49740.     "Answer whether unsaved modifications have been carried out using the 
  49741.     receiver."
  49742.  
  49743.     ^isLockingOn!
  49744. lockModel
  49745.     "If the receiver is lock, do so to the receiver's model."
  49746.  
  49747.     isLockingOn ifTrue: [model lock]!
  49748. turnLockingOff
  49749.     "Turn off the receiver's indication that it is locked."
  49750.  
  49751.     isLockingOn _ false!
  49752. turnLockingOn
  49753.     "Turn on the receiver's indication that it is locked."
  49754.  
  49755.     isLockingOn _ true!
  49756. unlockModel
  49757.     "If the receiver is locked, then the model probably is, but should not be, 
  49758.     so unlock the model."
  49759.  
  49760.     isLockingOn ifTrue: [model unlock]! !
  49761.  
  49762. !StringHolderController methodsFor: 'menu messages'!
  49763. accept 
  49764.     "Refer to the comment in ParagraphEditor|accept."
  49765.  
  49766.     super accept.
  49767.     model contents: paragraph string.
  49768.     self unlockModel!
  49769. cancel 
  49770.     "Refer to the comment in ParagraphEditor|cancel."
  49771.  
  49772.     super cancel.
  49773.     self unlockModel!
  49774. doIt
  49775.     "Treat the current text selection as an expression; evaluate it.
  49776.     If the left shift key is down, wait for mouse click, then restore the display.
  49777.      2/29/96 sw: if the selection is an insertion point, first select the current line."
  49778.     | result |
  49779.     self controlTerminate.
  49780.     result _ self evaluateSelection.
  49781.     self controlInitialize.
  49782.     ^result!
  49783. evaluateSelection
  49784.     "Treat the current text selection as an expression; evaluate it.
  49785.     If the left shift key is down, wait for mouse click, then restore the display.
  49786.      2/29/96 sw: if the selection is an insertion point, first select the current line."
  49787.     | result saveBits |
  49788.     self selectLine.
  49789.     (saveBits _ sensor leftShiftDown)
  49790.         ifTrue: [view topView deEmphasize; cacheBits].
  49791.     result _ model doItReceiver class evaluatorClass new
  49792.                 evaluate: self selectionAsStream
  49793.                 in: model doItContext
  49794.                 to: model doItReceiver
  49795.                 notifying: self
  49796.                 ifFail: [self controlInitialize.
  49797.                         saveBits ifTrue: [view topView emphasize].
  49798.                         ^ #failedDoit].
  49799.     Smalltalk logChange: self selection string.
  49800.     saveBits
  49801.         ifTrue: [sensor waitClickButton. ScheduledControllers restore].
  49802.     ^result!
  49803. inspectIt
  49804.     "1/13/96 sw: minor fixup"
  49805.     | result |
  49806.     self controlTerminate.
  49807.     (((result _ self evaluateSelection) isKindOf: FakeClassPool) or:
  49808.         [result == #failedDoit])
  49809.             ifFalse: [result inspect]
  49810.             ifTrue: [view flash].
  49811.     self controlInitialize!
  49812. performMenuMessage: aSelector
  49813.     "Intercept #again so the model does not get locked by keying the search text."
  49814.  
  49815.     | locked |
  49816.     locked _ model isLocked.
  49817.     super performMenuMessage: aSelector.
  49818.     (locked not and: [aSelector == #again and:
  49819.         [(UndoMessage sends: #undoAgain:andReselect:typedKey:) and: [UndoMessage arguments at: 3]]]) ifTrue:
  49820.             [self unlockModel]!
  49821. printIt
  49822.     "Treat the current text selection as an expression; evaluate it. Insert the 
  49823.     description of the result of evaluation after the selection and then make 
  49824.     this description the new text selection."
  49825.  
  49826.     | result |
  49827.     result _ self doIt.
  49828.     result ~~ #failedDoit
  49829.         ifTrue: [self afterSelectionInsertAndSelect: result printString]! !
  49830.  
  49831. !StringHolderController methodsFor: 'compiler access'!
  49832. correctFrom: start to: stop with: aString
  49833.     "Make a correction in the model that the user has authorised from somewhere else in the system (such as from the compilier).  The user's selection is not changed, only corrected."
  49834.     | wasShowing userSelection delta loc |
  49835.     aString = '#insert period' ifTrue:
  49836.         [loc _ start.
  49837.         [(loc _ loc-1)>0 and: [(paragraph text string at: loc) isSeparator]]
  49838.             whileTrue: [loc _ loc-1].
  49839.         ^ self correctFrom: loc+1 to: loc with: '.'].
  49840.     (wasShowing _ selectionShowing) ifTrue: [ self reverseSelection ].
  49841.     userSelection _ self selectionInterval.
  49842.  
  49843.     self selectInvisiblyFrom: start to: stop.
  49844.     self replaceSelectionWith: aString asText.
  49845.  
  49846.     delta _ aString size - (stop - start + 1).
  49847.     self selectInvisiblyFrom:
  49848.         userSelection first + (userSelection first > start ifFalse: [ 0 ] ifTrue: [ delta ])
  49849.         to: userSelection last + (userSelection last > start ifFalse: [ 0 ] ifTrue: [ delta ]).
  49850.     wasShowing ifTrue: [ self reverseSelection ].
  49851. !
  49852. nextTokenFrom: start direction: dir
  49853.     "Basically, find where to place a period before start"
  49854.     | loc str |
  49855.     loc _ start + dir.
  49856.     str _ paragraph text string.
  49857.     [(loc between: 1 and: str size) and: [(str at: loc) isSeparator]]
  49858.         whileTrue: [loc _ loc + dir].
  49859.     ^ loc!
  49860. notify: aString at: anInteger in: aStream 
  49861.     "The compilation of text failed. The syntax error is noted as the argument, 
  49862.     aString. Insert it in the text at starting character position anInteger."
  49863.  
  49864.     self insertAndSelect: aString at: (anInteger max: 1)! !
  49865.  
  49866. !StringHolderController methodsFor: 'model access'!
  49867. model: aModel
  49868.  
  49869.     super model: aModel.
  49870.     view displayContents == nil
  49871.         ifFalse: [self changeParagraph: view displayContents]! !
  49872.  
  49873. !StringHolderController methodsFor: 'private'!
  49874. afterSelectionInsertAndSelect: aString
  49875.  
  49876.     self insertAndSelect: aString at: stopBlock stringIndex !
  49877. closeTypeIn
  49878.     "Lock the model if something actually was typed."
  49879.  
  49880.     beginTypeInBlock ~~ nil ifTrue: [self lockModel].
  49881.     super closeTypeIn!
  49882. initializeYellowButtonMenu
  49883.  
  49884.     self yellowButtonMenu: CodeYellowButtonMenu 
  49885.         yellowButtonMessages: CodeYellowButtonMessages!
  49886. insertAndSelect: aString at: anInteger
  49887.  
  49888.     self replace: (anInteger to: anInteger - 1) with: (' ' , aString) asText and:
  49889.         [self selectAndScroll]!
  49890. zapSelectionWith: aText
  49891.     "Lock model, except during typeIn, which locks at close (in case 'again' follows)"
  49892.  
  49893.     super zapSelectionWith: aText.
  49894.     beginTypeInBlock == nil ifTrue: [self lockModel]! !
  49895.  
  49896. !StringHolderController methodsFor: 'binding'!
  49897. bindingOf: aString
  49898.     ^model bindingOf: aString! !
  49899.  
  49900. !StringHolderController methodsFor: 'editing keys'!
  49901. dispatchOnCharacter: char with: typeAheadStream
  49902.     "Check for Enter and cause an DOIT"
  49903.     | print |
  49904.     ^ char = Character enter
  49905.         ifTrue: [self dispatchOnEnterWith: typeAheadStream]
  49906.         ifFalse: [super dispatchOnCharacter: char with: typeAheadStream]!
  49907. dispatchOnEnterWith: typeAheadStream
  49908.     "Enter key hit.  Treat is as an 'accept', viz a synonym for cmd-s.  If cmd key is down, treat is as a synonym for print-it.  2/7/96 sw.
  49909.     2/29/96 sw: fixed erratic behavior in the cmd-key-down case -- was not always giving the 'select-line-first' behavior when the selection was empty."
  49910.  
  49911.     sensor keyboard.  "consume enter key"
  49912.     sensor commandKeyPressed
  49913.         ifTrue:
  49914.             [self printIt.]
  49915.         ifFalse: 
  49916.             [self closeTypeIn: typeAheadStream.
  49917.             self accept].
  49918.     ^ true! !
  49919. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  49920.  
  49921. StringHolderController class
  49922.     instanceVariableNames: ''!
  49923.  
  49924. !StringHolderController class methodsFor: 'class initialization'!
  49925. initialize
  49926.     "Initialize the yellow button pop-up menu and corresponding messages.
  49927.      1/12/96 sw: added senders of it, etc.  1/15/96 sw: explain
  49928.      1/22/96 sw: cmd keys detailed
  49929.      1/24/96 sw: added find; moved many items to shifted side etc.
  49930.      1/26/96 sw: made compatible with paragraph editor's version; I'm not clear on when/how this guy gets used (seemingly eg in a workspace) vs when the paragraph editor's does (seemingly in browsers)
  49931.      2/29/96 sw: correct cmd-key equivalent for do again, and add set-search-string"
  49932.  
  49933.     CodeYellowButtonMenu _ 
  49934.         PopUpMenu 
  49935.             labels: 
  49936. 'find...(f)
  49937. find again (g)
  49938. set search string (h)
  49939. do again (j)
  49940. undo (z)
  49941. copy (c)
  49942. cut (x)
  49943. paste (v)
  49944. do it (d)
  49945. print it (p)
  49946. inspect it (i)
  49947. accept (s)
  49948. cancel (l)
  49949. more...' 
  49950.         lines: #(3 5  8 11 13).
  49951.     CodeYellowButtonMessages _ 
  49952.         #(find findAgain setSearchString again undo copySelection cut paste doIt printIt inspectIt accept cancel shiftedYellowButtonActivity)
  49953.  
  49954.     "StringHolderController initialize"! !
  49955.  
  49956. StringHolderController initialize!
  49957. View subclass: #StringHolderView
  49958.     instanceVariableNames: 'displayContents '
  49959.     classVariableNames: ''
  49960.     poolDictionaries: ''
  49961.     category: 'Interface-Support'!
  49962. StringHolderView comment:
  49963. 'I am a View of a String that is an aspect of a more structured object. This String should not be changed by any editing unless the user issues the accept command. Thus my instances provide a working copy of the String. This copy is edited. When the user issues the accept command, the String is copied from the working version; or if the user issues the cancel command, the working version is restored from the String. StringHolderController is my default controller. It is initialized specially by passing the string viewed which is then converted to a Paragraph for editing.'!
  49964.  
  49965. !StringHolderView methodsFor: 'initialize-release'!
  49966. initialize 
  49967.     "Refer to the comment in View|initialize."
  49968.     super initialize.
  49969.     displayContents _ '' asParagraph! !
  49970.  
  49971. !StringHolderView methodsFor: 'updating'!
  49972. promptForCancel
  49973.     "Ask if it is OK to cancel changes to text"
  49974.     | okToCancel stripes |
  49975.     stripes _ Form extent: 16@16 fromStipple: 16r36C9.
  49976.     Display border: self insetDisplayBox width: 4
  49977.             rule: Form reverse fillColor: stripes.
  49978.     okToCancel _ (self confirm: 'Changes have not been saved.
  49979. Is it OK to cancel those changes?').
  49980.     Display border: self insetDisplayBox width: 4
  49981.             rule: Form reverse fillColor: stripes.
  49982.     okToCancel ifTrue:
  49983.         [self updateDisplayContents. model unlock
  49984.         "=self controller cancel= would be more consistent,
  49985.         and should provide undo, but tacky code there
  49986.         only works when =controller isInControl="]!
  49987. update: aSymbol
  49988.     "Refer to the comment in View|update:."
  49989.     aSymbol == #wantToChange ifTrue: [^ self promptForCancel].
  49990.     aSymbol == #flash ifTrue: [^ controller flash].
  49991.     self updateDisplayContents!
  49992. updateDisplayContents
  49993.     "Make the text that is displayed be the contents of the receiver's model."
  49994.  
  49995.     self editString: model contents.
  49996.     self displayView! !
  49997.  
  49998. !StringHolderView methodsFor: 'controller access'!
  49999. defaultController 
  50000.     "Refer to the comment in View|defaultController."
  50001.  
  50002.     ^self defaultControllerClass newParagraph: displayContents!
  50003. defaultControllerClass 
  50004.     "Refer to the comment in View|defaultControllerClass."
  50005.  
  50006.     ^StringHolderController!
  50007. displayContents
  50008.  
  50009.     ^displayContents! !
  50010.  
  50011. !StringHolderView methodsFor: 'displaying'!
  50012. display 
  50013.     "Refer to the comment in View.display."
  50014.     (self isUnlocked and: [self insetDisplayBox ~= displayContents clippingRectangle])
  50015.         ifTrue:  "Recompose the text if the window changed"
  50016.                 [self positionDisplayContents. 
  50017.                 (self controller isKindOf: ParagraphEditor)
  50018.                     ifTrue: [controller recomputeSelection]].
  50019.     super display!
  50020. displayView 
  50021.     "Refer to the comment in View|displayView."
  50022.  
  50023.     self clearInside.
  50024.     (self controller isKindOf: ParagraphEditor)
  50025.         ifTrue: [controller display]
  50026.         ifFalse: [displayContents display]!
  50027. lock
  50028.     "Refer to the comment in view|lock.  Must do at least what display would do to lock the view."
  50029.     (self isUnlocked and: [self insetDisplayBox ~= displayContents clippingRectangle])
  50030.         ifTrue:  "Recompose the text if the window changed"
  50031.                 [self positionDisplayContents. 
  50032.                 (self controller isKindOf: ParagraphEditor)
  50033.                     ifTrue: [controller recomputeSelection]].
  50034.     super lock!
  50035. positionDisplayContents
  50036.     "Presumably the text being displayed changed so that the wrapping box 
  50037.     and clipping box should be reset."
  50038.  
  50039.     displayContents 
  50040.         wrappingBox: (self insetDisplayBox insetBy: 6 @ 0)
  50041.         clippingBox: self insetDisplayBox! !
  50042.  
  50043. !StringHolderView methodsFor: 'model access'!
  50044. editString: aString 
  50045.     "The paragraph to be displayed is created from the characters in aString."
  50046.  
  50047.     displayContents _ Paragraph withText: aString asText
  50048.         style: TextStyle default copy
  50049.         compositionRectangle: (self insetDisplayBox insetBy: 6 @ 0)
  50050.         clippingRectangle: self insetDisplayBox
  50051.         foreColor: self foregroundColor backColor: self backgroundColor.
  50052.     (self controller isKindOf: ParagraphEditor)
  50053.         ifTrue: [controller changeParagraph: displayContents]!
  50054. model: aLockedModel 
  50055.     "Refer to the comment in View|model:."
  50056.  
  50057.     super model: aLockedModel.
  50058.     self editString: model contents! !
  50059.  
  50060. !StringHolderView methodsFor: 'deEmphasizing'!
  50061. deEmphasizeView 
  50062.     "Refer to the comment in View|deEmphasizeView."
  50063.  
  50064.     (self controller isKindOf: ParagraphEditor)
  50065.          ifTrue: [controller deselect]! !
  50066. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  50067.  
  50068. StringHolderView class
  50069.     instanceVariableNames: ''!
  50070.  
  50071. !StringHolderView class methodsFor: 'instance creation'!
  50072. container
  50073.     "Answer an instance of me with a new instance of StringHolder as the 
  50074.     model."
  50075.  
  50076.     ^self container: StringHolder new!
  50077. container: aContainer 
  50078.     "Answer an instance of me whose model is aContainer. Give it a 2-dot 
  50079.     border."
  50080.  
  50081.     | aCodeView |
  50082.     aCodeView _ self new model: aContainer.
  50083.     aCodeView borderWidthLeft: 2 right: 2 top: 2 bottom: 2.
  50084.     ^aCodeView!
  50085. open
  50086.     "Create a standard system view of a workspace on the screen."
  50087.  
  50088.     self open: Workspace new label: 'Workspace'!
  50089. open: aStringHolder 
  50090.     "Create a standard system view of the argument, aStringHolder, as viewed 
  50091.     by an instance of me. The view has label 'StringHolder'."
  50092.  
  50093.     self open: aStringHolder label: 'StringHolder'!
  50094. open: aStringHolder label: aString 
  50095.     "Create a standard system view of the model, aStringHolder, as viewed by 
  50096.     an instance of me. The label of the view is aString."
  50097.     | aStringHolderView topView |
  50098.     aStringHolderView _ self container: aStringHolder.
  50099.     topView _ StandardSystemView new.
  50100.     topView model: aStringHolderView model.
  50101.     topView addSubView: aStringHolderView.
  50102.     topView label: aString.
  50103.     topView minimumSize: 100 @ 50.
  50104.     topView controller open! !
  50105.  
  50106. !StringHolderView class methodsFor: 'workspace constants'!
  50107. openSystemWorkspace
  50108.     "Schedule a view of the system workspace."
  50109.  
  50110.     self open: StringHolder workspace label: 'System Workspace'! !Model subclass: #Switch
  50111.     instanceVariableNames: 'on onAction offAction '
  50112.     classVariableNames: ''
  50113.     poolDictionaries: ''
  50114.     category: 'Interface-Menus'!
  50115. Switch comment:
  50116. 'I represent a selection setting and actions to take depending on a change in the setting. An instance has three attributes: state, which is either on or off; on action; and off action. The on and off actions are blocks of code that execute whenever the instance changes state. I am typically used as a menu item in conjunction with a SwitchView and a SwitchController.
  50117. 1/24/96 sw: made this a subclass of Model, for faster dependents handling'!
  50118.  
  50119. !Switch methodsFor: 'initialize-release'!
  50120. release
  50121.     "Set the on and off actions of the receiver to nil ('no action') in order to
  50122.     break possible pointer cycles.  It is sent by Switch|deleteDependent: when
  50123.     the last dependent has been deleted from the Switch's list of dependents."
  50124.  
  50125.     super release.
  50126.     onAction _ nil.
  50127.     offAction _ nil! !
  50128.  
  50129. !Switch methodsFor: 'dependents access'!
  50130. removeDependent: aDependent 
  50131.     "If aDependent is the only dependent in the list, the receiver sends  
  50132.     Switch|release to try to break up possible pointer cycles."
  50133.  
  50134.     super removeDependent: aDependent.
  50135.     self dependents isEmpty ifTrue: [self release]! !
  50136.  
  50137. !Switch methodsFor: 'clearing'!
  50138. clear
  50139.     "Set the state of the receiver to 'off'. If the state of the receiver was 
  50140.     previously 'on', then 'self change' is sent. The receiver's off action is 
  50141.     NOT executed."
  50142.  
  50143.     self isOn
  50144.         ifTrue: 
  50145.             [on _ false.
  50146.             self changed]! !
  50147.  
  50148. !Switch methodsFor: 'state'!
  50149. isOff
  50150.     "Answer whether the receiver is set off or not."
  50151.  
  50152.     ^on not!
  50153. isOn
  50154.     "Answer whether the receiver is set on or not."
  50155.  
  50156.     ^on!
  50157. set
  50158.     "Set the state of the receiver to 'on'. If the state of the receiver was 
  50159.     previously 'off', then 'self change' is sent. The receiver's on action is 
  50160.     NOT executed."
  50161.  
  50162.     self isOff
  50163.         ifTrue: 
  50164.             [on _ true.
  50165.             self changed]!
  50166. switch
  50167.     "Change the state of the receiver from 'on' to 'off' or from 'off' to 'on' (see 
  50168.     Switch|turnOn, Switch|turnOff)."
  50169.  
  50170.     self isOn
  50171.         ifTrue: [self turnOff]
  50172.         ifFalse: [self turnOn]!
  50173. turnOff
  50174.     "Set the state of the receiver to 'off'. If the state of the receiver was 
  50175.     previously 'on', then 'self change' is sent and the receiver's off action is 
  50176.     executed."
  50177.  
  50178.     self isOn
  50179.         ifTrue: 
  50180.             [on _ false.
  50181.             self changed.
  50182.             self doAction: offAction]!
  50183. turnOn
  50184.     "Set the state of the receiver to 'on'. If the state of the receiver was 
  50185.     previously 'off', then 'self change' is sent and the receiver's on action is 
  50186.     executed."
  50187.  
  50188.     self isOff
  50189.         ifTrue: 
  50190.             [on _ true.
  50191.             self changed.
  50192.             self doAction: onAction]! !
  50193.  
  50194. !Switch methodsFor: 'action'!
  50195. doAction: anAction 
  50196.     "Execute anAction if it is non-nil."
  50197.  
  50198.     anAction == nil ifFalse: [anAction value]!
  50199. offAction: anAction 
  50200.     "Set the off action of the receiver to anAction."
  50201.  
  50202.     offAction _ anAction fixTemps!
  50203. onAction: anAction 
  50204.     "Set the on action of the receiver to anAction."
  50205.  
  50206.     onAction _ anAction fixTemps! !
  50207.  
  50208. !Switch methodsFor: 'private'!
  50209. initializeOff
  50210.  
  50211.     on _ false. 
  50212.     onAction _ nil.
  50213.     offAction _ nil!
  50214. initializeOn
  50215.  
  50216.     on _ true. 
  50217.     onAction _ nil.
  50218.     offAction _ nil! !
  50219. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  50220.  
  50221. Switch class
  50222.     instanceVariableNames: ''!
  50223.  
  50224. !Switch class methodsFor: 'instance creation'!
  50225. new
  50226.     "Answer an instance of me such that the on and off actions are set to nil
  50227.     ('no action'), and the state is set to 'off'."
  50228.  
  50229.     ^self newOff!
  50230. newOff
  50231.     "Answer an instance of me such that the on and off actions are set to nil 
  50232.     ('no action'), and the state is set to 'off'."
  50233.  
  50234.     ^super new initializeOff!
  50235. newOn
  50236.     "Answer an instance of me such that the on and off actions are set to nil 
  50237.     ('no action'), and the state is set to 'on'."
  50238.  
  50239.     ^super new initializeOn! !Controller subclass: #SwitchController
  50240.     instanceVariableNames: 'selector arguments '
  50241.     classVariableNames: ''
  50242.     poolDictionaries: ''
  50243.     category: 'Interface-Menus'!
  50244. SwitchController comment:
  50245. 'I coordinate the interaction of a Switch, a SwitchView, and input events (user actions, see class Sensor). My instances own a message in the form of a selector and an array of arguments. Whenever the Switch is selected, this message is sent to the Switch. I want control if the cursor is in the view and the red button is pressed.'!
  50246.  
  50247. !SwitchController methodsFor: 'initialize-release'!
  50248. initialize 
  50249.     "Refer to the comment in Controller|initialize."
  50250.  
  50251.     super initialize.
  50252.     selector _ #switch.
  50253.     arguments _ Array new: 0! !
  50254.  
  50255. !SwitchController methodsFor: 'accessing'!
  50256. addArgument: aValue 
  50257.     "Add the argument, aValue, as one of the arguments of the message the 
  50258.     receiver sends to its model."
  50259.  
  50260.     arguments _ arguments copyWith: aValue!
  50261. arguments
  50262.     "Answer the arguments the receiver sends in a message to its receiver."
  50263.  
  50264.     ^arguments!
  50265. arguments: anArray
  50266.     "The argument, anArray, consists of the arguments of the message the 
  50267.     receiver sends to its model."
  50268.  
  50269.     arguments _ anArray!
  50270. selector
  50271.     "Answer the selector the receiver sends in a message to its receiver."
  50272.  
  50273.     ^selector!
  50274. selector: aSymbol 
  50275.     "Set aSymbol to be the selector the receiver sends in a message to its 
  50276.     model."
  50277.  
  50278.     selector _ aSymbol! !
  50279.  
  50280. !SwitchController methodsFor: 'basic control sequence'!
  50281. controlInitialize 
  50282.     "Refer to the comment in Controller|controlInitialize."
  50283.  
  50284.     view indicatorReverse!
  50285. controlTerminate 
  50286.     "Refer to the comment in Controller|controlTerminate."
  50287.  
  50288.     view indicatorReverse.
  50289.     self viewHasCursor ifTrue: [self sendMessage]!
  50290. sendMessage
  50291.     "The receiver consists of a selector and possibly of arguments that should 
  50292.     be used to create a message to send to the receiver's model."
  50293.  
  50294.     | aBrowser aChangeSorter |
  50295.     arguments size = 0
  50296.         ifTrue: [model perform: selector]
  50297.         ifFalse: [model perform: selector withArguments: arguments].
  50298.  
  50299.     false ifTrue: ["Selectors Performed"
  50300.         "Please list all selectors that could be args to the 
  50301.         perform: in this method.  Do this so senders will find
  50302.         this method as one of the places the selector is sent from."
  50303.         self listPerformSelectorsHere.        "tells the parser its here"
  50304.  
  50305.         aBrowser indicateClassMessages.
  50306.         aBrowser indicateInstanceMessages.
  50307.         aChangeSorter whatPolarity.
  50308.         ].! !
  50309.  
  50310. !SwitchController methodsFor: 'control defaults'!
  50311. controlActivity 
  50312.     "Refer to the comment in Controller|controlActivity."
  50313.  
  50314.     ^self!
  50315. isControlActive 
  50316.     "Refer to the comment in Controller|isControlActive."
  50317.  
  50318.     ^sensor anyButtonPressed & self viewHasCursor!
  50319. isControlWanted
  50320.  
  50321.     sensor flushKeyboard.
  50322.     ^ self viewHasCursor & sensor redButtonPressed! !View subclass: #SwitchView
  50323.     instanceVariableNames: 'complemented label selector keyCharacter highlightForm arguments '
  50324.     classVariableNames: ''
  50325.     poolDictionaries: ''
  50326.     category: 'Interface-Menus'!
  50327. SwitchView comment:
  50328. 'I am a view of a Switch. My instances have labels and display modes (set to "normal" or "complemented"). When one of my instances is displayed in complemented mode, its inside color is reversed. The value of the display mode corresponds to the value of the model so that, for example, when a Switch is off, its SwitchView is displayed with black text (for the label) on a white background, and when the Switch is on, its SwitchView is displayed with white text on a black background. My instances have a key character that can be used for selecting the model. Highlighting can be done specially using a stored form, rather than simply changing all black bits to white, and vice versa. My instances'' default controller is SwitchController.'!
  50329.  
  50330. !SwitchView methodsFor: 'initialize-release'!
  50331. initialize 
  50332.     "Refer to the comment in View|initialize."
  50333.     super initialize.
  50334.     complemented _ false.
  50335.     label _ nil.
  50336.     selector _ #isOn.
  50337.     arguments _ #()!
  50338. release
  50339.  
  50340.     super release.
  50341.     label release! !
  50342.  
  50343. !SwitchView methodsFor: 'accessing'!
  50344. arguments
  50345.     "Answer the arguments the receiver sends in a message to its receiver."
  50346.  
  50347.     ^arguments!
  50348. arguments: anArray
  50349.     "The argument, anArray, consists of the arguments of the message
  50350.     the receiver sends to its model."
  50351.  
  50352.     arguments _ anArray!
  50353. highlightForm: aForm 
  50354.     "The argument is the form to be used to highlight the receiver."
  50355.  
  50356.     highlightForm _ aForm!
  50357. key: aCharacter 
  50358.     "Set the receiver to be selected by the argument, aCharacter."
  50359.  
  50360.     keyCharacter _ aCharacter! !
  50361.  
  50362. !SwitchView methodsFor: 'testing'!
  50363. containsKey: aCharacter 
  50364.     "Answer whether the receiver can be selected by the argument, 
  50365.     aCharacter."
  50366.  
  50367.     ^keyCharacter = aCharacter! !
  50368.  
  50369. !SwitchView methodsFor: 'controller access'!
  50370. defaultControllerClass 
  50371.     "Refer to the comment in View|defaultControllerClass."
  50372.  
  50373.     ^SwitchController! !
  50374.  
  50375. !SwitchView methodsFor: 'window access'!
  50376. defaultWindow
  50377.     "Returns the frame of the SwitchView's label's frame (slightly enlarged) 
  50378.     if the label exists, and returns the standard View default window (see 
  50379.     View|defaultWindow), otherwise."
  50380.  
  50381.     label == nil
  50382.         ifTrue: [^super defaultWindow]
  50383.         ifFalse: [^label boundingBox expandBy: 6]!
  50384. window: aWindow 
  50385.     "Refer to the comment in View|window:."
  50386.  
  50387.     super window: aWindow.
  50388.     self centerLabel! !
  50389.  
  50390. !SwitchView methodsFor: 'displaying'!
  50391. display
  50392.     "Sets the SwitchView mode to 'normal', displays the border, displays the 
  50393.     inside and, if its model is 'on', complements the inside."
  50394.  
  50395.     self displayBorder.
  50396.     self displayView!
  50397. displayComplemented
  50398.     "Complement the receiver if its mode is 'normal'."
  50399.  
  50400.     complemented
  50401.         ifFalse: 
  50402.             [complemented _ true.
  50403.             self highlight]!
  50404. displayNormal
  50405.     "Complement the receiver if its mode is 'complemented'."
  50406.  
  50407.     complemented
  50408.         ifTrue: 
  50409.             [complemented _ false.
  50410.             self highlight]!
  50411. displaySpecial 
  50412.     "The receiver has a special highlight form. Use it for displaying 
  50413.     complemented, if appropriate."
  50414.  
  50415.     complemented
  50416.         ifTrue: [self displaySpecialComplemented].
  50417.     label == nil 
  50418.         ifFalse: [label
  50419.                     displayOn: Display
  50420.                     transformation: self displayTransformation
  50421.                     clippingBox: self insetDisplayBox
  50422.                     align: label boundingBox center
  50423.                     with: label boundingBox center
  50424.                     rule: Form under
  50425.                     fillColor: nil]!
  50426. displaySpecialComplemented 
  50427.     "Display the receiver complemented using its special highlight form."
  50428.  
  50429.     highlightForm
  50430.         displayOn: Display
  50431.         transformation: self displayTransformation
  50432.         clippingBox: self insetDisplayBox
  50433.         fixedPoint: label boundingBox center!
  50434. displayView
  50435.     "Does the standard View actions and, in addition, displays the receiver's 
  50436.     label based on the current display transformation and inset display box."
  50437.  
  50438.     highlightForm == nil ifFalse: [self displaySpecial].
  50439.     self clearInside.
  50440.     label == nil
  50441.         ifFalse: 
  50442.             [(label isKindOf: Paragraph) ifTrue:
  50443.                     [label foregroundColor: self foregroundColor
  50444.                      backgroundColor: self backgroundColor].
  50445.             label displayOn: Display
  50446.                 transformation: self displayTransformation
  50447.                 clippingBox: self insetDisplayBox
  50448.                 fixedPoint: label boundingBox center].
  50449.     complemented _ false! !
  50450.  
  50451. !SwitchView methodsFor: 'updating'!
  50452. update: aParameter 
  50453.     "Refer to the comment in View|update:."
  50454.  
  50455.     highlightForm == nil
  50456.         ifTrue: [self interrogateModel 
  50457.                     ifTrue: [self displayComplemented]
  50458.                     ifFalse: [self displayNormal]]
  50459.         ifFalse: [self display]! !
  50460.  
  50461. !SwitchView methodsFor: 'label access'!
  50462. centerLabel
  50463.     "Align the center of the frame of the label with the center of the 
  50464.     receiver's window."
  50465.  
  50466.     label == nil 
  50467.         ifFalse: 
  50468.             [label 
  50469.                 align: label boundingBox center 
  50470.                 with: self getWindow center]!
  50471. label
  50472.     "Answer the label, a display object, that is the receiver's screen image."
  50473.  
  50474.     ^label!
  50475. label: aDisplayObject 
  50476.     "Set aDisplayObject to be the label that is the receiver's screen image."
  50477.  
  50478.     label release.
  50479.     label _ aDisplayObject.
  50480.     self centerLabel! !
  50481.  
  50482. !SwitchView methodsFor: 'indicating'!
  50483. indicatorOnDuring: aBlockContext 
  50484.     "Indicate the receiver during the execution of aBlockContext by 
  50485.     complementing the label (or a portion of the display box if no label is 
  50486.     defined)."
  50487.  
  50488.     self indicatorReverse.
  50489.     self highlight. 
  50490.     aBlockContext value.
  50491.     self highlight.
  50492.     self indicatorReverse!
  50493. indicatorReverse
  50494.     "Complement the label (or a portion of the displayBox if no label is 
  50495.     defined)."
  50496.  
  50497.     Display reverse: self insetDisplayBox fillColor: Color gray.
  50498.     Display reverse: (self insetDisplayBox insetBy: 2) fillColor: Color gray! !
  50499.  
  50500. !SwitchView methodsFor: 'selector'!
  50501. interrogateModel
  50502.     "Answer the result of sending the receiver's model the message created 
  50503.     from the receiver's selector and arguments."
  50504.  
  50505.     | aBrowser aChangeSorter |
  50506.     arguments size = 0
  50507.         ifTrue: [^model perform: selector]
  50508.         ifFalse: [^model perform: selector withArguments: arguments].
  50509.  
  50510.     false ifTrue: ["Selectors Performed"
  50511.         "Please list all selectors that could be args to the 
  50512.         perform: in this method.  Do this so senders will find
  50513.         this method as one of the places the selector is sent from."
  50514.         self listPerformSelectorsHere.        "tells the parser its here"
  50515.  
  50516.         aBrowser instanceMessagesIndicated.
  50517.         aBrowser classMessagesIndicated.
  50518.         aChangeSorter whatPolarity.
  50519.         ].!
  50520. selector
  50521.     "Answer the selector the receiver sends in a message to its receiver."
  50522.  
  50523.     ^selector!
  50524. selector: aSymbol 
  50525.     "Set aSymbol to be the selector the receiver sends in a message to its 
  50526.     model."
  50527.  
  50528.     selector _ aSymbol! !
  50529.  
  50530. !SwitchView methodsFor: 'deEmphasizing'!
  50531. deEmphasizeView 
  50532.     "See View|deEmphasizeView."
  50533.     highlightForm == nil
  50534.         ifTrue: [self interrogateModel ifTrue: [self displayNormal]]
  50535.         ifFalse: [self displaySpecial]!
  50536. emphasizeView 
  50537.     "See View|deEmphasizeView."
  50538.     highlightForm == nil
  50539.         ifTrue: [self interrogateModel ifTrue: [self displayComplemented]]
  50540.         ifFalse: [self displaySpecial]! !String variableByteSubclass: #Symbol
  50541.     instanceVariableNames: ''
  50542.     classVariableNames: 'SelectorTables OtherTable SingleCharSymbols '
  50543.     poolDictionaries: ''
  50544.     category: 'Collections-Text'!
  50545. Symbol comment:
  50546. 'I represent Strings that are created uniquely. Thus, someString asSymbol == someString asSymbol.'!
  50547.  
  50548. !Symbol methodsFor: 'accessing'!
  50549. at: anInteger put: anObject 
  50550.     "You cannot modify the receiver."
  50551.  
  50552.     self errorNoModification!
  50553. replaceFrom: start to: stop with: replacement startingAt: repStart
  50554.  
  50555.     self errorNoModification! !
  50556.  
  50557. !Symbol methodsFor: 'comparing'!
  50558. = anObject
  50559.  
  50560.     ^self == anObject!
  50561. hash
  50562.     "Primitive. Answer with a SmallInteger whose value is half of the
  50563.     receiver's object pointer (interpreting object pointers as 16-bit signed
  50564.     quantities). Essential. See Object documentation whatIsAPrimitive."
  50565.  
  50566.     <primitive: 75>
  50567.     ^self!
  50568. hashMappedBy: map
  50569.     "Answer what my hash would be if oops changed according to map."
  50570.  
  50571.     ^map newHashFor: self hash! !
  50572.  
  50573. !Symbol methodsFor: 'copying'!
  50574. copy
  50575.     "Answer with the receiver, because Symbols are unique."!
  50576. shallowCopy
  50577.     "Answer with the receiver, because Symbols are unique."! !
  50578.  
  50579. !Symbol methodsFor: 'converting'!
  50580. asString 
  50581.     "Refer to the comment in String|asString."
  50582.  
  50583.     | newString |
  50584.     newString _ String new: self size.
  50585.     1 to: self size do: [:index | newString at: index put: (self at: index)].
  50586.     ^newString!
  50587. asSymbol 
  50588.     "Refer to the comment in String|asSymbol."! !
  50589.  
  50590. !Symbol methodsFor: 'printing'!
  50591. isLiteral
  50592.  
  50593.     ^Scanner isLiteralSymbol: self!
  50594. printOn: aStream
  50595.  
  50596.     aStream nextPutAll: self!
  50597. storeOn: aStream
  50598.  
  50599.     self isLiteral
  50600.         ifTrue:
  50601.             [aStream nextPut: $#.
  50602.             aStream nextPutAll: self]
  50603.         ifFalse:
  50604.             [super storeOn: aStream.
  50605.             aStream nextPutAll: ' asSymbol']! !
  50606.  
  50607. !Symbol methodsFor: 'system primitives'!
  50608. isInfix
  50609.     "Answer whether the receiver is an infix message selector."
  50610.  
  50611.     ^(self at: 1) isLetter not!
  50612. isKeyword
  50613.     "Answer whether the receiver is a message keyword, i.e., ends with 
  50614.     colon."
  50615.  
  50616.     self size <= 1 ifTrue: [^false].
  50617.     ^(self at: self size) = $:!
  50618. isPvtSelector | prefix prefixSize |
  50619.     "Answer whether the receiver is a private message selector, that is, begins with 'pvt' followed by an uppercase letter, e.g. pvtStringhash."
  50620.  
  50621.     prefix _ 'pvt'.
  50622.     prefixSize _ prefix size.
  50623.  
  50624.     self size <= prefixSize ifTrue: [^false].
  50625.     1 to: prefixSize do:
  50626.         [:index | (self at: index) = (prefix at: index) ifFalse: [^false]].
  50627.     ^(self at: prefixSize + 1) isUppercase! !
  50628.  
  50629. !Symbol methodsFor: 'private'!
  50630. errorNoModification
  50631.  
  50632.     self error: 'symbols can not be modified.'!
  50633. species
  50634.  
  50635.     ^String!
  50636. string: aString
  50637.  
  50638.     1 to: aString size do: [:j | super at: j put: (aString at: j)].
  50639.     ^self  !
  50640. stringhash
  50641.  
  50642.     ^super hash! !
  50643. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  50644.  
  50645. Symbol class
  50646.     instanceVariableNames: ''!
  50647.  
  50648. !Symbol class methodsFor: 'class initialization'!
  50649. initialize
  50650.  
  50651.     | a v |
  50652.     "make up table of 1-char atoms"
  50653.     v _ Array new: 128.
  50654.     a _ String new: 1.
  50655.     1 to: 128 do: 
  50656.         [:i | 
  50657.         a at: 1 put: i - 1.
  50658.         v at: i put: a asSymbol].
  50659.     SingleCharSymbols _ v
  50660.     
  50661.     "Symbol initialize"! !
  50662.  
  50663. !Symbol class methodsFor: 'instance creation'!
  50664. intern: aString 
  50665.     "Answer a unique Symbol whose characters are those of aString."
  50666.  
  50667.     | ascii table mainTable index sym numArgs |
  50668.  
  50669.     ascii _ (aString at: 1) asciiValue.
  50670.     aString size = 1 ifTrue: [ascii < 128 ifTrue: 
  50671.         [^ SingleCharSymbols at: ascii + 1]].
  50672.  
  50673.     table _ ((ascii >= "$a asciiValue" 97) and:
  50674.         [(ascii <= "$z asciiValue" 122) and:
  50675.         [(numArgs _ aString numArgs) >= 0]])
  50676.             ifTrue: [ (mainTable _ SelectorTables
  50677.                                     at: (numArgs + 1 min: SelectorTables size))
  50678.                         at: (index _ ascii - "($a asciiValue - 1)" 96) ]
  50679.             ifFalse: [ (mainTable _ OtherTable)
  50680.                         at: (index _ aString stringhash \\ OtherTable size + 1)].
  50681.  
  50682.     1 to: table size do: 
  50683.         [:i | 
  50684.         (table at: i) == nil 
  50685.             ifFalse: [aString size = (table at: i) size ifTrue: [aString = (table at: i)
  50686.                         ifTrue: 
  50687.                             [^ table at: i]]]].
  50688.  
  50689.     sym _ (aString isMemberOf: Symbol)
  50690.         ifTrue: [aString]     "putting old symbol in new table"
  50691.         ifFalse: [(Symbol new: aString size) string: aString]. "create a new one"
  50692.  
  50693.     mainTable at: index put: (table copyWith: sym).
  50694.     ^sym
  50695. !
  50696. internCharacter: aCharacter
  50697.     "Answer a unique Symbol of one character, the argument, aCharacter."
  50698.  
  50699.     | ascii |
  50700.     (ascii _ aCharacter asciiValue) < 128
  50701.         ifTrue: [^SingleCharSymbols at: ascii + 1].
  50702.     ^self intern: (String with: aCharacter)!
  50703. newFrom: aCollection 
  50704.     "Answer an instance of me containing the same elements as aCollection."
  50705.  
  50706.     ^ (aCollection as: String) asSymbol
  50707.  
  50708. "    Symbol newFrom: {$P. $e. $n}
  50709.     {$P. $e. $n} as: Symbol
  50710. "! !
  50711.  
  50712. !Symbol class methodsFor: 'private'!
  50713. hasInterned: aString ifTrue: symBlock 
  50714.     "Answer with false if aString hasnt been interned (into a Symbol), 
  50715.     otherwise supply the symbol to symBlock and return true."
  50716.  
  50717.     | table ascii numArgs |
  50718.  
  50719.     ascii _ (aString at: 1) asciiValue.
  50720.     aString size = 1 ifTrue: [ascii < 128 ifTrue: 
  50721.         [symBlock value: (SingleCharSymbols at: ascii + 1).
  50722.         ^true]].
  50723.  
  50724.     table _ ((ascii >= "$a asciiValue" 97) and:
  50725.         [(ascii <= "$z asciiValue" 122) and:
  50726.         [(numArgs _ aString numArgs) >= 0]])
  50727.             ifTrue: [ (SelectorTables at: (numArgs + 1 min: SelectorTables size))
  50728.                         at: ascii - "($a asciiValue - 1)" 96 ]
  50729.             ifFalse: [ OtherTable at: aString stringhash \\ OtherTable size + 1].
  50730.  
  50731.     1 to: table size do: 
  50732.         [:i | 
  50733.         (table at: i) == nil 
  50734.             ifFalse: [aString size = (table at: i) size ifTrue: [aString = (table at: i)
  50735.                         ifTrue: 
  50736.                             [symBlock value: (table at: i).
  50737.                             ^true]]]].
  50738.     ^false
  50739. !
  50740. rehash        "Symbol rehash"
  50741.     "Rebuild the hash table, reclaiming unreferenced Symbols."
  50742.     | count oldCount |
  50743.     SelectorTables _ (1 to: 6) collect: [ :i | (1 to: 26) collect: [ :j | Array new: 0 ] ].
  50744.     OtherTable _ (1 to: 51) collect: [:k | Array new: 0].
  50745.     oldCount _ Symbol instanceCount.
  50746.     count _ 0.
  50747.     'Rebuilding Symbol Tables...'
  50748.         displayProgressAt: Sensor cursorPoint
  50749.         from: 0 to: oldCount
  50750.         during:
  50751.             [:bar |
  50752.             Smalltalk garbageCollect.
  50753.             Symbol allInstancesDo:
  50754.                 [ :sym |
  50755.                 self intern: sym.
  50756.                 bar value: (count _ count + 1)]].
  50757.     ^ (oldCount - count) printString , ' reclaimed'! !
  50758.  
  50759. !Symbol class methodsFor: 'access'!
  50760. morePossibleSelectorsFor: misspelled
  50761.     "Like possible SelectorsFor, but over hunts over a greater range of selectors."
  50762.  
  50763.     | numArgs results tables skip |
  50764.     numArgs _ misspelled numArgs.
  50765.     numArgs < 0 ifTrue: [ ^ OrderedCollection new: 0 ].
  50766.     skip _ misspelled first asciiValue - $a asciiValue + 1.
  50767.     tables _ SelectorTables at: (numArgs + 1 min: SelectorTables size).
  50768.     1 to: tables size do: [ :index |
  50769.         index ~= skip ifTrue:
  50770.             [ results _ misspelled correctAgainst: (tables at: index)
  50771.                                 continuedFrom: results ] ].
  50772.     ^ misspelled correctAgainst: nil continuedFrom: results.
  50773. !
  50774. possibleSelectorsFor: misspelled
  50775.     "Answer an ordered collection of possible corrections for the misspelled selector in order of likelyhood."
  50776.  
  50777.     | numArgs table lookupString |
  50778.     lookupString _ misspelled asLowercase. "correct uppercase selectors to lowercase"
  50779.     numArgs _ lookupString numArgs.
  50780.     numArgs < 0 ifTrue: [ ^ OrderedCollection new: 0 ].
  50781.     table _ (SelectorTables at: (numArgs + 1 min: SelectorTables size))
  50782.                 at: (lookupString at: 1) asciiValue - "($a asciiValue - 1)" 96.
  50783.     ^ lookupString correctAgainst: table.!
  50784. selectorsContaining: aString
  50785.     "Answer a list of selectors that contain aString within them.  Case-insensitive.
  50786.      1/15/96 sw.  This is an extremely slow, sledge-hammer approach at present, taking around 30 seconds to execute on an FX.  A variety of speedups is conceivable -- improvements invited."
  50787.  
  50788.     | key size table candidate selectorList selectorTable |
  50789.  
  50790.     key _ aString asLowercase.
  50791.  
  50792.     selectorList _ OrderedCollection new.
  50793.     size _ key size.
  50794.  
  50795.     (SelectorTables size to: 1 by: -1) do:
  50796.         [:j | selectorTable _ SelectorTables at: j.
  50797.         1 to: 26 do: [:index |
  50798.         table _ selectorTable at: index.
  50799.         1 to: table size do: 
  50800.             [:t | 
  50801.             ((candidate _ table at: t) == nil) ifFalse:
  50802.                 [candidate size >= size ifTrue:
  50803.                     [((candidate asLowercase findString: key startingAt: 1) > 0)
  50804.                         ifTrue:
  50805.                             [selectorList add: candidate]]]]]].
  50806.     ^ selectorList
  50807.  
  50808.  
  50809. "Symbol selectorsContaining: 'scon' OrderedCollection (includesController: selectorsContaining: codeThisContext conversionNotesContents isControlWanted isControlActive isConstantNumber isConnectionSet thisContext )"!
  50810. thatStarts: leadingCharacters skipping: skipSym
  50811.     "Answer a selector symbol that starts with aKeyword and
  50812.         starts with a lower-case letter. Ignore case in aKeyword.
  50813.     If skipSym is not nil, it is a previous answer; start searching after it.
  50814.     If no symbols are found, answer nil.
  50815.     Used by Ctrl-s routines."
  50816.  
  50817.     | key size index table candidate i skip firstTable |
  50818.     key _ leadingCharacters asLowercase.
  50819.     ((index _ (key at: 1) asciiValue - "($a asciiValue - 1)" 96) between: 0 and: 25)
  50820.         ifFalse: [^nil].
  50821.     size _ key size.
  50822.     skip _ skipSym ~~ nil.
  50823.     firstTable _ skip
  50824.         ifTrue: [skipSym numArgs + 1 min: SelectorTables size] "can't be in a later table"
  50825.         ifFalse: [SelectorTables size]. "could be in any table; favor longer identifiers"
  50826.     (firstTable to: 1 by: -1) do:
  50827.         [:j |
  50828.         table _ (SelectorTables at: j) at: index.
  50829.         1 to: table size do: 
  50830.             [:t | 
  50831.             ((candidate _ table at: t) == nil or:
  50832.                     [skip and: [skip _ candidate ~~ skipSym. true]]) ifFalse:
  50833.                 [candidate size >= size ifTrue:
  50834.                     [i _ size. "test last character first"
  50835.                      [i > 1 and: [(candidate at: i) asLowercase == (key at: i)]]
  50836.                         whileTrue: [i _ i - 1].
  50837.                      i = 1 ifTrue: "don't need to compare first character"
  50838.                         [^candidate]]]]].
  50839.     ^nil
  50840.  
  50841. "Symbol thatStarts: 'sf' skipping: nil"
  50842. "Symbol thatStarts: 'sf' skipping: #sfpGetFile:with:with:with:with:with:with:with:with:"
  50843. "Symbol thatStarts: 'candidate' skipping: nil"
  50844. ! !
  50845.  
  50846. Symbol initialize!
  50847. StringHolder subclass: #SyntaxError
  50848.     instanceVariableNames: 'class selector category selectionIndex debugger '
  50849.     classVariableNames: ''
  50850.     poolDictionaries: ''
  50851.     category: 'Interface-Syntax Errors'!
  50852. SyntaxError comment:
  50853. 'I represent a report of a syntax error when reading class descriptions from a noninteractive source such as an external file. As a StringHolder, the string to be viewed is the code or expression containing the error.'!
  50854.  
  50855. !SyntaxError methodsFor: 'menu messages'!
  50856. proceed: aController 
  50857.     "The error has presumably been fixed and the file in that created the 
  50858.     syntax error can now be continued."
  50859.  
  50860.     | d |
  50861.     d _ debugger. debugger _ nil.  "break cycle"
  50862.     d proceed: aController!
  50863. spawn: aString 
  50864.     "Create and schedule a message browser on the message, aString. Any 
  50865.     edits already made are retained."
  50866.  
  50867.     self messageListIndex > 0
  50868.         ifTrue: 
  50869.             [^BrowserView
  50870.                 openMessageBrowserForClass: class
  50871.                 selector: selector
  50872.                 editString: aString]! !
  50873.  
  50874. !SyntaxError methodsFor: 'message list'!
  50875. list
  50876.     "Answer an array of one element made up of the class name, message 
  50877.     category, and message selector in which the syntax error was found. 
  50878.     This is the single item in the message list of a view/browser on the 
  50879.     receiver."
  50880.  
  50881.     ^Array with: class name , '  ' , category , '  ' , selector!
  50882. messageListIndex
  50883.     "Answer the current selection (there is only one) of the receiver's list."
  50884.  
  50885.     ^selectionIndex! !
  50886.  
  50887. !SyntaxError methodsFor: 'class list'!
  50888. selectedClass
  50889.     "Answer the class in which the syntax error occurred."
  50890.  
  50891.     ^class!
  50892. selectedClassOrMetaClass
  50893.     "Answer the class in which the syntax error occurred."
  50894.  
  50895.     ^class! !
  50896.  
  50897. !SyntaxError methodsFor: 'selecting'!
  50898. selectionIndex
  50899.     "Answer the current list selection."
  50900.  
  50901.     ^selectionIndex!
  50902. toggleIndex: anInteger 
  50903.     "Answer the receiver since only one item can be selected--thus 
  50904.     preventing deselection."
  50905.  
  50906.     ^self! !
  50907.  
  50908. !SyntaxError methodsFor: 'contents'!
  50909. category: aSymbol
  50910.     "Set the category so it will be known when the user correct the error and accepts. TK 15 May 96"
  50911.     category _ aSymbol!
  50912. contents: aString notifying: aController 
  50913.     "Compile the code in aString and notify aController of any errors. Answer 
  50914.     true if compilation succeeds, false otherwise."
  50915.  
  50916.     | selectedMessageName compiledSelector |
  50917.     selectedMessageName _ selector.
  50918.     compiledSelector _ class
  50919.                             compile: aString
  50920.                             classified: category
  50921.                             notifying: aController.
  50922.     compiledSelector == nil ifTrue: [^false].
  50923.     contents _ aString.
  50924.     ^true!
  50925. notify: error at: location in: source
  50926.     "Put up a SyntaxError window in the normal way.  And we know the category.  TK 15 May 96."
  50927.     "Open a standard system view whose model is an instance of me. The syntax error occurred in typing to add code, aString, to class, aClass. "
  50928.     | topView aListView aCodeView aClass aString |
  50929.     aClass _ thisContext sender receiver encoder classEncoding.
  50930.     aString _ (source contents
  50931.                             copyReplaceFrom: location
  50932.                             to: location - 1
  50933.                             with: error).
  50934.     self setClass: aClass
  50935.         code: aString
  50936.         debugger: (Debugger context: thisContext).
  50937.     self class open: self! !
  50938.  
  50939. !SyntaxError methodsFor: 'private'!
  50940. setClass: aClass code: aString debugger: aDebugger
  50941.  
  50942.     class _ aClass.
  50943.     debugger _ aDebugger.
  50944.     "the debugger is just for proceeding"
  50945.     selector _ aClass parserClass new parseSelector: aString.
  50946.     contents _ aString.
  50947.     category == nil ifTrue: [
  50948.         category _ aClass organization categoryOfElement: selector].
  50949.     category == nil ifTrue: [category _ ClassOrganizer default].
  50950.     selectionIndex _ 1! !
  50951. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  50952.  
  50953. SyntaxError class
  50954.     instanceVariableNames: ''!
  50955.  
  50956. !SyntaxError class methodsFor: 'instance creation'!
  50957. class: aClass code: aString debugger: aDebugger 
  50958.     "Answer an instance of me in which the code, aString, is to be added to 
  50959.     the class, aClass and should be debugged in the context of aDebugger."
  50960.  
  50961.     ^self new
  50962.         setClass: aClass
  50963.         code: aString
  50964.         debugger: aDebugger!
  50965. errorInClass: aClass withCode: aString 
  50966.     "Answer a standard system view whose model is an instance of me. The syntax error occurred in typing to add code, aString, to class, aClass. "
  50967.  
  50968.     | aSyntaxError |
  50969.     aSyntaxError _ self
  50970.                 class: aClass
  50971.                 code: aString
  50972.                 debugger: (Debugger context: thisContext).
  50973.     self open: aSyntaxError!
  50974. open: aSyntaxError
  50975.     "Answer a standard system view whose model is an instance of me.  TK 15 May 96"
  50976.     |  topView aListView aCodeView |
  50977.     topView _ StandardSystemView new.
  50978.     topView model: aSyntaxError.
  50979.     topView label: 'Syntax Error'.
  50980.     topView minimumSize: 180 @ 120.
  50981.     aListView _ SyntaxErrorListView new.
  50982.     aListView model: aSyntaxError.
  50983.     aListView window: (0 @ 0 extent: 180 @ 20).
  50984.     aListView
  50985.         borderWidthLeft: 2
  50986.         right: 2
  50987.         top: 2
  50988.         bottom: 0.
  50989.     topView addSubView: aListView.
  50990.     aCodeView _ BrowserCodeView new.
  50991.     aCodeView model: aSyntaxError.
  50992.     aCodeView window: (0 @ 0 extent: 180 @ 100).
  50993.     aCodeView
  50994.         borderWidthLeft: 2
  50995.         right: 2
  50996.         top: 2
  50997.         bottom: 2.
  50998.     topView
  50999.         addSubView: aCodeView
  51000.         align: aCodeView viewport topLeft
  51001.         with: aListView viewport bottomLeft.
  51002.     topView controller openNoTerminateDisplayAt: Display extent // 2.
  51003.     Processor activeProcess suspend! !BrowserListController subclass: #SyntaxErrorListController
  51004.     instanceVariableNames: ''
  51005.     classVariableNames: 'SyntaxErrorListYellowButtonMessages SyntaxErrorListYellowButtonMenu '
  51006.     poolDictionaries: ''
  51007.     category: 'Interface-Syntax Errors'!
  51008. SyntaxErrorListController comment:
  51009. 'I am a kind of LockedListController that creates a yellow button menu for proceeding with reading an external file once the user has completed editing the syntax error being viewed.'!
  51010.  
  51011. !SyntaxErrorListController methodsFor: 'initialize-release'!
  51012. initialize
  51013.  
  51014.     super initialize.
  51015.     self initializeYellowButtonMenu! !
  51016.  
  51017. !SyntaxErrorListController methodsFor: 'menu messages'!
  51018. proceed
  51019.     "The user has completed editing the model of the receiver and evaluating 
  51020.     in the context in which the syntax error interrupt should now continue."
  51021.  
  51022.     self controlTerminate.
  51023.     model proceed: view topView controller.
  51024.     self controlInitialize! !
  51025.  
  51026. !SyntaxErrorListController methodsFor: 'private'!
  51027. changeModelSelection: anInteger
  51028.     !
  51029. initializeYellowButtonMenu
  51030.  
  51031.     self yellowButtonMenu: SyntaxErrorListYellowButtonMenu
  51032.         yellowButtonMessages: SyntaxErrorListYellowButtonMessages! !
  51033. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  51034.  
  51035. SyntaxErrorListController class
  51036.     instanceVariableNames: ''!
  51037.  
  51038. !SyntaxErrorListController class methodsFor: 'class initialization'!
  51039. initialize
  51040.  
  51041.     SyntaxErrorListYellowButtonMenu _ PopUpMenu labels: 'proceed'.
  51042.     SyntaxErrorListYellowButtonMessages _ #(proceed )
  51043.  
  51044.     "SyntaxErrorListController initialize"! !
  51045.  
  51046. SyntaxErrorListController initialize!
  51047. ListView subclass: #SyntaxErrorListView
  51048.     instanceVariableNames: ''
  51049.     classVariableNames: ''
  51050.     poolDictionaries: ''
  51051.     category: 'Interface-Syntax Errors'!
  51052. SyntaxErrorListView comment:
  51053. 'I am a ListView with a single item, the method or expression that created a syntax error when an attempt was made to read it from an external file. SyntaxErrorListController is my default controller.'!
  51054.  
  51055. !SyntaxErrorListView methodsFor: 'model access'!
  51056. model: aSyntaxError
  51057.  
  51058.     super model: aSyntaxError.
  51059.     self list: model list.
  51060.     selection _ model selectionIndex! !
  51061.  
  51062. !SyntaxErrorListView methodsFor: 'controller access'!
  51063. defaultControllerClass
  51064.  
  51065.     ^SyntaxErrorListController! !Object subclass: #SystemBuilder
  51066.     instanceVariableNames: ''
  51067.     classVariableNames: 'BuildingSystem '
  51068.     poolDictionaries: ''
  51069.     category: 'System-Support'!
  51070. SystemBuilder comment:
  51071. 'This class holds code used to create build files for the system, and actually to build the system.  1/18/96 sw'!
  51072.  
  51073. !SystemBuilder methodsFor: 'no messages'! !
  51074. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  51075.  
  51076. SystemBuilder class
  51077.     instanceVariableNames: ''!
  51078.  
  51079. !SystemBuilder class methodsFor: 'creating build files'!
  51080. classCategoriesStartingWith: aPrefix
  51081.     "Answer a list of system class categories beginning with the given prefix.  1/18/96 sw"
  51082.  
  51083.     "SystemBuilder classCategoriesStartingWith: 'Files'"
  51084.  
  51085.     ^ SystemOrganization categories select:
  51086.         [:aCat | (aCat asString findString:  aPrefix startingAt: 1) = 1]!
  51087. createBuildFiles 
  51088.  "SystemBuilder createBuildFiles" 
  51089.     "2/7/96 sw: no builds having yet been undertaken for our new kernel yet, this serves as a placeholder.  carried forward in this method is some old code from macpal building, for future reference...
  51090.     2/91:  You must invoke this method from within a project that bears as its change-set all the changes in the system other than code residing in classes in the MacPal categories--otherewise the build files created will not be right.  It does no harm to have changes relating to MacPal categories in the current changeset also, since these are stripped from it as part of the process.  8/91:  Probably will now work fine with whatever changeset you have current; it will leave that current changeset holding all the non-pal changes.  This is the hypothesis, anyway...
  51091.     self assimilateGenericChanges.
  51092.     self fileOutMacPalWithSuffix: ('.', 'xxx')
  51093.  
  51094. createRootBuildNodeWithSuffix: suffix 
  51095.     |  stream |
  51096.     stream _ (FileStream fileNamed: 'MacPal-FileIn', suffix).
  51097.  
  51098.     stream nextPutAll:
  51099. '
  51100.     (FileStream oldFileNamed: ''MacPal-Changes', suffix, ''') fileIn.'.
  51101.  
  51102.     self macPalCategories do:
  51103.         [:catName | 
  51104.             stream cr; tab; nextPutAll: '(FileStream oldFileNamed: '''.
  51105.             stream nextPutAll: catName.
  51106.             stream nextPutAll:  suffix, ''') fileIn.'].
  51107.  
  51108.     stream nextPutAll: '
  51109.  
  51110.     (Smalltalk at: #MacPalBuilder) perform: #finalSystemBuildingSteps
  51111. '; shorten; close
  51112.  
  51113. fileOutMacPalWithSuffix:  suffix 
  51114.     MacPalBuilder fileOutMacPalWithSuffix: 'MP'
  51115.     You must invoke this method from within a project that bears as its change-set all the changes in the system other than code residing in classes in the MacPal categories--otherwise the build files created will not be right
  51116.     self macPalCategories do:
  51117.         [:cat |
  51118.         SystemOrganization fileOutCategory: cat withSuffix: suffix.
  51119.         (SystemOrganization superclassOrder: cat)
  51120.             do: [:class | class removeFromChanges]].
  51121.  
  51122.     (FileStream fileNamed: 'MacPal-Changes', suffix) fileOutChanges.
  51123.  
  51124.     self createRootBuildNodeWithSuffix: suffix
  51125.  
  51126. initialize
  51127.     BuildingSystem _ true
  51128.  
  51129. macPalCategories
  51130.     MacPal macPalCategories
  51131.     NB - all class categories starting with the word MacPal are used
  51132.     ^ SystemOrganization categories select:
  51133.         [:aCat | (aCat asString findString:  'MacPal' startingAt: 1) = 1]
  51134.  
  51135. rootProjectInfo
  51136.  
  51137. You have managed to enter the Non-MacPal-Changes project, perhaps in error!! 
  51138.  
  51139. Choose 'enter' in the menu to the left to re-enter the main desktop project.  
  51140.  
  51141. DO NOT request a ST noChanges when you can see this window!!
  51142.  
  51143. This project holds the incoming changes to non-MacPal classes in this version of the MacPal image.
  51144.  
  51145. It also serves as the project from within which build files are created for the next build.    For this, you need to file in, while in this project, all the non-MacPal changes that have arisen since the incoming baseline image was built, even if they are already in the current image.
  51146.  
  51147. MacPalBuilder createBuildFiles."! !
  51148.  
  51149. !SystemBuilder class methodsFor: 'system building'!
  51150. buildingSystem
  51151.     "Should be true only during system building.  1/18/96 sw"
  51152.  
  51153.     BuildingSystem isNil ifTrue: [BuildingSystem _ false].
  51154.     ^ BuildingSystem!
  51155. buildingSystem: aBoolean
  51156.     "Should be true only during system building; used to suppress certain behavior that would be damaging during system building.  1/18/96 sw"
  51157.  
  51158.     BuildingSystem _ aBoolean!
  51159. finalSystemBuildingSteps
  51160.     "The final steps after all the file-ins, before we can call the system built.  1/18/96 sw"
  51161.  
  51162.     self reinitialize.
  51163.     self removeMacAppClassesFromSystem.
  51164.     Symbol rehash.     " Reclaim unused symbols"
  51165.     self showInTranscript: '** System Built **'.
  51166.     BuildingSystem _ false.!
  51167. gatherAllChangesExceptSystemChangesIntoCurrentChangeSet
  51168.     "Gather together into the current changeSet all the changes in all change sets except for the one named 'System Changes'.  1/22/96 sw"
  51169.  
  51170.     | currentChanges systemChanges |
  51171.     self flag: #scottPrivate.
  51172.     currentChanges _ Smalltalk changes.
  51173.     systemChanges _ ChangeSorter changeSetNamed: 'System Changes'.
  51174.     ChangeSet allInstancesDo:
  51175.         [:aChangeSet | ((aChangeSet ~~ currentChanges) and:
  51176.             [aChangeSet ~~ systemChanges])
  51177.                 ifTrue:
  51178.                     [currentChanges assimilateAllChangesFoundIn: aChangeSet.
  51179.                     Transcript cr; show: 'Changes in ', aChangeSet name, ' copied.']]
  51180.  
  51181. "SystemBuilder gatherAllChangesExceptSystemChangesIntoCurrentChangeSet"!
  51182. initializeAfterSystemBuild
  51183.     "Reinitialize needs to be called manually after filing in the kernel because other support classes need to have been filed in before it can run successfully.  This method copied over from old macPal stuff, 1/27/96 sw, to serve as a template, but the real work needs to be done still."
  51184.  
  51185.     Text initTextConstants.
  51186.     
  51187.     "Rebuild snapshot lists"
  51188.  
  51189.     self showInTranscript: '** SystemBuilder reinitialize  **'.
  51190.     self initMenus!
  51191. removeMacAppClassesFromSystem
  51192.     "Remove all those undesired MacApp classes from the image.  1/18/96 sw"
  51193.  
  51194.     "SystemBuilder removeMacAppClassesFromSystem"
  51195.  
  51196.     (self classCategoriesStartingWith: 'MacApp') do:
  51197.         [:aCategory |
  51198.             SystemOrganization removeSystemCategory: aCategory]! !BrowserListController subclass: #SystemCategoryListController
  51199.     instanceVariableNames: ''
  51200.     classVariableNames: 'SystemCategoryListYellowButtonMenu SystemCategoryListYellowButtonMessages '
  51201.     poolDictionaries: ''
  51202.     category: 'Interface-Browser'!
  51203. SystemCategoryListController comment:
  51204. 'I am a kind of LockedListController that creates a yellow button menu so that messages can be sent to the list selection (a class category) to:
  51205.     browse    create a system category browser
  51206.     edit    print the class categories
  51207.     update    make certain that the view has the correct list of system categories
  51208.     fileOut    print a description of all the classes in the category on an external file'!
  51209.  
  51210. !SystemCategoryListController methodsFor: 'initialize-release'!
  51211. initialize
  51212.  
  51213.     super initialize.
  51214.     self initializeYellowButtonMenu! !
  51215.  
  51216. !SystemCategoryListController methodsFor: 'menu messages'!
  51217. add
  51218.     "Add a system category"
  51219.     self controlTerminate.
  51220.     model addSystemCategory.
  51221.     self controlInitialize!
  51222. browse
  51223.     "Create and schedule a system category browser on the selected category 
  51224.     of classes."
  51225.  
  51226.     self controlTerminate.
  51227.     model buildSystemCategoryBrowser.
  51228.     self controlInitialize!
  51229. classNotFound
  51230.     view flash.
  51231.     self controlInitialize!
  51232. edit
  51233.     "Present the categories of system classes so that the user can view and 
  51234.     edit them."
  51235.  
  51236.     view singleItemMode ifTrue: [^view flash].
  51237.     self controlTerminate.
  51238.     model editSystemCategories.
  51239.     self controlInitialize!
  51240. fileOut
  51241.     "Print a description of the classes in the selected system category onto an 
  51242.     external file."
  51243.  
  51244.     self controlTerminate.
  51245.     Cursor write showWhile:
  51246.         [model fileOutSystemCategories].
  51247.     self controlInitialize!
  51248. findClass
  51249.     "modified 4/29/96 sw so that if only 1 class matches the user-supplied string, or if the user-supplied string exactly matches a class name, then the pop-up menu is bypassed"
  51250.     | pattern foundClass classNames index reply |
  51251.     self controlTerminate.
  51252.     model okToChange ifFalse: [^ self classNotFound].
  51253.     pattern _ (reply _ FillInTheBlank request: 'Class Name?') asLowercase.
  51254.     pattern isEmpty ifTrue: [^ self classNotFound].
  51255.     (Smalltalk hasClassNamed: reply)
  51256.         ifTrue:
  51257.             [foundClass _ Smalltalk at: reply asSymbol]
  51258.         ifFalse:
  51259.              [classNames _ Smalltalk classNames asArray select: 
  51260.                 [:n | (n asLowercase indexOfSubCollection: pattern startingAt: 1) > 0].
  51261.             classNames isEmpty ifTrue: [^ self classNotFound].
  51262.             index _ classNames size == 1
  51263.                 ifTrue:    [1]
  51264.                 ifFalse:    [(PopUpMenu labelArray: classNames lines: #()) startUp].
  51265.             index = 0 ifTrue: [^ self classNotFound].
  51266.             foundClass _ Smalltalk at: (classNames at: index)].
  51267.      model systemCategoryListIndex: (model systemCategoryList indexOf: foundClass category).
  51268.     model classListIndex: (model classList indexOf: foundClass name). 
  51269.     self controlInitialize!
  51270. printOut
  51271.     "Make a file with the description of the classes in the selected category.
  51272.     Defaults to the same file as fileOut, but could be changed in any given
  51273.     implementation to have a prettier format."
  51274.  
  51275.     self fileOut!
  51276. remove
  51277.     "remove the classes in the selected system category"
  51278.  
  51279.     self controlTerminate.
  51280.     model removeSystemCategory.
  51281.     self controlInitialize!
  51282. rename
  51283.     "Rename the selected system category"
  51284.     self controlTerminate.
  51285.     model renameSystemCategory.
  51286.     self controlInitialize!
  51287. update
  51288.     "The SystemOrganization has been changed from a source outside the 
  51289.     browser to which the receiver refers. The receiver's organization must be 
  51290.     updated."
  51291.  
  51292.     self controlTerminate.
  51293.     model updateSystemCategories.
  51294.     self controlInitialize! !
  51295.  
  51296. !SystemCategoryListController methodsFor: 'private'!
  51297. changeModelSelection: anInteger
  51298.     model toggleSystemCategoryListIndex: anInteger!
  51299. initializeYellowButtonMenu
  51300.  
  51301.     self yellowButtonMenu: SystemCategoryListYellowButtonMenu 
  51302.         yellowButtonMessages: SystemCategoryListYellowButtonMessages ! !
  51303. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  51304.  
  51305. SystemCategoryListController class
  51306.     instanceVariableNames: ''!
  51307.  
  51308. !SystemCategoryListController class methodsFor: 'class initialization'!
  51309. initialize
  51310.     "SystemCategoryListController initialize"
  51311.     SystemCategoryListYellowButtonMenu _ 
  51312.         PopUpMenu 
  51313.             labels:
  51314. 'find class...
  51315. browse
  51316. printOut
  51317. fileOut
  51318. reorganize
  51319. update
  51320. add item...
  51321. rename...
  51322. remove' 
  51323.             lines: #(1 3 6).
  51324.     SystemCategoryListYellowButtonMessages _
  51325.         #(findClass browse printOut fileOut
  51326.         edit update
  51327.         add rename remove )
  51328.     "
  51329.     SystemCategoryListController initialize.
  51330.     SystemCategoryListController allInstancesDo:
  51331.         [:x | x initializeYellowButtonMenu]
  51332.     "! !
  51333.  
  51334. SystemCategoryListController initialize!
  51335. BrowserListView subclass: #SystemCategoryListView
  51336.     instanceVariableNames: ''
  51337.     classVariableNames: ''
  51338.     poolDictionaries: ''
  51339.     category: 'Interface-Browser'!
  51340. SystemCategoryListView comment:
  51341. 'I am a BrowserListView whose items are the categories of classes in the Browser I view. SystemCategoryListController is my default controller.'!
  51342.  
  51343. !SystemCategoryListView methodsFor: 'updating'!
  51344. getList 
  51345.     "Refer to the comment in BrowserListView|getList."
  51346.  
  51347.     | selectedSystemCategoryName |
  51348.     singleItemMode
  51349.         ifTrue: 
  51350.             [selectedSystemCategoryName _ model selectedSystemCategoryName.
  51351.             selectedSystemCategoryName == nil 
  51352.                 ifTrue: [selectedSystemCategoryName _ '    '].
  51353.             ^Array with: selectedSystemCategoryName asSymbol]
  51354.         ifFalse: [^model systemCategoryList]!
  51355. update: aSymbol
  51356.  
  51357.     aSymbol == #systemCategorySelectionChanged
  51358.         ifTrue: [self updateSystemCategorySelection. ^self].
  51359.     aSymbol == #systemCategoriesChanged
  51360.         ifTrue: [self updateSystemCategoryList. ^self]!
  51361. updateSystemCategoryList
  51362.  
  51363.     singleItemMode ifFalse: [self getListAndDisplayView]!
  51364. updateSystemCategorySelection
  51365.  
  51366.     singleItemMode
  51367.         ifTrue: [self getListAndDisplayView]
  51368.         ifFalse: [self moveSelectionBox: model systemCategoryListIndex]! !
  51369.  
  51370. !SystemCategoryListView methodsFor: 'controller access'!
  51371. defaultControllerClass
  51372.  
  51373.     ^SystemCategoryListController! !Dictionary subclass: #SystemDictionary
  51374.     instanceVariableNames: ''
  51375.     classVariableNames: 'SystemChanges LastQuitLogPosition CachedClassNames LowSpaceProcess LowSpaceSemaphore SpecialSelectors '
  51376.     poolDictionaries: ''
  51377.     category: 'System-Support'!
  51378. NewSystemDictionary comment:
  51379. 'I represent a special dictionary that supports protocol for asking questions about the structure of the system. My only instance is Smalltalk whose entries are the global system variables, such as the classes and:
  51380.     Disk -- a FileDirectory
  51381.     Sensor -- an InputSensor
  51382.     Display -- a DisplayScreen
  51383.     StandardSystemControllers -- a ControlManager
  51384.     Transcript -- a TextCollector
  51385.     Processor -- a ProcessorScheduler 
  51386.     SourceFiles -- Array of FileStreams
  51387.     SystemOrganization -- a SystemOrganizer
  51388.     Mac -- an object used to make calls on the Mac Toolbox
  51389.     StartUpList -- an OrderedCollection of objects with a method called StartUp that is called when                     Smalltalk starts up
  51390.     StartUpList -- an OrderedCollection of objects with a method called ShutDown that is called when                     Smalltalk shuts down'!
  51391.  
  51392. !SystemDictionary methodsFor: 'dictionary access'!
  51393. at: aKey put: anObject 
  51394.     "Override from Dictionary to check Undeclared and fix up
  51395.     references to undeclared variables."
  51396.     | index element |
  51397.     (self includesKey: aKey) ifFalse: 
  51398.         [self declare: aKey from: Undeclared.
  51399.         self flushClassNameCache].
  51400.     super at: aKey put: anObject.
  51401.     ^ anObject!
  51402. printOn: aStream
  51403.  
  51404.     aStream nextPutAll: 'a SystemDictionary'.
  51405.     (self == Smalltalk)
  51406.         ifTrue: [ aStream nextPutAll: ' (all the globals)' ].
  51407. ! !
  51408.  
  51409. !SystemDictionary methodsFor: 'browsing'!
  51410. browseAllCallsOn: aLiteral 
  51411.     "Create and schedule a message browser on each method that refers to
  51412.     aLiteral. For example, Smalltalk browseAllCallsOn: #open:label:."
  51413.     (aLiteral isKindOf: LookupKey)
  51414.         ifTrue: [self browseMessageList: (self allCallsOn: aLiteral) asSortedCollection
  51415.                     name: 'Users of ' , aLiteral key
  51416.                     autoSelect: aLiteral key]
  51417.         ifFalse: [self browseMessageList: (self allCallsOn: aLiteral) asSortedCollection
  51418.                     name: 'Senders of ' , aLiteral
  51419.                     autoSelect: aLiteral keywords first]!
  51420. browseAllCallsOn: literal1 and: literal2 
  51421.     "Create and schedule a message browser on each method that calls on the 
  51422.     two Symbols, literal1 and literal2. For example, Smalltalk 
  51423.     browseAllCallsOn: #at: and: #at:put:."
  51424.  
  51425.     ^self 
  51426.         browseMessageList: (self allCallsOn: literal1 and: literal2)
  51427.         name: literal1 printString , ' -and- ' , literal2 printString!
  51428. browseAllImplementorsOf: selector
  51429.     "Create and schedule a message browser on each method that implements 
  51430.     the message whose selector is the argument, selector. For example, 
  51431.     Smalltalk browseAllImplementorsOf: #at:put:."
  51432.  
  51433.     ^self browseMessageList: (self allImplementorsOf: selector) name: 'Implementors of ' , selector!
  51434. browseAllImplementorsOfList: selectorList
  51435.     "Create and schedule a message browser on each method that implements 
  51436.     the message whose selector is in the argument selectorList. For example, 
  51437.     Smalltalk browseAllImplementorsOf: #(at:put: size).
  51438.     1/16/96 sw: defer to the titled version"
  51439.  
  51440.     self browseAllImplementorsOfList: selectorList title: 'Implementors of all'!
  51441. browseAllImplementorsOfList: selectorList title: aTitle
  51442.     "Create and schedule a message browser on each method that implements the message whose selector is in the argument selectorList. For example,  Smalltalk browseAllImplementorsOf: #(at:put: size).
  51443.     1/16/96 sw: this variant adds the title argument.
  51444.     1/24/96 sw: use a SortedCollection
  51445.     2/1/96 sw: show normal cursor"
  51446.  
  51447.     | implementorLists flattenedList |
  51448.  
  51449.     implementorLists _ selectorList collect: [:each | self allImplementorsOf: each].
  51450.     flattenedList _ SortedCollection new.
  51451.     implementorLists do: [:each | flattenedList addAll: each].
  51452.     Cursor normal show.
  51453.     ^ self browseMessageList: flattenedList name: aTitle!
  51454. browseAllMethodsInCategory: category 
  51455.     ^self browseMessageList: (self allMethodsInCategory: category)
  51456.         name: category!
  51457. browseAllSelect: aBlock
  51458.     "Create and schedule a message browser on each method that, when used 
  51459.     as the block argument to aBlock gives a true result. For example, 
  51460.     Smalltalk browseAllSelect: [:method | method numLiterals > 10]."
  51461.  
  51462.     ^self browseMessageList: (self allSelect: aBlock) name: 'selected messages'!
  51463. browseAllUnimplementedCalls
  51464.     "Create and schedule a message browser on each method that includes a 
  51465.     message that is not implemented in any object in the system."
  51466.  
  51467.     ^self browseMessageList: self allUnimplementedCalls name: 'Unimplemented calls'!
  51468. browseAllUnSentMessages
  51469.     "Create and schedule a message browser on each method whose message is 
  51470.     not sent in any method in the system."
  51471.  
  51472.     ^self browseMessageList: self allUnSentMessages name: 'UnSent Messages'!
  51473. browseChangedMessages
  51474.     "Create and schedule a message browser on each method that has been 
  51475.     changed."
  51476.  
  51477.     ^self 
  51478.         browseMessageList: SystemChanges changedMessageListAugmented 
  51479.         name: 'Changed Messages'!
  51480. browseChangesAndAdditions
  51481.     "Create and schedule a message browser on each method that has been changed, as well as on any method belonging to an added class.  1/18/96 sw"
  51482.  
  51483.     "Smalltalk browseChangesAndAdditions"
  51484.     ^ self 
  51485.         browseMessageList: SystemChanges changedMessageList asArray, SystemChanges allMessagesForAddedClasses asArray
  51486.         name: 'New and Changed Methods'!
  51487. browseMessageList: messageList name: label 
  51488.     "Create and schedule a MessageSet browser on messageList."
  51489.     ^ self browseMessageList: messageList name: label autoSelect: nil!
  51490. browseMessageList: messageList name: labelString autoSelect: autoSelectString
  51491.     "Create and schedule a MessageSet browser on the  message list.
  51492.     1/22/96 sw: add message count to title.
  51493.     1/24/96 sw: don't put the msg count in 'there-are-no' msg"
  51494.     messageList size = 0 ifTrue: 
  51495.         [^ (PopUpMenu labels: ' OK ')
  51496.                 startUpWithCaption: 'There are no
  51497. ' , labelString].
  51498.  
  51499.     MessageSet openMessageList: messageList name: (labelString, ' [', messageList size printString, ']') autoSelect: autoSelectString!
  51500. browseMethodsWhoseNamesContain: aString
  51501.     "Launch a browser on all methods whose names contain the given string; case-insensitive.  This takes a long time right now.  1/16/96 sw"
  51502.  
  51503.     | aList |
  51504.     aList _ Symbol selectorsContaining: aString.
  51505.     aList size > 0 ifTrue: 
  51506.         [self browseAllImplementorsOfList: aList asSortedCollection title: 'Methods whose names contain ''', aString, '''']!
  51507. browseMethodsWithSourceString: aString
  51508.     "Smalltalk browseMethodsWithSourceString: 'SourceString' "
  51509.     "Launch a browser on all methods whose source code contains aString as a substring.  The search is case-sensitive. This takes a long time right now.  7/23/96 di"
  51510.     ^ self browseMessageList: (self allMethodsWithSourceString: aString)
  51511.         name: 'Methods containing ' , aString printString!
  51512. browseMethodsWithString: aString
  51513.     "Launch a browser on all methods which contain string literals that have aString as a substring.  The search is case-sensitive. This takes a long time right now.  2/1/96 sw"
  51514.  
  51515.     | aList |
  51516.     aList _ self allMethodsWithString: aString.
  51517.     aList size > 0 ifTrue: 
  51518.         [Cursor normal show.
  51519.         self browseMessageList: aList  name: 'Methods with string ''', aString, '''']!
  51520. browseObsoleteReferences   "Smalltalk browseObsoleteReferences"
  51521.     | references |
  51522.     references _ OrderedCollection new.
  51523.     (Association allInstances select:
  51524.         [:x | ((x value isKindOf: Behavior) and: ['AnOb*' match: x value name]) or:
  51525.         ['AnOb*' match: x value class name]]) 
  51526.         do: [:x | references addAll: (Smalltalk allCallsOn: x)].
  51527.     Smalltalk browseMessageList: references name: 'References to Obsolete Classes'!
  51528. implementorsOf: aSelector
  51529.     self browseAllImplementorsOf: aSelector!
  51530. referencesTo: aSymbol
  51531.     "open a browser on all references in the system to the global symbol passed in.  SW 8/91"
  51532.     "Smalltalk referencesTo: #DebuggingFlags"
  51533.     self browseAllCallsOn: (self associationAt: aSymbol)!
  51534. sendersOf: aSelector
  51535.     self browseAllCallsOn: aSelector!
  51536. showMenuThenBrowse: selectorCollection
  51537.     "Show a menu of the given selectors, abbreviated to 40 characters.
  51538.     Create and schedule a message set browser of all implementors of the 
  51539.     message chosen. Do nothing if no message is chosen."
  51540.  
  51541.     | aStream menu index |
  51542.     selectorCollection isEmpty ifTrue: [^Transcript cr; show: 'No messages sent.'].
  51543.     aStream _ WriteStream on: (String new: 200).
  51544.     selectorCollection do:
  51545.         [:sel | aStream nextPutAll: (sel contractTo: 40); cr].
  51546.     aStream skip: -1.
  51547.     index _ (PopUpMenu labels: aStream contents) startUp.
  51548.     index > 0 ifTrue: [Smalltalk browseAllImplementorsOf: (selectorCollection at: index)]!
  51549. showMenuThenBrowseSendersOf: selectorCollection
  51550.     "Show a menu of the given selectors, abbreviated to 40 characters.
  51551.     Create and schedule a message set browser of all senders of the 
  51552.     message chosen. Do nothing if no message is chosen."
  51553.  
  51554.     | aStream menu index |
  51555.     selectorCollection isEmpty ifTrue: [^Transcript cr; show: 'No messages sent.'].
  51556.     aStream _ WriteStream on: (String new: 200).
  51557.     selectorCollection do:
  51558.         [:sel | aStream nextPutAll: (sel contractTo: 40); cr].
  51559.     aStream skip: -1.
  51560.     index _ (PopUpMenu labels: aStream contents) startUp.
  51561.     index > 0 ifTrue: [Smalltalk browseAllCallsOn: (selectorCollection at: index)]! !
  51562.  
  51563. !SystemDictionary methodsFor: 'retrieving'!
  51564. allBehaviorsDo: aBlock 
  51565.     "Evaluate the argument, aBlock, for each kind of Behavior in the system 
  51566.     (that is, Object and its subclasses)."
  51567.  
  51568.     aBlock value: Object.
  51569.     Object allSubclassesDo: aBlock!
  51570. allCallsOn: aLiteral 
  51571.     "Answer a Collection of all the methods that call on aLiteral."
  51572.     | aCollection special methods |
  51573.     aCollection _ OrderedCollection new.
  51574.     special _ self hasSpecialSelector: aLiteral ifTrueSetByte: [:byte ].
  51575.     Cursor wait showWhile: 
  51576.         [self allBehaviorsDo: 
  51577.             [:class |
  51578.              (class whichSelectorsReferTo: aLiteral special: special byte: byte) do: 
  51579.                 [:sel | sel ~~ #DoIt
  51580.                     ifTrue: [aCollection add: class name , ' ' , sel]]]].
  51581.     ^aCollection!
  51582. allCallsOn: firstLiteral and: secondLiteral
  51583.     "Answer a SortedCollection of all the methods that call on both aLiteral 
  51584.     and secondLiteral."
  51585.  
  51586.     | aCollection secondArray firstSpecial secondSpecial |
  51587.     aCollection _ SortedCollection new.
  51588.     firstSpecial _ self hasSpecialSelector: firstLiteral ifTrueSetByte: [:firstByte].
  51589.     secondSpecial _ self hasSpecialSelector: secondLiteral ifTrueSetByte: [:secondByte].
  51590.     Cursor wait showWhile:
  51591.         [self allBehaviorsDo:
  51592.             [:class |
  51593.             secondArray _ class whichSelectorsReferTo: secondLiteral special: secondSpecial byte: secondByte.
  51594.             ((class whichSelectorsReferTo: firstLiteral special: firstSpecial byte: firstByte) select:
  51595.                 [:aSel | (secondArray includes: aSel)]) do:
  51596.                         [:sel | aCollection add: class name , ' ' , sel]]].
  51597.     ^aCollection!
  51598. allClasses  "Smalltalk allClasses"
  51599.     ^ self classNames collect: [:name | Smalltalk at: name]!
  51600. allClassesDo: aBlock
  51601.     "Evaluate the argument, aBlock, for each class in the system."
  51602.  
  51603.     (self classNames collect: [:name | Smalltalk at: name]) do: aBlock!
  51604. allClassesImplementing: aSelector  
  51605.     "Answer an Array of all classes that implement the message aSelector."
  51606.  
  51607.     | aCollection |
  51608.     aCollection _ ReadWriteStream on: Array new.
  51609.     self allBehaviorsDo:
  51610.         [:class | (class includesSelector: aSelector)
  51611.             ifTrue: [aCollection nextPut: class]].
  51612.     ^ aCollection contents!
  51613. allImplementedMessages
  51614.     "Answer a Set of all the messages that are sent by a method in the system 
  51615.     but are not implemented."
  51616.  
  51617.     | aSet |
  51618.     aSet _ Set new: Symbol instanceCount * 2.
  51619.     Cursor wait showWhile: 
  51620.         [self allBehaviorsDo: [:cl | cl selectorsDo: [:aSelector | aSet add: aSelector]]].
  51621.     ^aSet!
  51622. allImplementorsOf: aSelector  
  51623.     "Answer a SortedCollection of all the methods that implement the message 
  51624.     aSelector."
  51625.  
  51626.     | aCollection |
  51627.     aCollection _ SortedCollection new.
  51628.     Cursor wait showWhile:
  51629.         [self allBehaviorsDo:
  51630.             [:class |
  51631.             (class includesSelector: aSelector)
  51632.                 ifTrue: [aCollection add: class name, ' ', aSelector]]].
  51633.     ^aCollection!
  51634. allMethodsInCategory: category 
  51635.     | aCollection |
  51636.     aCollection _ SortedCollection new.
  51637.     Cursor wait showWhile:
  51638.         [self allBehaviorsDo:
  51639.             [:x | (x organization listAtCategoryNamed: category) do:
  51640.                 [:sel | aCollection add: x name , ' ' , sel]]].
  51641.     ^aCollection!
  51642. allMethodsWithSourceString: aString 
  51643.     "Answer a SortedCollection of all the methods that contain, in source code, aString as a substring.  The search is case-sensitive.  7/23/96 di."
  51644.     | list classCount |
  51645.     list _ Set new.
  51646. 'Searching all source code...'
  51647. displayProgressAt: Sensor cursorPoint
  51648. from: 0 to: Smalltalk classNames size
  51649. during:
  51650.     [:bar | classCount _ 0.
  51651.     Smalltalk allClassesDo:
  51652.         [:class | bar value: (classCount _ classCount + 1).
  51653.         (Array with: class with: class class) do:
  51654.             [:cl | cl selectorsDo:
  51655.                 [:sel | 
  51656.                 ((cl sourceCodeAt: sel) findString: aString startingAt: 1) > 0
  51657.                     ifTrue:
  51658.                     [sel == #DoIt ifFalse: [list add: cl name , ' ' , sel]]]]]].
  51659.     ^ list asSortedCollection!
  51660. allMethodsWithString: aString 
  51661.     "Answer a SortedCollection of all the methods that contain, in a string literal, aString as a substring.  2/1/96 sw.  The search is case-sensitive, and does not dive into complex literals, confining itself to string constants.
  51662.     5/2/96 sw: fixed so that duplicate occurrences of aString in the same method don't result in duplicated entries in the browser"
  51663.  
  51664.     | aStringSize list lits |
  51665.  
  51666.     aStringSize _ aString size.
  51667.     list _ Set new.
  51668.  
  51669.     Cursor wait showWhile: [self allBehaviorsDo: 
  51670.         [:class | class selectorsDo:
  51671.             [:sel | sel ~~ #DoIt ifTrue:
  51672.                 [lits _ (class compiledMethodAt: sel) literals.
  51673.                 lits do:
  51674.                     [:aLiteral | ((aLiteral isMemberOf: String) and:
  51675.                         [aLiteral size >= aStringSize])
  51676.                             ifTrue:
  51677.                                 [(aLiteral findString: aString startingAt: 1)  > 0 ifTrue:
  51678.                                     [list add: class name , ' ' , sel]]]]]]].
  51679.     ^ list asSortedCollection!
  51680. allObjectsDo: aBlock 
  51681.     "Evaluate the argument, aBlock, for each object in the system
  51682.      excluding SmallIntegers."
  51683.  
  51684.     | object |
  51685.     object _ self someObject.
  51686.     [0 == object] whileFalse: [
  51687.         aBlock value: object.
  51688.         object _ object nextObject.
  51689.     ].!
  51690. allPrimitiveMessages
  51691.     "Answer an OrderedCollection of all the methods that are implemented by 
  51692.     primitives."
  51693.  
  51694.     | aColl aSelector method | 
  51695.     aColl _ OrderedCollection new: 200.
  51696.     Cursor execute showWhile: 
  51697.         [self allBehaviorsDo: 
  51698.             [:class | class selectorsDo: 
  51699.                 [:sel | 
  51700.                 method _ class compiledMethodAt: sel.
  51701.                 method primitive ~= 0
  51702.                     ifTrue: [aColl addLast: class name , ' ' , sel 
  51703.                                     , ' ' , method primitive printString]]]].
  51704.     ^aColl!
  51705. allPrimitiveMethodsInCategories: aList
  51706.     "Answer an OrderedCollection of all the methods that are implemented by primitives in the given categories.  1/26/96 sw"
  51707.  
  51708.     | aColl aSelector method | 
  51709.     aColl _ OrderedCollection new: 200.
  51710.     Cursor execute showWhile: 
  51711.         [self allBehaviorsDo: 
  51712.             [:aClass | (aList includes: (SystemOrganization categoryOfElement: aClass theNonMetaClass name asString) asString)
  51713.                 ifTrue: [aClass selectorsDo: 
  51714.                     [:sel | 
  51715.                         method _ aClass compiledMethodAt: sel.
  51716.                         method primitive ~= 0
  51717.                             ifTrue: [aColl addLast: aClass name , ' ' , sel 
  51718.                                     , ' ' , method primitive printString]]]]].
  51719.     ^ aColl
  51720.  
  51721. "Smalltalk allPrimitiveMethodsInCategories: #('Collections-Streams' 'Files-Streams' 'Files-Abstract' 'Files-Macintosh')"!
  51722. allSelect: aBlock 
  51723.     "Answer a SortedCollection of each method that, when used as the block 
  51724.     argument to aBlock, gives a true result."
  51725.  
  51726.     | aCollection |
  51727.     aCollection _ SortedCollection new.
  51728.     Cursor execute showWhile: 
  51729.         [self allBehaviorsDo: 
  51730.             [:class | class selectorsDo: 
  51731.                 [:sel | (aBlock value: (class compiledMethodAt: sel))
  51732.                     ifTrue: [aCollection add: class name , ' ' , sel]]]].
  51733.     ^aCollection!
  51734. allUnimplementedCalls 
  51735.     "Answer an Array of each message that is sent by an expression in a 
  51736.     method but is not implemented by any object in the system."
  51737.  
  51738.     | aStream secondStream all  |
  51739.     all _ self allImplementedMessages.
  51740.     aStream _ WriteStream on: (Array new: 50).
  51741.     Cursor execute showWhile:
  51742.         [self allBehaviorsDo:
  51743.             [:cl |
  51744.              cl selectorsDo:
  51745.                 [:sel |
  51746.                  secondStream _ WriteStream on: (String new: 5).
  51747.                 (cl compiledMethodAt: sel) messages do:
  51748.                     [:m | (all includes: m) ifFalse: [secondStream nextPutAll: m; space]].
  51749.                 secondStream position = 0 ifFalse:
  51750.                     [aStream nextPut: cl name , ' ' , sel , ' calls: ', secondStream contents]]]].
  51751.     ^aStream contents!
  51752. allUnSentMessages
  51753.     "Answer an Array of each message that is implemented by some object in  the system but is not sent by any.
  51754.      5/8/96 sw: call factored-out method allUnSentMessagesIn:"
  51755.  
  51756.     | anArray sels |
  51757.     anArray _ Array new.
  51758.     sels _ self allUnSentMessagesIn: self allImplementedMessages.
  51759.     sels do: [:sel | anArray _ anArray , (self allImplementorsOf: sel)].
  51760.     ^ anArray!
  51761. allUnSentMessagesIn: aList
  51762.     "Answer the subset of aList (a selector list) which are not sent anywhere in the system.  Factored out from#allUnSentMessages 5/8/96 sw"
  51763.  
  51764.     |  anArray all |
  51765.     all _ aList copy.
  51766.     anArray _ Array new: 0.
  51767.     Cursor execute
  51768.         showWhile: 
  51769.             [self allBehaviorsDo: 
  51770.                 [:cl |
  51771.                  cl selectorsDo: 
  51772.                     [:sel | 
  51773.                     (cl compiledMethodAt: sel) literals do: 
  51774.                         [:m |
  51775.                         (m isMemberOf: Symbol)  "might be sent"
  51776.                             ifTrue: [all remove: m ifAbsent: []].
  51777.                         (m isMemberOf: Array)  "might be performed"
  51778.                             ifTrue: [m do: [:x | all remove: x ifAbsent: []]].
  51779.                         ]]].
  51780.             1 to: self specialSelectorSize do: 
  51781.                 [:index | 
  51782.                 all remove: (self specialSelectorAt: index) ifAbsent: []]].
  51783.     ^ all!
  51784. collectPointersTo: anObject 
  51785.     "Find all occurrences in the system of pointers to the argument anObject."
  51786.     | some |
  51787.     Smalltalk garbageCollect.
  51788.     "Big collection shouldn't grow, so collector is always same"
  51789.     some _ OrderedCollection new: 100.
  51790.     self pointersTo: anObject do:
  51791.         [:obj | obj ~~ some collector ifTrue: [some add: obj]].
  51792.     ^ some asArray
  51793.  
  51794.     "(Smalltalk collectPointersTo: Browser) inspect."
  51795. !
  51796. pointersTo: anObject do: aBlock 
  51797.     "Evaluate the argument aBlock for each pointer to anObject in the 
  51798.     system."
  51799.     | class obj method i fixedSize |
  51800.     Smalltalk allBehaviorsDo: 
  51801.         [:class |
  51802.         class isBits ifTrue:
  51803.             [class == CompiledMethod ifTrue: 
  51804.                 [class allInstancesDo: 
  51805.                     [:method | 
  51806.                     (method pointsTo: anObject)
  51807.                         ifTrue: [aBlock value: method]]]]
  51808.         ifFalse: 
  51809.             [class allInstancesDo: 
  51810.                     [:obj | 
  51811.                     (obj pointsTo: anObject)
  51812.                         ifTrue: [(obj == thisContext
  51813.                                 or: ["Could miss something here"
  51814.                                     obj isMemberOf: BlockContext])
  51815.                                 ifFalse: [aBlock value: obj]]]]]! !
  51816.  
  51817. !SystemDictionary methodsFor: 'class names'!
  51818. classNamed: className 
  51819.     "className is either a class name or a class name followed by ' class'.
  51820.     Answer the class or metaclass it names.
  51821.     8/91 sw chgd so returns nil if class not found, to correct failures in Change Sorter across class renames"
  51822.     | meta baseName baseClass length |
  51823.     length _ className size.
  51824.     (length > 6 and: 
  51825.             [(className copyFrom: length - 5 to: length) = ' class'])
  51826.         ifTrue: 
  51827.             [meta _ true.
  51828.             baseName _ className copyFrom: 1 to: length - 6]
  51829.         ifFalse: 
  51830.             [meta _ false.
  51831.             baseName _ className].
  51832.     baseClass _ Smalltalk at: baseName asSymbol ifAbsent: [nil].
  51833.     baseClass isNil ifTrue: [^ nil].
  51834.     meta
  51835.         ifTrue: [^baseClass class]
  51836.         ifFalse: [^baseClass]!
  51837. classNames
  51838.     "Answer a SortedCollection of all class names."
  51839.     | names |
  51840.     CachedClassNames == nil ifTrue:
  51841.         [names _ OrderedCollection new: self size.
  51842.         self do: 
  51843.             [:cl | (cl isKindOf: Class) ifTrue: [names add: cl name]].
  51844.         CachedClassNames _ names asSortedCollection].
  51845.     ^ CachedClassNames!
  51846. flushClassNameCache
  51847.     "This is an implementation efficiency: the collection of class names is 
  51848.     saved as a class variable and recomputed whenever the collection is 
  51849.     needed but has been previously flushed (set to nil).  Last touched sw 8/91"
  51850.     "Smalltalk flushClassNameCache"
  51851.  
  51852.     CachedClassNames _ nil!
  51853. hasClassNamed: aString
  51854.     "Answer whether there is a class of the given name, but don't intern aString if it's not alrady interned.  4/29/96 sw"
  51855.  
  51856.     Symbol hasInterned: aString ifTrue: 
  51857.         [:aSymbol | ^ (self at: aSymbol ifAbsent: [nil]) isKindOf: Class].
  51858.     ^ false!
  51859. removeClassFromSystem: aClass
  51860.     "Delete the class, aClass, from the system.
  51861.      7/18/96 sw: now that removeClassChanges doesn't remove the changes for the metaclass, call removeClassAndMetaClassChanges: instead"
  51862.  
  51863.     SystemChanges removeClassAndMetaClassChanges: aClass.
  51864.     SystemOrganization removeElement: aClass name.
  51865.     self removeKey: aClass name.
  51866.     self flushClassNameCache
  51867. !
  51868. renameClass: aClass as: newName 
  51869.     "Rename the class, aClass, to have the title newName."
  51870.     | oldref |
  51871.     SystemOrganization classify: newName under: aClass category.
  51872.     SystemOrganization removeElement: aClass name.
  51873.     SystemChanges renameClass: aClass as: newName.
  51874.     oldref _ self associationAt: aClass name.
  51875.     self removeKey: aClass name.
  51876.     oldref key: newName.
  51877.     self add: oldref.  "Old association preserves old refs"
  51878.     self flushClassNameCache! !
  51879.  
  51880. !SystemDictionary methodsFor: 'memory space'!
  51881. bytesLeft
  51882.     "Answer the number of bytes of space available. Does a full garbage collection."
  51883.  
  51884.     ^ self garbageCollect
  51885. !
  51886. createStackOverflow
  51887.     "For testing the low space handler..."
  51888.     "Smalltalk installLowSpaceWatcher; createStackOverflow"
  51889.  
  51890.     self createStackOverflow.  "infinite recursion"!
  51891. garbageCollect
  51892.     "Primitive. Reclaims all garbage and answers the number of bytes of available space."
  51893.  
  51894.     <primitive: 130>
  51895.     ^ self primBytesLeft!
  51896. garbageCollectMost
  51897.     "Primitive. Reclaims recently created garbage (which is usually most of it) fairly quickly and answers the number of bytes of available space."
  51898.  
  51899.     <primitive: 131>
  51900.     ^ self primBytesLeft!
  51901. installLowSpaceWatcher
  51902.     "Start a process to watch for low-space conditions."
  51903.     "Smalltalk installLowSpaceWatcher"
  51904.  
  51905.     self primSignalAtBytesLeft: 0.  "disable low-space interrupts"
  51906.     LowSpaceProcess == nil ifFalse: [LowSpaceProcess terminate].
  51907.     LowSpaceProcess _ [self lowSpaceWatcher] newProcess.
  51908.     LowSpaceProcess priority: Processor lowIOPriority.
  51909.     LowSpaceProcess resume.
  51910.  
  51911. !
  51912. lowSpaceWatcher
  51913.     "Wait until the low space semaphore is signalled, then take appropriate actions."
  51914.  
  51915.     | lowSpaceThreshold |
  51916.     lowSpaceThreshold _ 80000.
  51917.     self garbageCollectMost <= lowSpaceThreshold ifTrue: [
  51918.         self garbageCollect <= lowSpaceThreshold ifTrue: [
  51919.             "free space must be above threshold before starting"
  51920.             ^ self beep
  51921.         ].
  51922.     ].
  51923.  
  51924.     LowSpaceSemaphore _ Semaphore new.
  51925.     self primLowSpaceSemaphore: LowSpaceSemaphore.
  51926.     self primSignalAtBytesLeft: lowSpaceThreshold.  "enable low space interrupts"
  51927.  
  51928.     LowSpaceSemaphore wait.  "wait for a low space condition..."
  51929.  
  51930.     self primSignalAtBytesLeft: 0.  "disable low space interrupts"
  51931.     self primLowSpaceSemaphore: nil.
  51932.     LowSpaceProcess _ nil.
  51933.     ScheduledControllers interruptName: 'Space is low'.
  51934. !
  51935. primBytesLeft
  51936.     "Primitive. Answer the number of bytes available for new object data.
  51937.     Not accurate unless preceded by
  51938.         Smalltalk garbageCollectMost (for reasonable accuracy), or
  51939.         Smalltalk garbageCollect (for real accuracy).
  51940.     See Object documentation whatIsAPrimitive."
  51941.  
  51942.     <primitive: 112>
  51943.     ^ 0!
  51944. primLowSpaceSemaphore: aSemaphore
  51945.     "Primitive. Register the given Semaphore to be signalled when the
  51946.     number of free bytes drops below some threshold. Disable low-space
  51947.     interrupts if the argument is nil."
  51948.  
  51949.     <primitive: 124>
  51950.     self primitiveFailed!
  51951. primSignalAtBytesLeft: numBytes
  51952.     "Tell the interpreter the low-space threshold in bytes. When the free
  51953.     space falls below this threshold, the interpreter will signal the low-space
  51954.     semaphore, if one has been registered.  Disable low-space interrupts if the
  51955.     argument is zero.  Fail if numBytes is not an Integer."
  51956.  
  51957.     <primitive: 125>
  51958.     self primitiveFailed!
  51959. printSpaceAnalysis        "Smalltalk garbageCollect; printSpaceAnalysis"
  51960.     | f name space words scale count |
  51961.     f _ FileStream newFileNamed: 'STspace.text'.
  51962.     f timeStamp.
  51963.     self allClassesDo:
  51964.         [:cl | name _ cl name.
  51965.         Sensor redButtonPressed ifTrue: [Transcript cr; show: name].
  51966.         space _ cl == Character ifTrue: [#(0 0)] ifFalse: [cl space].
  51967.         count _ cl instanceCount.
  51968.         f print: name; tab;
  51969.             print: space first; tab;
  51970.             print: space last; tab;
  51971.             print: count; tab.
  51972.         words _ (cl instSize+2)*count.
  51973.         cl isVariable ifTrue:
  51974.                 [scale _ cl isBytes ifTrue: [2] ifFalse: [1].
  51975.                 cl allInstancesDo: [:x | words _ words + (x size//scale)]].
  51976.         f print: words; cr].
  51977.     f close!
  51978. signalLowSpace
  51979.     "Signal the low-space semaphore to alert the user that space is running low."
  51980.  
  51981.     LowSpaceSemaphore signal.!
  51982. useUpMemory
  51983.     "For testing the low space handler..."
  51984.     "Smalltalk installLowSpaceWatcher; useUpMemory"
  51985.  
  51986.     | lst |
  51987.     lst _ nil.
  51988.     [true] whileTrue: [
  51989.         lst _ Link new nextLink: lst; yourself.
  51990.     ].! !
  51991.  
  51992. !SystemDictionary methodsFor: 'special objects'!
  51993. compactClassesArray  "Smalltalk compactClassesArray"
  51994.     "Return the array of 31 classes whose instances may be
  51995.     represented compactly"
  51996.     ^ Smalltalk specialObjectsArray at: 29!
  51997. hasSpecialSelector: aLiteral ifTrueSetByte: aBlock
  51998.  
  51999.     1 to: self specialSelectorSize do:
  52000.         [:index | 
  52001.         (self specialSelectorAt: index) == aLiteral
  52002.             ifTrue: [aBlock value: index + 16rAF. ^true]].
  52003.     ^false!
  52004. specialNargsAt: anInteger 
  52005.     "Answer the number of arguments for the special selector at: anInteger."
  52006.  
  52007.     ^SpecialSelectors at: anInteger * 2!
  52008. specialObjectsArray  "Smalltalk specialObjectsArray at: 1"
  52009.     <primitive: 129>
  52010.     ^ self primitiveFailed!
  52011. specialSelectorAt: anInteger 
  52012.     "Answer the special message selector stored at location anInteger in the 
  52013.     system dictionary."
  52014.  
  52015.     ^SpecialSelectors at: anInteger * 2 - 1!
  52016. specialSelectors
  52017.     "Used by SystemTracer only."
  52018.  
  52019.     ^SpecialSelectors!
  52020. specialSelectorSize
  52021.     "Answer the number of special selectors in the system."
  52022.  
  52023.     ^SpecialSelectors size // 2! !
  52024.  
  52025. !SystemDictionary methodsFor: 'image, changes name'!
  52026. changesName  "Smalltalk changesName"
  52027.     "Answer the current name for the changes file that matches the image file name"
  52028.     | imName index |
  52029.     FileDirectory splitName: self imageName
  52030.         to: [:volName :fileName | imName _ fileName].
  52031.     imName size > 5 ifTrue: 
  52032.         [(index _ (imName findString: '.image' startingAt: imName size - 5)) > 0 ifTrue: 
  52033.             [^(imName copyFrom: 1 to: index-1), '.changes']].
  52034.     ^imName, '.changes'
  52035. !
  52036. imageName
  52037.     "Answer the full path name for the current image."
  52038.     "Smalltalk imageName"
  52039.  
  52040.     <primitive: 121>
  52041.     self primitiveFailed!
  52042. imageName: newName
  52043.     "Set the the full path name for the current image.  All further snapshots will use this."
  52044.  
  52045.     <primitive: 121>
  52046.     ^ self primitiveFailed!
  52047. imagePath
  52048.     "Answer the path for the directory containing the image file."
  52049.     "Smalltalk imagePath"
  52050.  
  52051.     ^ FileDirectory
  52052.         splitName: self imageName
  52053.         to: [ :volName :fileName | ^ volName ]!
  52054. sourcesName
  52055.     "Answer the sources file name used in this Smalltalk release."
  52056.  
  52057.     ^ self vmPath, 'ST-80vers1.sources'!
  52058. vmPath
  52059.     "Answer the path for the directory containing the Smalltalk virtual machine. Return the empty string if this primitive is not implemented."
  52060.     "Smalltalk vmPath"
  52061.  
  52062.     <primitive: 142>
  52063.     ^ ''! !
  52064.  
  52065. !SystemDictionary methodsFor: 'sources, change log'!
  52066. changes
  52067.     "Answer the current system ChangeSet."
  52068.  
  52069.     ^SystemChanges!
  52070. closeSourceFiles
  52071.     "Shut down the source files if appropriate.  1/29/96 sw: changed so that the closing and nilification only take place if the entry was a FileStream, thus allowing stringified sources to remain in the saved image file"
  52072.  
  52073.     1 to: 2 do: [:i |
  52074.         ((SourceFiles at: i) isKindOf: FileStream)
  52075.             ifTrue:
  52076.                 [(SourceFiles at: i) close.
  52077.                 SourceFiles at: i put: nil]]!
  52078. copyright
  52079.     "The Smalltalk copyright."
  52080.  
  52081.     ^'Copyright (c) Xerox Corp. 1981, 1982 All rights reserved.
  52082. Copyright (c) Apple Computer, Inc. 1985-1996 All rights reserved.'!
  52083. externalizeSources   
  52084.     "Write the sources and changes streams onto external files.
  52085.         1/29/96 sw"
  52086.      "Smalltalk externalizeSources"
  52087.  
  52088.     "NB: openSourceFiles, actualContents, and fileExistsNamed: are symbols not yet in AST image 1/25/96 sw"
  52089.  
  52090.     | sourcesName changesName aFile |
  52091.     sourcesName _ self sourcesName.
  52092.     (FileDirectory default includesKey: sourcesName) ifTrue:
  52093.         [^ self inform: 'Sorry, you must first move or remove the
  52094. file named ', sourcesName].
  52095.     changesName _ self changesName.
  52096.     (FileDirectory default includesKey: changesName) ifTrue:
  52097.         [^ self inform: 'Sorry, you must first move or remove the
  52098. file named ', changesName].
  52099.  
  52100.  
  52101.     aFile _  FileStream newFileNamed: sourcesName.
  52102.     aFile nextPutAll: SourceFiles first originalContents.
  52103.     aFile close.
  52104.     SourceFiles at: 1 put: (FileStream readOnlyFileNamed: sourcesName).
  52105.  
  52106.     aFile _ FileStream newFileNamed: self changesName.
  52107.     aFile nextPutAll: SourceFiles last contents.
  52108.     aFile close.
  52109.     SourceFiles at: 2 put: (FileStream oldFileNamed: changesName).
  52110.  
  52111.     self inform: 'Sources successfully externalized'!
  52112. forceChangesToDisk
  52113.     "Ensure that the changes file has been fully written to disk by closing and re-opening it. This makes the system more robust in the face of a power failure or hard-reboot."
  52114.  
  52115.     | changesFile |
  52116.     changesFile _ SourceFiles at: 2.
  52117.     (changesFile isKindOf: FileStream) ifTrue: [
  52118.         changesFile flush.
  52119.         changesFile close.
  52120.         changesFile open: changesFile name forWrite: true.
  52121.         changesFile setToEnd.
  52122.     ].
  52123. !
  52124. internalizeChangeLog    
  52125.         "Smalltalk internalizeChangeLog"
  52126.     "Bring the changes file into a memory-resident filestream, for faster access and freedom from external file system.  1/31/96 sw"
  52127.  
  52128.     | reply aName aFile |
  52129.     reply _ self confirm:  'CAUTION -- do not undertake this lightly!!
  52130. If you have backed up your system and
  52131. are prepared to face the consequences of
  52132. the requested internalization of sources,
  52133. hit Yes.  If you have any doubts, hit No
  52134. to back out with no harm done.'.
  52135.  
  52136.     (reply ==  true) ifFalse:
  52137.         [^ self inform: 'Okay - abandoned'].
  52138.  
  52139.     aName _ self changesName.
  52140.     (aFile _ SourceFiles last) == nil ifTrue:
  52141.         [(FileDirectory default includesKey: aName)
  52142.             ifFalse: [^ self halt: 'Cannot locate ', aName, ' so cannot proceed.'].
  52143.         aFile _ FileStream readOnlyFileNamed: aName].
  52144.     SourceFiles at: 2 put: (ReadWriteStream with: aFile contentsOfEntireFile).
  52145.  
  52146.     self inform: 'Okay, changes file internalized'!
  52147. internalizeSources    
  52148.         "Smalltalk internalizeSources"
  52149.     "Bring the sources and changes files into memory-resident filestreams, for faster access and freedom from file-system interface.  1/29/96 sw"
  52150.  
  52151.     | reply aName aFile |
  52152.     reply _ self confirm:  'CAUTION -- do not undertake this lightly!!
  52153. If you have backed up your system and
  52154. are prepared to face the consequences of
  52155. the requested internalization of sources,
  52156. hit Yes.  If you have any doubts, hit No
  52157. to back out with no harm done.'.
  52158.  
  52159.     (reply ==  true) ifFalse:
  52160.         [^ self inform: 'Okay - abandoned'].
  52161.  
  52162.     aName _ self sourcesName.
  52163.     (aFile _ SourceFiles first) == nil ifTrue:
  52164.         [(FileDirectory default includesKey: aName)
  52165.             ifFalse: [^ self halt: 'Cannot locate ', aName, ' so cannot proceed.'].
  52166.         aFile _ FileStream readOnlyFileNamed: aName].
  52167.     SourceFiles at: 1 put: (ReadWriteStream with: aFile contentsOfEntireFile).
  52168.  
  52169.     aName _ self changesName.
  52170.     (aFile _ SourceFiles last) == nil ifTrue:
  52171.         [(FileDirectory default includesKey: aName)
  52172.             ifFalse: [^ self halt: 'Cannot locate ', aName, ' so cannot proceed.'].
  52173.         aFile _ FileStream readOnlyFileNamed: aName].
  52174.     SourceFiles at: 2 put: (ReadWriteStream with: aFile contentsOfEntireFile).
  52175.  
  52176.     self inform: 'Okay, sources internalized'!
  52177. logChange: aStringOrText
  52178.     "Write the argument, aString, onto the changes file."
  52179.     | aFileStream aString |
  52180.     (SourceFiles isNil or: [(SourceFiles at: 2) == nil]) ifTrue: [^self].
  52181.     (aStringOrText isMemberOf: Text)
  52182.         ifTrue: [aString _ aStringOrText string]
  52183.         ifFalse: [aString _ aStringOrText].
  52184.     (aString isMemberOf: String)
  52185.         ifFalse: [self error: 'cant log this change'].
  52186.     (aString findFirst: [:char | char isSeparator not]) = 0
  52187.         ifTrue: [^self].  "null doits confuse replay"
  52188.     (SourceFiles at: 2) setToEnd;
  52189.             cr; cr; nextChunkPut: aString.
  52190.     self forceChangesToDisk.!
  52191. newChanges: aChangeSet 
  52192.     "Set the system ChangeSet to be the argument, aChangeSet."
  52193.  
  52194.     SystemChanges _ aChangeSet!
  52195. noChanges 
  52196.     "Initialize the system ChangeSet."
  52197.  
  52198.     SystemChanges initialize!
  52199. openSourceFiles
  52200.     FileDirectory
  52201.         openSources: self sourcesName
  52202.         andChanges: self changesName
  52203.         forImage: self imageName!
  52204. recover: nCharacters
  52205.     "Schedule an editable text view on the last n characters of changes."
  52206.     | changes |
  52207.     changes _ SourceFiles at: 2.
  52208.     changes setToEnd; skip: nCharacters negated.
  52209.     (FileStream newFileNamed: 'st80.recent') nextPutAll: (changes next: nCharacters); close; open; edit!
  52210. timeStamp: aStream 
  52211.     "Writes system version and current time on stream aStream."
  52212.  
  52213.     | dateTime |
  52214.     dateTime _ Time dateAndTimeNow.
  52215.     aStream nextPutAll: 'From ', Smalltalk version, ' on ', (dateTime at: 1) printString,
  52216.                         ' at ', (dateTime at: 2) printString!
  52217. version
  52218.     "Answer the version of this Smalltalk release."
  52219.  
  52220.     ^ 'Smalltalk-80 version 1.03 of July 31, 1996'! !
  52221.  
  52222. !SystemDictionary methodsFor: 'snapshot and quit'!
  52223. ioReset    "Smalltalk ioReset"
  52224.     "Cause a shutDown and startUp of OS resources.
  52225.     This can be useful to close hung files so that they
  52226.     can be opened again, as when a fileOut failed"
  52227.  
  52228.     self processShutDownList.
  52229.     self garbageCollect.  "Purge unref'd files"
  52230.     self processStartUpList!
  52231. lastQuitLogPosition
  52232.     ^ LastQuitLogPosition!
  52233. processShutDownList
  52234.     "Call the shutDown method on each object that needs to gracefully shut itself down before a snapshot."
  52235.  
  52236.     SoundPlayer shutDown.
  52237.     Smalltalk shutDown.
  52238.     Delay shutDown.
  52239.     ControlManager shutDown.
  52240.     DisplayScreen shutDown.
  52241. !
  52242. processStartUpList
  52243.     "Call the startUp method on each object that needs to gracefully restart itself after a snapshot."
  52244.  
  52245.     DisplayScreen startUp.
  52246.     Cursor startUp.
  52247.     InputSensor startUp.
  52248.     ProcessorScheduler hiddenBackgroundProcess.
  52249.     Delay startUp.
  52250.     Smalltalk startUp.
  52251.     ControlManager startUp.  "NOTE: The active process terminates here."
  52252. !
  52253. quitPrimitive
  52254.     "Primitive. Exit to another operating system on the host machine, if one
  52255.     exists. All state changes in the object space since the last snapshot are lost.
  52256.     Essential. See Object documentation whatIsAPrimitive."
  52257.  
  52258.     <primitive: 113>
  52259.     self primitiveFailed!
  52260. saveAs
  52261.     | dir newName |
  52262.     dir _ FileDirectory default.
  52263.     newName _ (FillInTheBlank request: 'New File Name?'                     initialAnswer: 'NewImageName') asFileName.
  52264.     (newName endsWith: '.image') ifTrue:
  52265.         [newName _ newName copyFrom: 1 to: newName size - 6].
  52266.     (dir includesKey: newName , '.image')
  52267.         | (dir includesKey: newName , '.changes') ifTrue:
  52268.         [^ self notify: newName , ' is already in use
  52269. Please choose another name.'].
  52270.     dir copyFileNamed: self changesName toFileNamed: newName , '.changes'.
  52271.     self logChange: '----SAVEAS ' , newName , '----'
  52272.         , Date dateAndTimeNow printString.
  52273.     self imageName: newName , '.image'.
  52274.     self closeSourceFiles; openSourceFiles.
  52275.     "Just so SNAPSHOT appears on the new file, and not the old"
  52276.     self snapshot: true andQuit: false.!
  52277. shutDown
  52278.     ^ self closeSourceFiles!
  52279. snapshot: save andQuit: quit
  52280.     "Mark the changes file and close all files.  If save is true, save the current state of this Smalltalk in the image file.  If quit is true, then exit to the outer shell.  Note: latter part of this method runs when resuming a previously saved image. 
  52281.     1/17/96 sw: ripped out the disk-library maintenance stuff
  52282.     5/8/96 sw: report snapshot/quit to transcript as well as chgs log"
  52283.  
  52284.     | resuming msg |
  52285.     save & (SourceFiles at: 2) notNil ifTrue:
  52286.         [msg _  (quit
  52287.             ifTrue: ['----QUIT----']
  52288.             ifFalse: ['----SNAPSHOT----']), Date dateAndTimeNow printString.
  52289.  
  52290.         self logChange: msg.
  52291.         Transcript cr; show: msg.
  52292.         LastQuitLogPosition _ (SourceFiles at: 2) position].
  52293.  
  52294.     self processShutDownList.
  52295.     Cursor write show.
  52296.     save ifTrue: [resuming _ self snapshotPrimitive]  "<-- PC frozen here on image file"
  52297.         ifFalse: [resuming _ false].
  52298.     quit & resuming not ifTrue: [self quitPrimitive].
  52299.     Cursor normal show.
  52300.     self processStartUpList.
  52301.     !
  52302. snapshotPrimitive
  52303.     "Primitive. Write the current state of the object memory on a file in the
  52304.     same format as the Smalltalk-80 release. The file can later be resumed,
  52305.     returning you to this exact state. Return normally after writing the file.
  52306.     Essential. See Object documentation whatIsAPrimitive."
  52307.  
  52308.     <primitive: 97>
  52309.     self primitiveFailed!
  52310. startUp
  52311.     "Start up the low-space watcher and open the files for sources and changes."
  52312.  
  52313.     Smalltalk installLowSpaceWatcher.
  52314.     self openSourceFiles.! !
  52315.  
  52316. !SystemDictionary methodsFor: 'housekeeping'!
  52317. cleanOutUndeclared  "Smalltalk cleanOutUndeclared"
  52318.     Undeclared keys do:
  52319.     [:key | (Smalltalk allCallsOn: (Undeclared associationAt: key)) isEmpty
  52320.                 ifTrue: [Undeclared removeKey: key]].
  52321. !
  52322. condenseChanges        "Smalltalk condenseChanges"
  52323.     "Move all the changes onto a compacted sources file."
  52324.     | f name oldChanges classCount |
  52325.     f _ FileStream fileNamed: 'ST80.temp'.
  52326.     f header; timeStamp.
  52327. 'Condensing Changes File...'
  52328.     displayProgressAt: Sensor cursorPoint
  52329.     from: 0 to: Smalltalk classNames size
  52330.     during:
  52331.         [:bar | classCount _ 0.
  52332.         Smalltalk allClassesDo:
  52333.             [:class | bar value: (classCount _ classCount + 1).
  52334.             class moveChangesTo: f.
  52335.             class class moveChangesTo: f]].
  52336.     LastQuitLogPosition _ f position.
  52337.     f trailer; close.
  52338.     oldChanges _ SourceFiles at: 2.
  52339.     oldChanges close.
  52340.     FileDirectory default rename: oldChanges name
  52341.                         toBe: oldChanges name , '.old'.
  52342.     FileDirectory default rename: f name
  52343.                         toBe: oldChanges name.
  52344.     SourceFiles at: 2
  52345.             put: (StandardFileStream oldFileNamed: oldChanges name).!
  52346. condenseSources        "Smalltalk condenseSources"
  52347.     "Move all the changes onto a compacted sources file."
  52348.     | f name oldChanges classCount dir |
  52349.     dir _ FileDirectory default.
  52350.  
  52351.     "Write all sources with fileIndex 1"
  52352.     f _ FileStream newFileNamed: self sourcesName , '.temp'.
  52353.     f header; timeStamp.
  52354. 'Condensing Sources File...'
  52355.     displayProgressAt: Sensor cursorPoint
  52356.     from: 0 to: Smalltalk classNames size
  52357.     during:
  52358.         [:bar | classCount _ 0.
  52359.         Smalltalk allClassesDo:
  52360.             [:class | bar value: (classCount _ classCount + 1).
  52361.             class fileOutOn: f moveSource: true toFile: 1]].
  52362.     f trailer; close.
  52363.  
  52364.     "Make a new empty changes file"
  52365.     self closeSourceFiles.
  52366.     dir rename: self changesName
  52367.         toBe: self changesName , '.old'.
  52368.     (FileStream newFileNamed: self changesName)
  52369.         header; timeStamp; close.
  52370.     LastQuitLogPosition _ 0.
  52371.  
  52372.     dir rename: self sourcesName
  52373.         toBe: self sourcesName , '.old'.
  52374.     dir rename: self sourcesName , '.temp'
  52375.         toBe: self sourcesName.
  52376.     self openSourceFiles.
  52377.     PopUpMenu notify: 'Source files have been rewritten!!
  52378. Check that all is well,
  52379. and then save/quit.'!
  52380. deleteClasses  "Select and execute to get more space in your system."
  52381.             "Smalltalk deleteClasses.  Smalltalk spaceLeft"
  52382.     #(InstructionPrinter MessageTally GraphicSymbol GraphicSymbolInstance FormButtonCache FormMenuView FormMenuController FormEditor) do:
  52383.         [:name | (Smalltalk at: name) removeFromSystem].
  52384.     "Reclaim unused Symbols (3K):"
  52385.     Symbol rehash.!
  52386. forgetDoIts
  52387.  
  52388.     Smalltalk allBehaviorsDo: "get rid of old DoIt methods"
  52389.             [:cl | cl removeSelector: #DoIt; removeSelector: #DoItIn:]
  52390.  
  52391.     "Smalltalk forgetDoIts"!
  52392. obsoleteClasses   "Smalltalk obsoleteClasses inspect"
  52393.     "NOTE:  Also try inspecting comments below"
  52394.     | obs c |
  52395.     obs _ OrderedCollection new.  Smalltalk garbageCollect.
  52396.     Metaclass allInstances do:
  52397.         [:m | c _ m soleInstance.
  52398.         (c ~~ nil and: ['AnOb*' match: c name asString])
  52399.             ifTrue: [obs add: c]].
  52400.     ^ obs asArray
  52401.  
  52402. "Likely in a ClassDict or Pool...
  52403. (Association allInstances select: [:a | (a value isKindOf: Class) and: ['AnOb*' match: a value name]]) asArray
  52404. "
  52405. "Obsolete class refs or super pointer in last lit of a method...
  52406. | n l found |
  52407. Smalltalk browseAllSelect:
  52408.     [:m | found _ false.
  52409.     1 to: m numLiterals do:
  52410.         [:i | (((l _ m literalAt: i) isMemberOf: Association)
  52411.                 and: [(l value isKindOf: Behavior)
  52412.                 and: ['AnOb*' match: l value name]])
  52413.             ifTrue: [found _ true]].
  52414.     found]
  52415. "!
  52416. reclaimDependents        "Smalltalk reclaimDependents"
  52417.     "Reclaim unused entries in DependentsFields (DF)..."
  52418.     "NOTE:  if <object>addDependent: is ever used to add something
  52419.         other than a view, this process will fail to reinstate that
  52420.         thing after clearing out DependentsFields.  DF was only
  52421.         intended to be used as part of the MVC architecture."
  52422.     Object classPool at: #DependentsFields  "Remove all entries from DF"
  52423.                 put: IdentityDictionary new.
  52424.     Smalltalk garbageCollect.  "If that was the only reference, they will go away"
  52425.     "Now if any views of non-models remain,
  52426.         they should be reinstated as dependent views..."
  52427.     View allInstancesDo:
  52428.         [:v | (v model==nil or: [v model isKindOf: Model])
  52429.                 ifFalse: [v model addDependent: v]].
  52430.     View allSubInstancesDo:
  52431.         [:v | (v model==nil or: [v model isKindOf: Model])
  52432.                 ifFalse: [v model addDependent: v]]
  52433.     !
  52434. recompileAllFrom: firstName 
  52435.     "Recompile all classes, starting with given name."
  52436.  
  52437.     | class |
  52438.     Smalltalk forgetDoIts.
  52439.     self allClassesDo: 
  52440.         [:class | class name >= firstName
  52441.             ifTrue: 
  52442.                 [Transcript show: class name; cr.
  52443.                 class compileAll]]
  52444.  
  52445.     "Smalltalk recompileAllFrom: 'Aardvark'."
  52446. !
  52447. removeEmptyMessageCategories
  52448.     "Smalltalk removeEmptyMessageCategories"
  52449.     Smalltalk garbageCollect.
  52450.     ClassOrganizer allInstancesDo:
  52451.         [:org | org categories do: 
  52452.             [:cat | (org listAtCategoryNamed: cat) isEmpty
  52453.                 ifTrue: [org removeCategory: cat]]]!
  52454. verifyChanges        "Smalltalk verifyChanges"
  52455.     "Recompile all methods in the changes file."
  52456.     Smalltalk allBehaviorsDo: [:class | class recompileChanges].
  52457. ! !
  52458.  
  52459. !SystemDictionary methodsFor: 'miscellaneous'!
  52460. beep
  52461.     "Emit a short alert sound."
  52462.  
  52463.     <primitive: 140>
  52464.     self primitiveFailed!
  52465. clipboardText
  52466.     "Get the current clipboard text."
  52467.  
  52468.     <primitive: 141>
  52469.     ^ self primitiveFailed!
  52470. clipboardText: aString
  52471.     "Set the current clipboard text to the given string."
  52472.  
  52473.     <primitive: 141>
  52474.     ^ self primitiveFailed!
  52475. gifImports
  52476.     "Answer the global dictionary of gif imports, creating it if necessary.  7/24/96 sw"
  52477.  
  52478.     "Smalltalk viewGIFImports"
  52479.     (self includesKey: #GIFImports)
  52480.         ifFalse:
  52481.             [self at: #GIFImports put: Dictionary new].
  52482.     ^ self at: #GIFImports!
  52483. gifReaderClass
  52484.     "Answer, if present, a class to handle the importing of GIF files from disk. If none, return nil.   9/18/96 sw"
  52485.  
  52486.     | aClass |
  52487.     ^ ((aClass _ self at: #GIFReadWriter ifAbsent: [nil]) isKindOf: Class)
  52488.         ifTrue:
  52489.             [aClass]
  52490.         ifFalse:
  52491.             [nil]!
  52492. hyperSqueakPresent
  52493.     "Answer whether HyperSqueak is present in the current image.  9/19/96 sw"
  52494.  
  52495.     ^ self hyperSqueakSupportClass notNil!
  52496. hyperSqueakSupportClass
  52497.     "If present, answer the SqueakSupport class, else nil.  9/18/96 sw"
  52498.     | aClass |
  52499.     ^ ((aClass _ self at: #SqueakSupport ifAbsent: [nil]) isKindOf: Class)
  52500.         ifTrue:
  52501.             [aClass]
  52502.         ifFalse:
  52503.             [nil]!
  52504. removeGIFReadersFromSystem
  52505.     "Remove all GIF-reader classes from the system.  9/18/96 sw"
  52506.  
  52507.     SystemOrganization removeSystemCategory: 'Graphics-Files'
  52508.  
  52509. "Smalltalk removeGIFReadersFromSystem"!
  52510. removeHyperSqueakFromSystem
  52511.     "Remove all the HyperSqueak classes from the system.  9/18/96 sw"
  52512.  
  52513.     | hsSupport |
  52514.     (hsSupport _ self hyperSqueakSupportClass) == nil
  52515.         ifTrue:
  52516.             [^ self inform: 'HyperSqueak is already gone!!'].
  52517.     hsSupport squeakCategories do:
  52518.         [:aCategoryName | SystemOrganization removeSystemCategory: aCategoryName]!
  52519. viewGIFImports
  52520.     "Open up a special Form inspector on the dictionary of GIF imports.  7/24/96 sw"
  52521.  
  52522.     self gifImports inspectFormsWithLabel: 'GIF Imports'! !
  52523.  
  52524. !SystemDictionary methodsFor: 'private'!
  52525. exitToDebugger
  52526.     "Primitive. Enter the machine language debugger, if one exists. Essential.
  52527.     See Object documentation whatIsAPrimitive."
  52528.  
  52529.     <primitive: 114>
  52530.     self primitiveFailed!
  52531. newWorld
  52532.     "return true iff we are running in the new world"
  52533.     ^ 999999 class == SmallInteger! !
  52534.  
  52535. !SystemDictionary methodsFor: 'profiling'!
  52536. clearProfile
  52537.     "Clear the profile database."
  52538.  
  52539.     <primitive: 250>
  52540. !
  52541. dumpProfile
  52542.     "Dump the profile database to a file."
  52543.  
  52544.     <primitive: 251>
  52545. !
  52546. profile: aBlock
  52547.     "Make a virtual machine profile of the given block."
  52548.     "Note: Profiling support is provided so that VM implementors
  52549.      can better understand and improve the efficiency of the virtual
  52550.      machine. To use it, you must be running a version of the
  52551.      virtual machine compiled with profiling enabled (which
  52552.      makes it much slower than normal even when not profiling).
  52553.      You will also need the CodeWarrior profile reader application."
  52554.  
  52555.     self stopProfiling.
  52556.     self clearProfile.
  52557.     self startProfiling.
  52558.     aBlock value.
  52559.     self stopProfiling.
  52560.     self dumpProfile.!
  52561. startProfiling
  52562.     "Start profiling the virtual machine."
  52563.  
  52564.     <primitive: 252>
  52565. !
  52566. stopProfiling
  52567.     "Stop profiling the virtual machine."
  52568.  
  52569.     <primitive: 253>
  52570. ! !ClassOrganizer subclass: #SystemOrganizer
  52571.     instanceVariableNames: ''
  52572.     classVariableNames: ''
  52573.     poolDictionaries: ''
  52574.     category: 'Kernel-Support'!
  52575. SystemOrganizer comment:
  52576. 'My instances provide an organization for the classes in the system, just as a ClassOrganizer organizes the messages within a class. The only difference is the methods for fileIn/Out.'!
  52577.  
  52578. !SystemOrganizer methodsFor: 'fileIn/Out'!
  52579. fileOutCategory: category 
  52580.     "Store on the file named category (a string) concatenated with '.st' all the 
  52581.     classes associated with the category."
  52582.     ^ self fileOutCategory: category withSuffix: '.st'!
  52583. fileOutCategory: category on: aFileStream 
  52584.     "Store on the file associated with aFileStream, all the classes associated 
  52585.     with the category and any requested shared pools."
  52586.  
  52587.     | first poolSet tempClass classes |
  52588.     classes _ (self superclassOrder: category).
  52589.     poolSet _ Set new.
  52590.     classes do: 
  52591.         [:class | class sharedPools do: [:eachPool | poolSet add: eachPool]].
  52592.     poolSet size > 0 ifTrue:
  52593.         [tempClass _ Class new.
  52594.         tempClass shouldFileOutPools ifTrue:
  52595.             [poolSet _ poolSet select: [:aPool | tempClass shouldFileOutPool: (Smalltalk keyAtValue: aPool)].
  52596.             poolSet do: [:aPool | tempClass fileOutPool: aPool onFileStream: aFileStream]]].
  52597.     first _ true.
  52598.     classes do: 
  52599.         [:class | 
  52600.         first
  52601.             ifTrue: [first _ false]
  52602.             ifFalse: [aFileStream cr; nextPut: Character newPage; cr].
  52603.         class
  52604.             fileOutOn: aFileStream
  52605.             moveSource: false
  52606.             toFile: 0]!
  52607. fileOutCategory: category withSuffix: aSuffix
  52608.     "Store on the file named category (a string) concatenated withaSuffix all the 
  52609.     classes associated with the category."
  52610.     | aFileStream |
  52611.     aFileStream _ FileStream newFileNamed: (category , aSuffix) asFileName.
  52612.     self fileOutCategory: category on: aFileStream.
  52613.     aFileStream close!
  52614. superclassOrder: category 
  52615.     "Answer an OrderedCollection containing references to the classes in the 
  52616.     category whose name is the argument, category (a string). The classes 
  52617.     are ordered with superclasses first so they can be filed in."
  52618.  
  52619.     | list |
  52620.     list _ 
  52621.         (self listAtCategoryNamed: category asSymbol) 
  52622.             collect: [:title | Smalltalk at: title].
  52623.     ^ChangeSet superclassOrder: list! !
  52624.  
  52625. !SystemOrganizer methodsFor: 'remove'!
  52626. removeSystemCategory: category
  52627.     "remove all the classes associated with the category"
  52628.  
  52629.     (self superclassOrder: category) do: [:class | class removeFromSystem].
  52630.     self removeEmptyCategories! !ArrayedCollection subclass: #Text
  52631.     instanceVariableNames: 'string runs '
  52632.     classVariableNames: ''
  52633.     poolDictionaries: 'TextConstants '
  52634.     category: 'Collections-Text'!
  52635. Text comment:
  52636. 'I represent a String that has been marked with abstract changes in character appearance. Actual display is performed in the presence of a TextStyle which indicates, for each abstract code, an actual font to be used.'!
  52637.  
  52638. !Text methodsFor: 'accessing'!
  52639. at: index
  52640.  
  52641.     ^string at: index!
  52642. at: index put: character
  52643.  
  52644.     ^string at: index put: character!
  52645. atPin: index
  52646.  
  52647.     ^string atPin: index!
  52648. atWrap: index
  52649.  
  52650.     ^string atWrap: index!
  52651. findString: aString startingAt: start 
  52652.     "Answer the index of subString within the receiver, starting at index 
  52653.     start. If the receiver does not contain subString, answer 0."
  52654.  
  52655.     ^string findString: aString asString startingAt: start!
  52656. replaceFrom: start to: stop with: aText
  52657.  
  52658.     string _ string copyReplaceFrom: start to: stop with: aText string.
  52659.     runs _ runs copyReplaceFrom: start to: stop with: aText runs!
  52660. size
  52661.  
  52662.     ^string size!
  52663. string
  52664.     "Answer the string representation of the receiver."
  52665.  
  52666.     ^string! !
  52667.  
  52668. !Text methodsFor: 'comparing'!
  52669. = other
  52670.     ^ other notNil 
  52671.         ifTrue:    [string = other string and: [runs = other asText runs]]
  52672.         ifFalse: [false]! !
  52673.  
  52674. !Text methodsFor: 'copying'!
  52675. copy
  52676.  
  52677.     ^self deepCopy!
  52678. copyFrom: start to: stop 
  52679.     "Answer a copied subrange of the receiver."
  52680.  
  52681.     | realStart realStop |
  52682.     stop > self size
  52683.         ifTrue: [realStop _ self size]        "handle selection at end of string"
  52684.         ifFalse: [realStop _ stop].
  52685.     start < 1
  52686.         ifTrue: [realStart _ 1]            "handle selection before start of string"
  52687.         ifFalse: [realStart _ start].
  52688.     ^Text 
  52689.         string: (string copyFrom: realStart to: realStop)
  52690.         runs: (runs copyFrom: realStart to: realStop)!
  52691. copyReplaceFrom: start to: stop with: aText
  52692.  
  52693.     ^self shallowCopy replaceFrom: start to: stop with: aText! !
  52694.  
  52695. !Text methodsFor: 'converting'!
  52696. asDisplayText
  52697.     "Answer a DisplayText whose text is the receiver."
  52698.  
  52699.     ^DisplayText text: self!
  52700. asNumber
  52701.     "Answer the number created by interpreting the receiver as the textual 
  52702.     representation of a number."
  52703.  
  52704.     ^string asNumber!
  52705. asParagraph
  52706.     "Answer a Paragraph whose text is the receiver."
  52707.  
  52708.     ^Paragraph withText: self!
  52709. asString
  52710.     "Answer a String representation of the textual receiver."
  52711.  
  52712.     ^string!
  52713. asText    
  52714.     "Answer the receiver itself."
  52715.  
  52716.     ^self! !
  52717.  
  52718. !Text methodsFor: 'emphasis'!
  52719. allBold
  52720.     "Force this whole text to be bold."
  52721.  
  52722.     string size = 0 ifTrue: [^self].
  52723.     self emphasizeFrom: 1 to: string size with: 2!
  52724. emphasisAt: characterIndex 
  52725.     "Answer the code for characters in the run beginning at characterIndex."
  52726.  
  52727.     self size = 0 ifTrue: [^1].    "null text tolerates access"
  52728.     ^runs at: characterIndex!
  52729. emphasizeFrom: start to: stop with: emphasis 
  52730.     "Set the emphasis for characters in the interval start to stop."
  52731.  
  52732.     runs _ 
  52733.         runs
  52734.             copyReplaceFrom: start
  52735.             to: stop
  52736.             with: (RunArray new: stop - start + 1 withAll: emphasis)!
  52737. makeBoldFrom: start to: stop
  52738.     ^ self emphasizeFrom: start to: stop with: 2 "bold"!
  52739. makeSelectorBoldIn: aClass
  52740.     "For formatting Smalltalk source code, set the emphasis of that portion of 
  52741.     the receiver's string that parses as a message selector to be bold."
  52742.     | parser |
  52743.     string size = 0 ifTrue: [^self].
  52744.     (parser _ aClass parserClass new) parseSelector: string.
  52745.     self makeBoldFrom: 1 to: (parser endOfLastToken min: string size)!
  52746. runLengthFor: characterIndex 
  52747.     "Answer the count of characters remaining in run beginning with 
  52748.     characterIndex."
  52749.  
  52750.     ^runs runLengthAt: characterIndex! !
  52751.  
  52752. !Text methodsFor: 'printing'!
  52753. printOn: aStream
  52754.  
  52755.     aStream nextPutAll: 'Text for '.
  52756.     string printOn: aStream!
  52757. storeOn: aStream
  52758.  
  52759.     aStream nextPutAll: '(Text string: ';
  52760.         store: string;
  52761.         nextPutAll: ' runs: ';
  52762.         store: runs;
  52763.         nextPut: $)! !
  52764.  
  52765. !Text methodsFor: 'private'!
  52766. runs
  52767.  
  52768.     ^runs!
  52769. setString: aString setRuns: anArray
  52770.  
  52771.     string _ aString.
  52772.     runs _ anArray! !
  52773. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  52774.  
  52775. Text class
  52776.     instanceVariableNames: ''!
  52777.  
  52778. !Text class methodsFor: 'class initialization'!
  52779. initDefaultFontsAndStyle
  52780.     "This provides the system with 10 and 12 'point' serif and sans-serif font 
  52781.     families."
  52782.  
  52783.     | defaultFontArray |    
  52784.     defaultFontArray _ Array new: 12.
  52785.     defaultFontArray at: 1 put: (StrikeFont fromStrike: 'TimesRoman10').
  52786.     defaultFontArray at: 2 put:        "(StrikeFont fromStrike: 'TimesRoman10b')."
  52787.         ((defaultFontArray at: 1) emphasized: 1 named: 'TimesRoman10b').
  52788.     defaultFontArray at: 3 put:        "(StrikeFont fromStrike: 'TimesRoman10i')."
  52789.         ((defaultFontArray at: 1) emphasized: 2 named: 'TimesRoman10i').
  52790.     defaultFontArray at: 4 put: (StrikeFont fromStrike: 'TimesRoman12').
  52791.     defaultFontArray at: 5 put:        "(StrikeFont fromStrike: 'TimesRoman12b')."
  52792.         ((defaultFontArray at: 4) emphasized: 1 named: 'TimesRoman12b').
  52793.     defaultFontArray at: 6 put:        "(StrikeFont fromStrike: 'TimesRoman12i')."
  52794.         ((defaultFontArray at: 4) emphasized: 2 named: 'TimesRoman12i').
  52795.     defaultFontArray at: 7 put: (StrikeFont fromStrike: 'Helvetica10').
  52796.     defaultFontArray at: 8 put:        "(StrikeFont fromStrike: 'Helvetica10b')."
  52797.         ((defaultFontArray at: 7) emphasized: 1 named: 'Helvetica10b').
  52798.     defaultFontArray at: 9 put:        "(StrikeFont fromStrike: 'Helvetica10i')."
  52799.         ((defaultFontArray at: 7) emphasized: 2 named: 'Helvetica10i').
  52800.     defaultFontArray at: 10 put: (StrikeFont fromStrike: 'Helvetica12').
  52801.     defaultFontArray at: 11 put:        "(StrikeFont fromStrike: 'Helvetica12b')."
  52802.         ((defaultFontArray at: 10) emphasized: 1 named: 'Helvetica12b').
  52803.     defaultFontArray at: 12 put:        "(StrikeFont fromStrike: 'Helvetica12i')."
  52804.         ((defaultFontArray at: 10) emphasized: 2 named: 'Helvetica12i').
  52805.  
  52806.     TextConstants at: #DefaultTextStyle put:
  52807.         (TextStyle fontArray: defaultFontArray).
  52808.  
  52809.         "Text initDefaultFontsAndStyle."!
  52810. initialize    
  52811.     "Initialize constants shared by classes associated with text display."
  52812.  
  52813.     (Smalltalk includes: TextConstants) 
  52814.         ifFalse: [Smalltalk at: #TextConstants put: (Dictionary new: 32)].
  52815.     TextConstants at: #CaretForm  
  52816.                   put: (Cursor
  52817.     extent: 16@16
  52818.     fromArray: #(
  52819.         2r00110000000
  52820.         2r00110000000
  52821.         2r01111000000
  52822.         2r11111100000
  52823.         2r11001100000
  52824.         2r0
  52825.         2r0
  52826.         2r0
  52827.         2r0
  52828.         2r0
  52829.         2r0
  52830.         2r0
  52831.         2r0
  52832.         2r0
  52833.         2r0
  52834.         2r0)
  52835.     offset: 8@0).
  52836.  
  52837.     self initTextConstants.
  52838.     self initDefaultFontsAndStyle
  52839.  
  52840.     "Text initialize"!
  52841. initTextConstants 
  52842.     "Initialize constants shared by classes associated with text display, e.g., 
  52843.     Space, Tab, Cr, Bs, ESC."
  52844.         "1/24/96 sw: in exasperation and confusion, changed cmd-g mapping from 231 to 232 to see if I could gain any relief?!!"
  52845.  
  52846.  
  52847.     | letter varAndValue tempArray width |
  52848.     "CtrlA..CtrlZ, Ctrla..Ctrlz"
  52849.     letter _ $A.
  52850.      #(        212 230 228 196 194 226 241 243 214 229 200 217 246 
  52851.             245 216 202 210 239 211 240 197 198 209 215 242 231
  52852.              1 166 228 132 130 12 232 179 150 165 136 153 182 
  52853.             14 15 138 17 18 19 11 21 134 145 151 178 167 ) do:
  52854.         [:kbd |
  52855.         TextConstants at: ('Ctrl', letter asSymbol) asSymbol put: kbd asCharacter.
  52856.         letter _ letter == $Z ifTrue: [$a] ifFalse: [(letter asciiValue + 1) asCharacter]].
  52857.  
  52858.     varAndValue _ #(
  52859.         Space    32
  52860.         Tab        9
  52861.         CR        13
  52862.         Enter    3
  52863.         BS        8
  52864.         BS2        158
  52865.         ESC        160
  52866.         Clear     173
  52867.     ).
  52868.  
  52869.     varAndValue size odd ifTrue: [self notify: 'unpaired text constant'].
  52870.     (2 to: varAndValue size by: 2) do:
  52871.         [:i | TextConstants at: (varAndValue at: i - 1) put: (varAndValue at: i) asCharacter].
  52872.  
  52873.     varAndValue _ #(
  52874.         CtrlDigits             (159 144 143 128 127 129 131 180 149 135)
  52875.         CtrlOpenBrackets    (201 7 218 249 219 15)
  52876.             "lparen gottn by ctrl-_ = 201; should be 213 but can't type that on Mac"
  52877.  
  52878.             "location of non-character stop conditions"
  52879.         EndOfRun    257
  52880.         CrossedX    258
  52881.  
  52882.             "values for alignment"
  52883.         LeftFlush    0
  52884.         RightFlush    1
  52885.         Centered    2
  52886.         Justified    3
  52887.  
  52888.             "subscripts for a marginTabsArray tuple"
  52889.         LeftMarginTab    1
  52890.         RightMarginTab    2
  52891.  
  52892.             "font faces"
  52893.         Basal    0
  52894.         Bold    1
  52895.         Italic    2
  52896.  
  52897.             "in case font doesn't have a width for space character"
  52898.             "some plausible numbers-- are they the right ones?"
  52899.         DefaultSpace            4
  52900.         DefaultTab                24
  52901.         DefaultLineGrid            16
  52902.         DefaultBaseline            12
  52903.         DefaultFontFamilySize    3    "basal, bold, italic"
  52904.     ).
  52905.  
  52906.     varAndValue size odd ifTrue: [self notify: 'unpaired text constant'].
  52907.     (2 to: varAndValue size by: 2) do:
  52908.         [:i | TextConstants at: (varAndValue at: i - 1) put: (varAndValue at: i)].
  52909.  
  52910.     TextConstants at: #DefaultRule    put: Form over.
  52911.     TextConstants at: #DefaultMask    put: Form black.
  52912.  
  52913.     width _ Display width max: 720.
  52914.     tempArray _ Array new: width // DefaultTab.
  52915.     1 to: tempArray size do:
  52916.         [:i | tempArray at: i put: DefaultTab * i].
  52917.     TextConstants at: #DefaultTabsArray put: tempArray.
  52918.     tempArray _ Array new: (width // DefaultTab) // 2.
  52919.     1 to: tempArray size do:
  52920.         [:i | tempArray at: i put: (Array with: (DefaultTab*i) with: (DefaultTab*i))].
  52921.     TextConstants at: #DefaultMarginTabsArray put: tempArray.
  52922.  
  52923. "Text initTextConstants "! !
  52924.  
  52925. !Text class methodsFor: 'instance creation'!
  52926. fromString: aString 
  52927.     "Answer an instance of me whose characters are those of the argument, 
  52928.     aString."
  52929.  
  52930.     ^self string: aString emphasis: 1!
  52931. fromUser
  52932.     "Answer an instance of me obtained by requesting the user to type some 
  52933.     characters into a prompter (a FillInTheBlank object)."
  52934.  
  52935.     | result |
  52936.     FillInTheBlank
  52937.         request: 'Type text followed by carriage return'
  52938.         displayAt: (50@ Display boundingBox height//2)
  52939.         centered: false
  52940.         action: [:result]
  52941.         initialAnswer: ''.
  52942.     ^self fromString: result!
  52943. new: stringSize
  52944.  
  52945.     ^self fromString: (String new: stringSize)!
  52946. string: aString emphasis: code 
  52947.     "Answer an instance of me whose characters are those of the argument, 
  52948.     aString. Use the font whose index into the default TextStyle font array is 
  52949.     code."
  52950.  
  52951.     ^self string: aString runs: (RunArray new: aString size withAll: code)!
  52952. string: aString fontName: fontName 
  52953.     "Answer an instance of me whose characters are those of.
  52954.     Use the font in the default TextStyle named by fontName."
  52955.  
  52956.     ^ self string: aString emphasis:
  52957.         (TextStyle default fontNames indexOf: fontName ifAbsent: [1])! !
  52958.  
  52959. !Text class methodsFor: 'private'!
  52960. string: aString runs: anArray
  52961.  
  52962.     ^self basicNew setString: aString setRuns: anArray! !
  52963.  
  52964. Text initialize!
  52965. StringHolder subclass: #TextCollector
  52966.     instanceVariableNames: 'entryStream transcriptOpen '
  52967.     classVariableNames: ''
  52968.     poolDictionaries: ''
  52969.     category: 'Interface-Transcript'!
  52970. TextCollector comment:
  52971. 'I represent a StringHolder into which text can also be gathered by sending messages using Stream protocol.'!
  52972.  
  52973. !TextCollector methodsFor: 'initialize-release'!
  52974. defaultBackgroundColor
  52975.     ^ #lightOrange!
  52976. initialize 
  52977.     "Refer to the comment in StringHolder|initialize."
  52978.  
  52979.     super initialize.
  52980.     transcriptOpen _ false.
  52981.     self beginEntry! !
  52982.  
  52983. !TextCollector methodsFor: 'accessing'!
  52984. next: anInteger put: aCharacter 
  52985.     "Insert the character, aCharacter, at position anInteger in the text."
  52986.  
  52987.     ^entryStream next: anInteger put: aCharacter!
  52988. nextPut: aCharacter 
  52989.     "Append aCharacter to the text."
  52990.  
  52991.     ^entryStream nextPut: aCharacter!
  52992. nextPutAll: aCollection 
  52993.     "Append all the characters in aCollection to the text."
  52994.  
  52995.     ^entryStream nextPutAll: aCollection!
  52996. show: aString 
  52997.     "Append all the characters in aCollection to the text and display the text."
  52998.  
  52999.     self nextPutAll: aString.
  53000.     self endEntry! !
  53001.  
  53002. !TextCollector methodsFor: 'clearing'!
  53003. clear
  53004.     "Re-initialize the text to contain no characters."
  53005.  
  53006.     contents _ Text new.
  53007.     self beginEntry.
  53008.     self changed: #update
  53009.     "Transcript clear"!
  53010. refresh
  53011.     "Bring the window to the front on the screen."
  53012.  
  53013.     self changed: #refresh
  53014.     "Transcript refresh"! !
  53015.  
  53016. !TextCollector methodsFor: 'entry control'!
  53017. appendEntry
  53018.     "Append the text contents of the receiver's WriteStream to its text."
  53019.  
  53020.     contents _ contents , self nextEntry asText.
  53021.     contents size > self characterLimit
  53022.         ifTrue: [contents _ 
  53023.                     contents 
  53024.                         copyFrom: contents size - (self characterLimit // 2)
  53025.                         to: contents size].
  53026.     self beginEntry!
  53027. beginEntry
  53028.     "To speed up appending information to the receiver, a WriteStream is 
  53029.     maintained. Initialize it."
  53030.  
  53031.     entryStream _ WriteStream on: (String new: 200)!
  53032. endEntry
  53033.     "If the receiver's WriteStream is not empty, then reinitialize it. Send all 
  53034.     depends a message that the streaming has changed."
  53035.  
  53036.     entryStream isEmpty
  53037.         ifFalse: 
  53038.             [self changed: #appendEntry.
  53039.             self beginEntry]!
  53040. nextEntry
  53041.     "Answer the text contents of the receiver's WriteStream."
  53042.  
  53043.     ^entryStream contents! !
  53044.  
  53045. !TextCollector methodsFor: 'character writing'!
  53046. bs
  53047.     "Backspace the Transcript.  Put in at Alan's request 1/31/96 sw"
  53048.     "Transcript bs"
  53049.  
  53050.     contents _ contents copyFrom: 1 to: contents size - 1.
  53051.     self changed: #update!
  53052. cr
  53053.     "Append a carriage return to the text."
  53054.  
  53055.     ^entryStream cr!
  53056. crtab
  53057.     "Append a carriage return and a tab to the text."
  53058.  
  53059.     ^entryStream crtab!
  53060. crtab: anInteger 
  53061.     "Append a carriage return and anInteger number of tabs to the text."
  53062.  
  53063.     ^entryStream crtab: anInteger!
  53064. space
  53065.     "Append a space to the text."
  53066.  
  53067.     ^entryStream space!
  53068. tab
  53069.     "Append a tab to the text."
  53070.  
  53071.     ^entryStream tab! !
  53072.  
  53073. !TextCollector methodsFor: 'printing'!
  53074. print: anObject 
  53075.     "Append a description of the object, anObject, to the text."
  53076.  
  53077.     ^entryStream print: anObject!
  53078. store: anObject 
  53079.     "Append a description of the object, anObject, to the text. The description 
  53080.     can be evaluated in order to create an object like anObject."
  53081.  
  53082.     anObject storeOn: self! !
  53083.  
  53084. !TextCollector methodsFor: 'close'!
  53085. okToChange
  53086.     "remove self from ScreenController's list of Transcripts then return super okToChange"
  53087.     transcriptOpen _ false.
  53088.     ^super okToChange! !
  53089.  
  53090. !TextCollector methodsFor: 'private'!
  53091. aTranscriptIsOpen
  53092.     transcriptOpen _ true!
  53093. characterLimit
  53094.  
  53095.     ^5000!
  53096. transcriptOpen
  53097.     ^transcriptOpen! !
  53098. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  53099.  
  53100. TextCollector class
  53101.     instanceVariableNames: ''!
  53102.  
  53103. !TextCollector class methodsFor: 'system'!
  53104. newTranscript: aTextCollector 
  53105.     "Store aTextCollector as the value of the system global Transcript."
  53106.  
  53107.     Smalltalk at: #Transcript put: aTextCollector! !
  53108.  
  53109. !TextCollector class methodsFor: 'examples'!
  53110. example
  53111.     "TextCollectors support WriteStream protocol for appending characters to the
  53112.     System Transcript."
  53113.  
  53114.     Transcript show: (3+4) printString; cr.
  53115.     Transcript nextPutAll: '3+4 ='; space; print: 3+4; cr; endEntry.! !StringHolderController subclass: #TextCollectorController
  53116.     instanceVariableNames: ''
  53117.     classVariableNames: ''
  53118.     poolDictionaries: ''
  53119.     category: 'Interface-Transcript'!
  53120. TextCollectorController comment:
  53121. 'I am a kind of StringHolderController (a ParagraphEditor that adds the doIt, printIt, accept, and cancel commands). I do not change the yellow button menu. I do add methods for accepting text that was generated from Stream-like messages to the model, aTextCollector.'!
  53122.  
  53123. !TextCollectorController methodsFor: 'entry control'!
  53124. appendEntry
  53125.     "Append the text in the model's writeStream to the editable text. "
  53126.     
  53127.     view topView isCollapsed
  53128.         ifTrue: [paragraph text
  53129.                 replaceFrom: 1
  53130.                 to: paragraph text size
  53131.                 with: model contents asText]
  53132.         ifFalse: 
  53133.             [self deselect.
  53134.             paragraph text size > model characterLimit ifTrue: 
  53135.                 [paragraph removeFirstChars: paragraph text size - (model characterLimit // 2)].
  53136.             self selectWithoutComp: paragraph text size + 1.
  53137.             self replaceSelectionWith: model nextEntry asText.
  53138.             self selectWithoutComp: paragraph text size + 1.
  53139.             self selectAndScroll.
  53140.             self deselect.
  53141.             model contents: paragraph text]!
  53142. changeText: aText 
  53143.     "The paragraph to be edited is changed to aText."
  53144.  
  53145.     paragraph text: aText.
  53146.     self resetState.
  53147.     self selectWithoutComp: paragraph text size + 1.
  53148.     self selectAndScroll.
  53149.     self deselect.
  53150.     view displayView! !
  53151.  
  53152. !TextCollectorController methodsFor: 'private'!
  53153. selectWithoutComp: characterIndex
  53154.  
  53155.     startBlock _ paragraph characterBlockForIndex: characterIndex.
  53156.     stopBlock _ startBlock copy! !StringHolderView subclass: #TextCollectorView
  53157.     instanceVariableNames: ''
  53158.     classVariableNames: ''
  53159.     poolDictionaries: ''
  53160.     category: 'Interface-Transcript'!
  53161. TextCollectorView comment:
  53162. 'I am a StringHolderView of the description of the contents of a TextCollector or Transcript. TextCollectorController is my default controller.'!
  53163.  
  53164. !TextCollectorView methodsFor: 'updating'!
  53165. update: aParameter
  53166.     "Transcript cr; show: 'qwre'.    Transcript clear."
  53167.     aParameter == #appendEntry ifTrue:
  53168.         [(self controller isKindOf: TextCollectorController) ifTrue: 
  53169.             [^ ScheduledControllers bring: self topView controller
  53170.                 nextToTopFor: [controller appendEntry]]].
  53171.     aParameter == #update ifTrue:
  53172.         [(self controller isKindOf: TextCollectorController) ifTrue: 
  53173.             [^ ScheduledControllers bring: self topView controller
  53174.                 nextToTopFor: [controller changeText: model contents asText]]].
  53175.     ^ super update: aParameter! !
  53176.  
  53177. !TextCollectorView methodsFor: 'controller access'!
  53178. defaultControllerClass
  53179.     ^ TextCollectorController! !
  53180. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  53181.  
  53182. TextCollectorView class
  53183.     instanceVariableNames: ''!
  53184.  
  53185. !TextCollectorView class methodsFor: 'instance creation'!
  53186. open
  53187.     "Create and schedule an instance of me on a new TextCollector."
  53188.  
  53189.     ^self open: TextCollector new label: 'TextCollector' !
  53190. open: aTextCollector label: aString 
  53191.     "Answer an instance of me on the argument, aTextCollector. The
  53192.     label of the StandardSystemView should be aString."
  53193.     | topView aView |
  53194.     topView _ StandardSystemView new.
  53195.     topView model: aTextCollector.
  53196.     topView label: aString.
  53197.     topView minimumSize: 100 @ 50.
  53198.     aView _ self new model: aTextCollector.
  53199.     aView borderWidth: 2.
  53200.     topView addSubView: aView.
  53201.     topView controller open! !Interval subclass: #TextLineInterval
  53202.     instanceVariableNames: 'internalSpaces paddingWidth '
  53203.     classVariableNames: ''
  53204.     poolDictionaries: 'TextConstants '
  53205.     category: 'Graphics-Support'!
  53206. TextLineInterval comment:
  53207. 'My instances specify the starting and stopping points in a String of a composed line. The step is always 1.'!
  53208.  
  53209. !TextLineInterval methodsFor: 'accessing'!
  53210. internalSpaces
  53211.     "Answer the number of spaces in the line."
  53212.  
  53213.     ^internalSpaces!
  53214. internalSpaces: spacesInteger 
  53215.     "Set the number of spaces in the line to be spacesInteger."
  53216.  
  53217.     internalSpaces _ spacesInteger!
  53218. paddingWidth
  53219.     "Answer the amount of space to be added to the font."
  53220.  
  53221.     ^paddingWidth!
  53222. paddingWidth: padWidthInteger 
  53223.     "Set the amount of space to be added to the font to be padWidthInteger."
  53224.  
  53225.     paddingWidth _ padWidthInteger!
  53226. stop: stopInteger 
  53227.     "Set the stopping point in the string of the line to be stopInteger."
  53228.  
  53229.     stop _ stopInteger! !
  53230.  
  53231. !TextLineInterval methodsFor: 'comparing'!
  53232. = line
  53233.  
  53234.     self species = line species
  53235.         ifTrue: [^((start = line first and: [stop = line last])
  53236.                 and: [internalSpaces = line internalSpaces])
  53237.                 and: [paddingWidth = line paddingWidth]]
  53238.         ifFalse: [^false]! !
  53239.  
  53240. !TextLineInterval methodsFor: 'scanning'!
  53241. justifiedPadFor: spaceIndex 
  53242.     "Compute the width of pad for a given space in a line of justified text."
  53243.  
  53244.     | pad |
  53245.     internalSpaces = 0 ifTrue: [^0].
  53246.     pad _ paddingWidth // internalSpaces.
  53247.     spaceIndex <= (paddingWidth \\ internalSpaces)
  53248.         ifTrue: [^pad + 1]
  53249.         ifFalse: [^pad]!
  53250. justifiedTabDeltaFor: spaceIndex 
  53251.     "Compute the delta for a tab in a line of justified text, so tab falls 
  53252.     somewhere plausible when line is justified."
  53253.  
  53254.     | pad extraPad |
  53255.     internalSpaces = 0 ifTrue: [^0].
  53256.     pad _ paddingWidth // internalSpaces.
  53257.     extraPad _ paddingWidth \\ internalSpaces.
  53258.     spaceIndex <= extraPad
  53259.         ifTrue: [^spaceIndex * (pad + 1)]
  53260.         ifFalse: [^extraPad * (pad + 1) + (spaceIndex - extraPad * pad)]! !
  53261.  
  53262. !TextLineInterval methodsFor: 'updating'!
  53263. slide: delta 
  53264.     "Change the starting and stopping points of the line by delta."
  53265.  
  53266.     start _ start + delta.
  53267.     stop _ stop + delta! !
  53268.  
  53269. !TextLineInterval methodsFor: 'private'!
  53270. internalSpaces: spacesInteger paddingWidth: padWidthInteger
  53271.  
  53272.     internalSpaces _ spacesInteger.
  53273.     paddingWidth _ padWidthInteger! !
  53274. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  53275.  
  53276. TextLineInterval class
  53277.     instanceVariableNames: ''!
  53278.  
  53279. !TextLineInterval class methodsFor: 'instance creation'!
  53280. start: startInteger stop: stopInteger internalSpaces: spacesInteger paddingWidth: padWidthInteger
  53281.     "Answer an instance of me with the arguments as the start, stop points, 
  53282.     number of spaces in the line, and width of the padding."
  53283.  
  53284.     | newSelf |
  53285.     newSelf _ super from: startInteger to: stopInteger by: 1.
  53286.     ^newSelf internalSpaces: spacesInteger paddingWidth: padWidthInteger! !Object subclass: #TextStyle
  53287.     instanceVariableNames: 'fontArray fontFamilySize lineGrid baseline alignment firstIndent restIndent rightIndent tabsArray marginTabsArray '
  53288.     classVariableNames: ''
  53289.     poolDictionaries: 'TextConstants '
  53290.     category: 'Graphics-Support'!
  53291. TextStyle comment:
  53292. 'Formatting information for the composing and displaying of text.'!
  53293.  
  53294. !TextStyle methodsFor: 'accessing'!
  53295. alignment
  53296.     "Answer the code for the current setting of the alignment."
  53297.  
  53298.     ^alignment!
  53299. alignment: anInteger 
  53300.     "Set the current setting of the alignment to be anInteger:
  53301.     0=left flush, 1=centered, 2=right flush, 3=justified."
  53302.  
  53303.     alignment _ anInteger \\ (Justified + 1)!
  53304. baseline
  53305.     "Answer the distance from the top of the line to the bottom of most of the 
  53306.     characters (by convention, bottom of the letter 'A')."
  53307.  
  53308.     ^baseline!
  53309. baseline: anInteger 
  53310.     "Set the distance from the top of the line to the bottom of most of the 
  53311.     characters."
  53312.  
  53313.     baseline _ anInteger!
  53314. defaultFont
  53315.     "Answer the first font in the font family."
  53316.  
  53317.     ^fontArray at: 1!
  53318. firstIndent
  53319.     "Answer the horizontal indenting of the first line of a paragraph in the 
  53320.     style of the receiver."
  53321.  
  53322.     ^firstIndent!
  53323. firstIndent: anInteger 
  53324.     "Set the horizontal indenting of the first line of a paragraph in the style 
  53325.     of the receiver to be the argument, anInteger."
  53326.  
  53327.     firstIndent _ anInteger!
  53328. fontFamilySize
  53329.     "Answer the number of emphasis changes of the fonts in the receiver's 
  53330.     font family."
  53331.  
  53332.     ^fontFamilySize!
  53333. fontFamilySize: anInteger 
  53334.     "Set the number of emphasis changes of the fonts in the receiver's font 
  53335.     family."
  53336.  
  53337.     fontFamilySize _ anInteger!
  53338. fontNamed: fontName  "TextStyle default fontNamed: 'TimesRoman10'"
  53339.     ^ fontArray detect: [:x | x name sameAs: fontName]!
  53340. fontNames  "TextStyle default fontNames"
  53341.     ^ fontArray collect: [:x | x name]!
  53342. lineGrid
  53343.     "Answer the relative space between lines of a paragraph in the style of 
  53344.     the receiver."
  53345.  
  53346.     ^lineGrid!
  53347. lineGrid: anInteger 
  53348.     "Set the relative space between lines of a paragraph in the style of the 
  53349.     receiver to be the argument, anInteger."
  53350.  
  53351.     lineGrid _ anInteger!
  53352. restIndent
  53353.     "Answer the indent for all but the first line of a paragraph in the style 
  53354.     of the receiver."
  53355.  
  53356.     ^restIndent!
  53357. restIndent: anInteger 
  53358.     "Set the indent for all but the first line of a paragraph in the style of the 
  53359.     receiver to be the argument, anInteger."
  53360.  
  53361.     restIndent _ anInteger!
  53362. rightIndent
  53363.     "Answer the right margin indent for the lines of a paragraph in the style 
  53364.     of the receiver."
  53365.  
  53366.     ^rightIndent!
  53367. rightIndent: anInteger 
  53368.     "Answer the right margin indent for the lines of a paragraph in the style 
  53369.     of the receiver to be the argument, anInteger."
  53370.  
  53371.     rightIndent _ anInteger! !
  53372.  
  53373. !TextStyle methodsFor: 'tabs and margins'!
  53374. clearIndents
  53375.     "Reset all the margin (index) settings to be 0."
  53376.  
  53377.     self firstIndent: 0.
  53378.     self restIndent: 0.
  53379.     self rightIndent: 0!
  53380. leftMarginTabAt: marginIndex 
  53381.     "Set the 'nesting' level of left margin indents of the paragraph in the 
  53382.     style of the receiver to be the argument, marginIndex."
  53383.  
  53384.     (marginIndex > 0 and: [marginIndex < marginTabsArray size])
  53385.         ifTrue: [^(marginTabsArray at: marginIndex) at: 1]
  53386.         ifFalse: [^0]    
  53387.     "The marginTabsArray is an Array of tuples.  The Array is indexed according 
  53388.     to the marginIndex, the 'nesting' level of the requestor."
  53389. !
  53390. nextTabXFrom: anX leftMargin: leftMargin rightMargin: rightMargin 
  53391.     "Tab stops are distances from the left margin. Set the distance into the 
  53392.     argument, anX, normalized for the paragraph's left margin."
  53393.  
  53394.     | normalizedX tabX |
  53395.     normalizedX _ anX - leftMargin.
  53396.     1 to: tabsArray size do: 
  53397.         [:i | (tabX _ tabsArray at: i) > normalizedX 
  53398.                 ifTrue: [^leftMargin + tabX min: rightMargin]].
  53399.     ^rightMargin!
  53400. rightMarginTabAt: marginIndex 
  53401.     "Set the 'nesting' level of right margin indents of the paragraph in the 
  53402.     style of the receiver to be marginIndex."
  53403.  
  53404.     (marginIndex > 0 and: [marginIndex < marginTabsArray size])
  53405.         ifTrue: [^(marginTabsArray at: marginIndex) at: 2]
  53406.         ifFalse: [^0]
  53407.     "The marginTabsArray is an Array of tuples.  The Array is indexed according 
  53408.     to the marginIndex, the 'nesting' level of the requestor."
  53409. !
  53410. tabWidth
  53411.     "Answer the width of a tab."
  53412.  
  53413.     ^DefaultTab! !
  53414.  
  53415. !TextStyle methodsFor: 'fonts and font indexes'!
  53416. collectionFromFileNamed: fileName
  53417.     "Read the file.  It is an Array of StrikeFonts.  File format is the ReferenceStream version 2 format.  For any fonts with new names, add them to DefaultTextStyle.fontArray.  
  53418.     To write out fonts: (TextStyle default fontArray saveOnFile2).
  53419.     To read: (TextStyle default collectionFromFileNamed: 'new fonts')
  53420. *** Do not remove this method *** 8/19/96 tk"
  53421.  
  53422.     | ff this names |
  53423.     ff _ ReferenceStream fileNamed: fileName.
  53424.     [this _ ff next.
  53425.         this class == SmallInteger ifTrue: ["version number"].
  53426.         this class == Array ifTrue:
  53427.             [(this at: 1) = 'class structure' ifTrue:
  53428.                 ["Verify the shapes of all the classes"
  53429.                 (Smalltalk incomingObjectsClass acceptStructures: this) ifFalse:
  53430.                     [^ ff close]]].    "An error occurred"
  53431.         this class == Array ifTrue:
  53432.             [names _ self fontNames.
  53433.             this do: [:each | each class == StrikeFont ifTrue:
  53434.                 [(names includes: each name) ifFalse:
  53435.                     [fontArray _ fontArray copyWith: each]]]].
  53436.         ff atEnd]  whileFalse.         
  53437.     ff close.!
  53438. flushFonts
  53439.     "Clean out the fonts, an aid when snapshotting claims too many are 
  53440.     holding onto Display."
  53441.  
  53442.     (self confirm: 
  53443. 'flushFonts is very dangerous.
  53444. Are you foolish or clever enough to proceed?')
  53445.         ifTrue: [1 to: fontArray size do: [:index | fontArray at: index put: nil]]
  53446.         ifFalse: [Transcript cr; show: 'flushFonts cancelled']
  53447.  
  53448.     "TextStyle default flushFonts"! !
  53449.  
  53450. !TextStyle methodsFor: 'private'!
  53451. fontArray
  53452.     "Only for writing out fonts, etc.  8/16/96 tk"
  53453.     ^ fontArray!
  53454. fontAt: index 
  53455.     "This is private because no object outside TextStyle should depend on the 
  53456.     representation of the font family in fontArray."
  53457.  
  53458.     ((fontArray atPin: index) isMemberOf: StrikeFont)
  53459.                 ifTrue: [^fontArray atPin: index].
  53460.     ((fontArray at: 1) isMemberOf: StrikeFont)
  53461.                 ifTrue: [^fontArray at: 1].
  53462.     self error: 'No valid fonts in font array'!
  53463. fontAt: index put: font
  53464.     "Automatically grow the array.  8/20/96 tk"
  53465.     index > fontArray size ifTrue: [
  53466.         fontArray _ fontArray, (Array new: index - fontArray size)].
  53467.     fontArray at: index put: font!
  53468. gridForFont: fontIndex withLead: leadInteger 
  53469.     "Force whole style to suit one of its fonts. Assumes only one font referred
  53470.     to by runs."
  53471.  
  53472.     | font |
  53473.     font _ self fontAt: fontIndex.
  53474.     self lineGrid: font height + leadInteger.
  53475.     self baseline: font ascent!
  53476. marginTabAt: marginIndex side: sideIndex 
  53477.     "The marginTabsArray is an Array of tuples.  The Array is indexed
  53478.     according to the marginIndex, the 'nesting' level of the requestor.
  53479.     sideIndex is 1 for left, 2 for right."
  53480.  
  53481.     (marginIndex > 0 and: [marginIndex < marginTabsArray size])
  53482.         ifTrue: [^(marginTabsArray at: marginIndex) at: sideIndex]
  53483.         ifFalse: [^0]!
  53484. newFontArray: anArray
  53485.     "Currently there is no supporting protocol for changing these arrays. If an editor wishes to implement margin setting, then a copy of the default should be stored with these instance variables.  
  53486.     8/20/96 tk, Make size depend on first font."
  53487.  
  53488.     fontArray _ anArray.
  53489.     lineGrid _ (anArray at: 1) lineGrid.    "For whole family"
  53490.     baseline _ (anArray at: 1) ascent + 1.
  53491.     alignment _ 0.
  53492.     firstIndent _ 0.
  53493.     restIndent _ 0.
  53494.     rightIndent _ 0.
  53495.     tabsArray _ DefaultTabsArray.
  53496.     marginTabsArray _ DefaultMarginTabsArray! !
  53497. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  53498.  
  53499. TextStyle class
  53500.     instanceVariableNames: ''!
  53501.  
  53502. !TextStyle class methodsFor: 'instance creation'!
  53503. fontArray: anArray 
  53504.     "Answer an instance of me with fonts those in the argument, anArray."
  53505.  
  53506.     ^self new newFontArray: anArray! !
  53507.  
  53508. !TextStyle class methodsFor: 'constants'!
  53509. default
  53510.     "Answer the system default text style."
  53511.  
  53512.     ^DefaultTextStyle! !Magnitude subclass: #Time
  53513.     instanceVariableNames: 'hours minutes seconds '
  53514.     classVariableNames: ''
  53515.     poolDictionaries: ''
  53516.     category: 'Numeric-Magnitudes'!
  53517. Time comment:
  53518. 'I represent the time of day.'!
  53519.  
  53520. !Time methodsFor: 'accessing'!
  53521. hours
  53522.     "Answer the number of hours the receiver represents."
  53523.  
  53524.     ^hours!
  53525. minutes
  53526.     "Answer the number of minutes the receiver represents."
  53527.  
  53528.     ^minutes!
  53529. seconds
  53530.     "Answer the number of seconds the receiver represents."
  53531.  
  53532.     ^seconds! !
  53533.  
  53534. !Time methodsFor: 'arithmetic'!
  53535. addTime: timeAmount
  53536.     "Answer a Time that is timeInterval after the receiver. timeInterval is an 
  53537.     instance of Date or Time."
  53538.  
  53539.     ^Time fromSeconds: self asSeconds + timeAmount asSeconds!
  53540. subtractTime: timeAmount 
  53541.     "Answer a Time that is timeInterval before the receiver. timeInterval is 
  53542.     an instance of Date or Time."
  53543.  
  53544.     ^Time fromSeconds: self asSeconds - timeAmount asSeconds! !
  53545.  
  53546. !Time methodsFor: 'comparing'!
  53547. < aTime 
  53548.     "Answer whether aTime is earlier than the receiver."
  53549.  
  53550.     hours ~= aTime hours ifTrue: [^hours < aTime hours].
  53551.     minutes ~= aTime minutes ifTrue: [^minutes < aTime minutes].
  53552.     ^seconds < aTime seconds!
  53553. = aTime 
  53554.     "Answer whether aTime represents the same second as the receiver."
  53555.  
  53556.     self species = aTime species
  53557.         ifTrue: [^hours = aTime hours 
  53558.                     & (minutes = aTime minutes) 
  53559.                     & (seconds = aTime seconds)]
  53560.         ifFalse: [^false]!
  53561. hash
  53562.     "Hash must be redefined since = was redefined."
  53563.  
  53564.     ^((hours hash bitShift: 3) bitXor: minutes) bitXor: seconds! !
  53565.  
  53566. !Time methodsFor: 'printing'!
  53567. print24: hr24 on: aStream 
  53568.     "Format is 'hh:mm:ss' or 'h:mm:ss am' "
  53569.     hr24
  53570.     ifTrue:
  53571.         [hours < 10 ifTrue: [aStream nextPutAll: '0'].
  53572.         hours printOn: aStream]
  53573.     ifFalse:
  53574.         [hours > 12
  53575.         ifTrue: [hours - 12 printOn: aStream]
  53576.         ifFalse: [hours < 1
  53577.                 ifTrue: [12 printOn: aStream]
  53578.                 ifFalse: [hours printOn: aStream]]].
  53579.     aStream nextPutAll: (minutes < 10 ifTrue: [':0']
  53580.                                       ifFalse: [':']).
  53581.     minutes printOn: aStream.
  53582.     aStream nextPutAll: (seconds < 10 ifTrue: [':0']
  53583.                                       ifFalse: [':']).
  53584.     seconds printOn: aStream.
  53585.     hr24 ifFalse:
  53586.         [ aStream nextPutAll: (hours < 12 ifTrue: [' am']
  53587.                                         ifFalse: [' pm'])]!
  53588. printOn: aStream 
  53589.     ^ self print24: false on: aStream!
  53590. storeOn: aStream
  53591.  
  53592.     aStream nextPutAll: '(', self class name, ' readFromString: ';
  53593.         print: self printString;
  53594.         nextPut: $)! !
  53595.  
  53596. !Time methodsFor: 'converting'!
  53597. asSeconds
  53598.     "Answer the number of seconds since midnight of the receiver."
  53599.  
  53600.     ^3600 * hours + (60 * minutes + seconds)! !
  53601.  
  53602. !Time methodsFor: 'private'!
  53603. hours: anInteger
  53604.  
  53605.     hours _ anInteger!
  53606. hours: hourInteger minutes: minInteger seconds: secInteger
  53607.  
  53608.     hours _ hourInteger.
  53609.     minutes _ minInteger.
  53610.     seconds _ secInteger! !
  53611. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  53612.  
  53613. Time class
  53614.     instanceVariableNames: ''!
  53615.  
  53616. !Time class methodsFor: 'instance creation'!
  53617. fromSeconds: secondCount 
  53618.     "Answer an instnace of me that is secondCount number of seconds since midnight."
  53619.     | secondsInHour hours secs |
  53620.     secs _ secondCount asInteger.
  53621.     hours _ secs // 3600.
  53622.     secondsInHour _ secs \\ 3600.
  53623.     ^self new hours: hours
  53624.                minutes: secondsInHour // 60
  53625.                seconds: secondsInHour \\ 60!
  53626. now
  53627.     "Answer an instnace of me representing the time right now--this is a 24 
  53628.     hour clock."
  53629.  
  53630.     ^self dateAndTimeNow at: 2!
  53631. readFrom: aStream
  53632.     "Read a Time from the stream in the form:
  53633.         <hour>:<minute>:<second> <am/pm>
  53634.  
  53635.     <minute>, <second> or <am/pm> may be omitted.  e.g. 1:59:30 pm; 8AM; 15:30"
  53636.  
  53637.     | hour minute second |
  53638.     hour _ Integer readFrom: aStream.
  53639.     minute _ 0.
  53640.     second _ 0.
  53641.     (aStream peekFor: $:) ifTrue:
  53642.         [minute _ Integer readFrom: aStream.
  53643.         (aStream peekFor: $:) ifTrue:
  53644.             [second _ Integer readFrom: aStream]].
  53645.     aStream skipSeparators.
  53646.     (aStream atEnd not and: [aStream peek isLetter])
  53647.         ifTrue:
  53648.             [aStream next asLowercase = $p ifTrue: [hour _ hour + 12].
  53649.             (aStream peekFor: $m) ifFalse: [aStream peekFor: $M]].
  53650.     ^self fromSeconds: 60*(60*hour+minute)+second
  53651.  
  53652.     "Time readFrom: (ReadStream on: '2:23:09 pm')"
  53653. ! !
  53654.  
  53655. !Time class methodsFor: 'general inquiries'!
  53656. dateAndTimeNow
  53657.     "Answer a two-element Array of (Date today, Time now)."
  53658.  
  53659.     | secondCount d t |
  53660.     secondCount _ self primSecondsClock.
  53661.     d _ Date fromDays: secondCount // 86400.
  53662.     t _ Time fromSeconds: secondCount \\ 86400.
  53663.     ^ Array with: d with: t!
  53664. millisecondClockValue
  53665.     "Answer the number of milliseconds since the millisecond clock was last 
  53666.     reset or rolled over."
  53667.  
  53668.     ^ self primMillisecondClock!
  53669. millisecondsToRun: timedBlock 
  53670.     "Answer the number of milliseconds timedBlock takes to return its value."
  53671.  
  53672.     | initialMilliseconds |
  53673.     initialMilliseconds _ self millisecondClockValue.
  53674.     timedBlock value.
  53675.     ^self millisecondClockValue - initialMilliseconds!
  53676. totalSeconds
  53677.     "Answer the total seconds from January 1, 1901."
  53678.  
  53679.     ^ self primSecondsClock! !
  53680.  
  53681. !Time class methodsFor: 'private'!
  53682. primMillisecondClock
  53683.     "Primitive. Answer the number of milliseconds since the millisecond clock
  53684.      was last reset or rolled over. Answer zero if the primitive fails.
  53685.      Optional. See Object documentation whatIsAPrimitive."
  53686.  
  53687.     <primitive: 135>
  53688.     ^ 0!
  53689. primSecondsClock
  53690.     "Answer the number of seconds since 00:00 on the morning of
  53691.      January 1, 1901 (a 32-bit unsigned number).
  53692.      Essential. See Object documentation whatIsAPrimitive. "
  53693.  
  53694.     <primitive: 137>
  53695.     self primitiveFailed! !Color subclass: #TranslucentColor
  53696.     instanceVariableNames: 'alpha '
  53697.     classVariableNames: ''
  53698.     poolDictionaries: ''
  53699.     category: 'Graphics-Display Objects'!
  53700. TranslucentColor comment:
  53701. 'A TranslucentColor behaves just like a normal color, except that it will pack its alpha value into the high byte of a 32-bit pixelValue.  This allows creating forms with translucency for use with the alpha blend function of BitBlt.'!
  53702.  
  53703. !TranslucentColor methodsFor: 'equality'!
  53704. = aColor
  53705.     ^ super = aColor and: [aColor alpha = alpha]! !
  53706.  
  53707. !TranslucentColor methodsFor: 'conversions'!
  53708. pixelWordForDepth: depth
  53709.     depth < 32 ifTrue: [^ super pixelWordForDepth: depth].
  53710.     ^ (super pixelWordForDepth: depth) bitOr: (alpha bitShift: 24)! !
  53711.  
  53712. !TranslucentColor methodsFor: 'private'!
  53713. alpha
  53714.     ^ alpha!
  53715. setRgb: rgbValue alpha: alphaValue
  53716.     rgb _ rgbValue.
  53717.     alpha _ (255.0*alphaValue) asInteger min: 255 max: 0! !SwitchController subclass: #TriggerController
  53718.     instanceVariableNames: ''
  53719.     classVariableNames: ''
  53720.     poolDictionaries: ''
  53721.     category: 'Interface-Menus'!
  53722.  
  53723. !TriggerController methodsFor: 'as yet unclassified'!
  53724. controlInitialize 
  53725.     "Do the action upon mouse DOWN.  Don't bother to reverse the view since this the action happens immediately."
  53726.  
  53727.     self viewHasCursor ifTrue: [self sendMessage]!
  53728. controlTerminate 
  53729.     "Do nothing on mouseUp, action is on mouseDown."
  53730.  
  53731.     "view indicatorReverse.  Don't do this since was not changed on mouseDown"  ! !Boolean subclass: #True
  53732.     instanceVariableNames: ''
  53733.     classVariableNames: ''
  53734.     poolDictionaries: ''
  53735.     category: 'Kernel-Objects'!
  53736. True comment:
  53737. 'I represent the logical value true.'!
  53738.  
  53739. !True methodsFor: 'logical operations'!
  53740. & alternativeObject 
  53741.     "Evaluating conjunction -- answer alternativeObject since receiver is true."
  53742.  
  53743.     ^alternativeObject!
  53744. not
  53745.     "Negation--answer false since the receiver is true."
  53746.  
  53747.     ^false!
  53748. | aBoolean 
  53749.     "Evaluating disjunction (OR) -- answer true since the receiver is true."
  53750.  
  53751.     ^self! !
  53752.  
  53753. !True methodsFor: 'controlling'!
  53754. and: alternativeBlock 
  53755.     "Nonevaluating conjunction -- answer the value of alternativeBlock since
  53756.     the receiver is true."
  53757.  
  53758.     ^alternativeBlock value!
  53759. ifFalse: alternativeBlock 
  53760.     "Since the condition is true, the value is the true alternative, which is nil. 
  53761.     Execution does not actually reach here because the expression is compiled 
  53762.     in-line."
  53763.  
  53764.     ^nil!
  53765. ifFalse: falseAlternativeBlock ifTrue: trueAlternativeBlock 
  53766.     "Answer the value of trueAlternativeBlock. Execution does not 
  53767.     actually reach here because the expression is compiled in-line."
  53768.  
  53769.     ^trueAlternativeBlock value!
  53770. ifTrue: alternativeBlock 
  53771.     "Answer the value of alternativeBlock. Execution does not actually 
  53772.     reach here because the expression is compiled in-line."
  53773.  
  53774.     ^alternativeBlock value!
  53775. ifTrue: trueAlternativeBlock ifFalse: falseAlternativeBlock 
  53776.     "Answer with the value of trueAlternativeBlock. Execution does not 
  53777.     actually reach here because the expression is compiled in-line."
  53778.  
  53779.     ^trueAlternativeBlock value!
  53780. or: alternativeBlock 
  53781.     "Nonevaluating disjunction -- answer true since the receiver is true."
  53782.  
  53783.     ^self! !
  53784.  
  53785. !True methodsFor: 'printing'!
  53786. printOn: aStream 
  53787.  
  53788.     aStream nextPutAll: 'true'! !
  53789.  
  53790. !True methodsFor: 'conversion'!
  53791. binaryValue
  53792.     ^1
  53793. ! !Form subclass: #TwoToneForm
  53794.     instanceVariableNames: 'foregroundColor backgroundColor '
  53795.     classVariableNames: ''
  53796.     poolDictionaries: ''
  53797.     category: 'Graphics-Display Objects'!
  53798.  
  53799. !TwoToneForm methodsFor: 'as yet unclassified'!
  53800. colorMap
  53801.     "An Array of Colors, can't go to a Bitmap without knowing the destination depth.  6/24/96 tk"
  53802.     ^ Array with: backgroundColor with: foregroundColor
  53803.  
  53804. "    | fore back |
  53805.     fore _ foregroundColor bitPatternForDepth: depth.
  53806.     back _ backgroundColor bitPatternForDepth: depth.
  53807.     ^ Bitmap with: back first with: fore first.
  53808. "!
  53809. colorMapForDepth: d
  53810.  
  53811.     | fore back |
  53812.     fore _ foregroundColor bitPatternForDepth: d.
  53813.     back _ backgroundColor bitPatternForDepth: d.
  53814.     ^ Bitmap with: back first with: fore first.
  53815. !
  53816. colorMapFrom: sourceForm
  53817.     | map |
  53818.     map _ Bitmap new: (1 bitShift: (sourceForm depth min: 9)).
  53819.     1 to: map size do: [:i | map at: i put: 16rFFFFFFFF].
  53820.     map at: (backgroundColor mapIndexForDepth: sourceForm depth) put: 0.
  53821.     ^ map!
  53822. displayOnPort: port at: location
  53823.     port colorMap: (self colorMapForDepth: port destForm depth);
  53824.         copyForm: self to: location rule: Form over;
  53825.         colorMap: nil!
  53826. foregroundColor: cf backgroundColor: cb
  53827.     foregroundColor _ cf.
  53828.     backgroundColor _ cb!
  53829. fromDisplay: aRectangle 
  53830.     "Copy from the Display, using an appropriate color map"
  53831.  
  53832.     (width = aRectangle width and: [height = aRectangle height])
  53833.         ifFalse: [self extent: aRectangle extent].
  53834.     (BitBlt toForm: self)
  53835.         destOrigin: 0@0;
  53836.         sourceForm: Display;
  53837.         sourceRect: aRectangle;
  53838.         combinationRule: Form over;
  53839.         colorMap: (self colorMapFrom: Display);
  53840.         copyBits! !
  53841. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  53842.  
  53843. TwoToneForm class
  53844.     instanceVariableNames: ''!
  53845.  
  53846. !TwoToneForm class methodsFor: 'as yet unclassified'!
  53847. fromDisplay: aRectangle using: oldForm backgroundColor: backColor
  53848.     "Like fromDisplay: only if oldForm is the right size, copy into it and answer it instead."
  53849.  
  53850.     ((oldForm ~~ nil) and: [oldForm extent = aRectangle extent])
  53851.         ifTrue: [oldForm fromDisplay: aRectangle.
  53852.                  ^ oldForm]
  53853.         ifFalse: [^ self fromDisplay: aRectangle
  53854.                     using: ((self extent: aRectangle extent depth: 1)
  53855.                                 foregroundColor: Display black
  53856.                                 backgroundColor: backColor)]! !Object subclass: #UndefinedObject
  53857.     instanceVariableNames: ''
  53858.     classVariableNames: ''
  53859.     poolDictionaries: ''
  53860.     category: 'Kernel-Objects'!
  53861. UndefinedObject comment:
  53862. 'I describe the behavior of my sole instance, nil. nil represents a prior value for variables that have not been initialized, or for results which are meaningless.'!
  53863.  
  53864. !UndefinedObject methodsFor: 'copying'!
  53865. deepCopy
  53866.     "Only one instance of UndefinedObject should ever be made, so answer 
  53867.     with self."!
  53868. shallowCopy
  53869.     "Only one instance of UndefinedObject should ever be made, so answer 
  53870.     with self."! !
  53871.  
  53872. !UndefinedObject methodsFor: 'printing'!
  53873. printOn: aStream 
  53874.     "Refer to the comment in Object|printOn:." 
  53875.  
  53876.     aStream nextPutAll: 'nil'!
  53877. storeOn: aStream 
  53878.     "Refer to the comment in Object|storeOn:." 
  53879.  
  53880.     aStream nextPutAll: 'nil'! !
  53881.  
  53882. !UndefinedObject methodsFor: 'testing'!
  53883. isExtant
  53884.     ^ false!
  53885. isNil 
  53886.     "Refer to the comment in Object|isNil."
  53887.  
  53888.     ^true!
  53889. notNil 
  53890.     "Refer to the comment in Object|notNil."
  53891.  
  53892.     ^false! !
  53893.  
  53894. !UndefinedObject methodsFor: 'dependents access'!
  53895. addDependent: ignored 
  53896.     "Refer to the comment in Object|addDependent:."
  53897.  
  53898.     self error: 'Nil should not have dependents'!
  53899. release
  53900.     "Nil release is a no-op"!
  53901. suspend
  53902.     "Kills off processes that didn't terminate properly"
  53903.     "Display reverse; reverse."  "<-- So we can catch the suspend bug"
  53904.     Processor terminateActive! !
  53905. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  53906.  
  53907. UndefinedObject class
  53908.     instanceVariableNames: ''!
  53909.  
  53910. !UndefinedObject class methodsFor: 'instance creation'!
  53911. new
  53912.     self error: 'You may not create any more undefined objects--use nil'! !Workspace subclass: #UnsavableWorkspace
  53913.     instanceVariableNames: ''
  53914.     classVariableNames: ''
  53915.     poolDictionaries: ''
  53916.     category: 'System-Support'!
  53917. UnsavableWorkspace comment:
  53918. 'A workspace which will happily go away without hassle when the user dismisses it; used, for example, to hold help messages.  1/17/96 sw'!
  53919.  
  53920. !UnsavableWorkspace methodsFor: 'as yet unclassified'!
  53921. okToChange
  53922.     "1/17/96 sw"
  53923.  
  53924.     ^ true! !
  53925. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  53926.  
  53927. UnsavableWorkspace class
  53928.     instanceVariableNames: ''!
  53929. UnsavableWorkspace class comment:
  53930. 'A workspace whose window will happily close without warning when the user so requests.  Used for throwaway windows.  1/27/96 sw'!
  53931.  
  53932. !UnsavableWorkspace class methodsFor: 'instance creation'!
  53933. labeled: aLabel containing: aString
  53934.     "Open an unsavable workspace with the given label and contents.  1/17/96 sw"
  53935.  
  53936.     StringHolderView open: (self new contents: aString copy) label: aLabel ! !Object subclass: #Utilities
  53937.     instanceVariableNames: ''
  53938.     classVariableNames: 'CommonRequestStrings RecentSubmissions AuthorInitials DirectTextToScreenPoint '
  53939.     poolDictionaries: ''
  53940.     category: 'System-Support'!
  53941. Utilities comment:
  53942. 'A repository for general and miscellaneous utilities; much of what is here are in effect global methods that don''t naturally attach to anything else.  1/96 sw'!
  53943.  
  53944. !Utilities methodsFor: 'no messages'! !
  53945. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  53946.  
  53947. Utilities class
  53948.     instanceVariableNames: ''!
  53949.  
  53950. !Utilities class methodsFor: 'debugging'!
  53951. breakIf: aBoolean announcing: aMessage
  53952.     "If aBoolean is true, halt, with the given message.  1/26/96 sw"
  53953.     aBoolean ifTrue:
  53954.         [self break: aMessage]!
  53955. directTextToScreenPoint
  53956.     "Answer a point at which to put debugging info.  2/14/96 sw"
  53957.     | pointToReturn box nextPoint |
  53958.     DirectTextToScreenPoint == nil ifTrue:
  53959.         [DirectTextToScreenPoint _ 10 @ 10].
  53960.     pointToReturn _ DirectTextToScreenPoint.
  53961.     nextPoint _ DirectTextToScreenPoint + (0 @ 20).
  53962.     box _ DisplayScreen boundingBox.
  53963.     nextPoint v > (box bottom - 30)
  53964.         ifTrue:
  53965.             [nextPoint _ (nextPoint x + 300) @ 10].
  53966.     nextPoint h > (box right - 200)
  53967.         ifTrue:
  53968.             [nextPoint _ 10 @ 10].
  53969.     DirectTextToScreenPoint _ nextPoint.
  53970.     ^ pointToReturn!
  53971. inspectCollection: aCollection notifying: aView
  53972.     aCollection size = 0 
  53973.         ifTrue: [aView notNil 
  53974.             ifTrue: [^ aView flash]
  53975.             ifFalse: [^ self]].
  53976.     aCollection size = 1
  53977.         ifTrue: [aCollection first inspect]
  53978.         ifFalse: [aCollection asArray inspect]!
  53979. performReportingTimeTaken: aBlock withMessage: aString
  53980.     self showInTranscript:  aString, ' ', ((Time millisecondsToRun: aBlock) // 1000) printString, ' seconds.'!
  53981. resetDirectTextToScreenPoint
  53982.     "Reset so that the next time direct-text-to-screen takes place, it will be at the topleft of the screen.  2/14/96 sw"
  53983.     "Utilities resetDirectTextToScreenPoint"
  53984.  
  53985.     DirectTextToScreenPoint _ nil! !
  53986.  
  53987. !Utilities class methodsFor: 'investigations'!
  53988. reportSenderCountsFor: selectorList
  53989.     "Produce a report on the number of senders of each of the selectors in the list.  1/27/96 sw"
  53990.  
  53991.     | total report thisSize |
  53992.     total _ 0.
  53993.     report _ '
  53994. '.
  53995.     selectorList do:
  53996.         [:selector | thisSize _ (Smalltalk allCallsOn: selector) size.
  53997.         report _ report, thisSize printString, Character tab, selector printString, Character cr.
  53998.         total _ total + thisSize].
  53999.     report _ report, '--- ------------------
  54000. '.
  54001.     report _ report, total printString, Character tab, 'TOTAL
  54002. '.
  54003.     ^ report! !
  54004.  
  54005. !Utilities class methodsFor: 'identification'!
  54006. authorInitials
  54007.     "Answer the initials to be used to identify the current code author.  1/18/96 sw"
  54008.  
  54009.     ^ AuthorInitials!
  54010. authorInitials: initials
  54011.     "Set up the author initials for the system.  Used in conjunction with cmd-shift-v to paste an authorship stamp.  1/18/96 sw"
  54012.  
  54013.     "Utilities authorInitials: 'sw'"
  54014.  
  54015.     AuthorInitials _ initials!
  54016. changeStamp
  54017.     "Answer a string to be pasted into source code to mark who changed it and when.  1/17/96 sw"
  54018.     ^ Date today mmddyy, ' ', self authorInitials!
  54019. copyrightNotice
  54020.     ^ 'Copyright 1985-96, Apple Computer, Inc.'!
  54021. dateTimeSuffix
  54022.     "Answer a string which indicates the date and time, intended for use in building fileout filenames, etc.  1/18/96 sw"
  54023.  
  54024.     "Utilities dateTimeSuffix"
  54025.  
  54026.     | dateTime headString tailString |
  54027.     dateTime _ Time dateAndTimeNow.
  54028.     headString _ dateTime first printString copyFrom: 1 to: 6.
  54029.     headString _ headString copyWithout: $ .
  54030.     tailString _ dateTime last printString copyWithout: $:.
  54031.     ^ headString, (tailString copyFrom: 1 to: tailString size - 5), (tailString copyFrom: tailString size -1 to: tailString size)! !
  54032.  
  54033. !Utilities class methodsFor: 'support windows'!
  54034. commandKeyMappings
  54035.     ^ self class firstCommentAt: #commandKeyMappings
  54036.  
  54037. "Lower-case command keys
  54038. a    Select all
  54039. b    Browse it
  54040. c    Copy
  54041. d    Do it
  54042. e    Exchange
  54043. f    Find
  54044. g    Find again
  54045. h    Set Search String
  54046. i    Inspect it
  54047. j    Again once
  54048. k    Set font
  54049. l    Cancel
  54050. m    Implementors of it
  54051. n    Senders of it
  54052. o    Spawn
  54053. p    Print it
  54054. q    Query symbol
  54055. r    Recognizer
  54056. s    Save (i.e. accept)
  54057. u    Align
  54058. v    Paste
  54059. w    Delete preceding word
  54060. x    Cut
  54061. y    Swap characters
  54062. z    Undo
  54063.  
  54064. Upper-case command keys (Hold down Cmd & Shift, or Ctrl key)
  54065. A    Advance argument
  54066. B    Browse it in this same browser (in System browsers only)
  54067. C    Compare argument to clipboard
  54068. D    Duplicate
  54069. F    Insert 'ifFalse:'
  54070. J    Again many
  54071. K    Set style
  54072. L    Outdent (move selection one tab-stop left)
  54073. N    References to it
  54074. R    Indent (move selection one tab-stap right)
  54075. S    Search
  54076. T    Insert 'ifTrue:'
  54077. W    Selectors containing it
  54078. V    Paste author's initials
  54079.  
  54080. esc    Select current type-in
  54081.  
  54082. [    Enclose within [ and ], or remove enclosing [ and ]
  54083. (    Enclose within ( and ), or remove enclosing ( and )   NB: use ctrl (
  54084. {    Enclose within { and }, or remove enclosing { and }
  54085. <    Enclose within < and >, or remove enclosing < and >
  54086. '    Enclose within ' and ', or remove enclosing ' and '
  54087. ""    Enclose within "" and "", or remove enclosing "" and ""
  54088.  
  54089. 0    10 point plain serif
  54090. 1    10 point bold serif
  54091. 2    10 point italic serif
  54092.  
  54093. 3    12 point plain serif
  54094. 4    12 point bold serif
  54095. 5    12 point italic serif
  54096.  
  54097. 6    10 point plain sans-serif
  54098. 7    10 point bold sans-serif
  54099.  
  54100. 8    10 point underline serif
  54101. 9    12 point plain sans-serif
  54102.  
  54103. "
  54104.     
  54105. "Answer a string to be presented in a window at user request as a crib sheet for command-key mappings.  2/7/96 sw
  54106. 5/1/96 sw: modified so that the long string lives in a comment, hence doesn't take up memory.  Also, fixed up some of the actual text, and added help for parentheses-enclosing items and text-style controls.
  54107. 5/10/96 sw: added a bunch of changes at JM's suggestion
  54108. 8/11/96 sw: fixed the font sizes, added align & references to it, and help for cmd-shift-B"!
  54109. openCommandKeyHelp
  54110.     "Open a window giving command key help.  1/17/96 sw"
  54111.  
  54112.     "Utilities openCommandKeyHelp"
  54113.  
  54114.     UnsavableWorkspace labeled: 'Command Keys' containing: self commandKeyMappings!
  54115. openStandardWorkspace 
  54116.     "Open up a throwaway workspace with useful expressions in it.  1/22/96 sw.  Title changed 2/4/96 sw"
  54117.     "Utilities openStandardWorkspace"
  54118.  
  54119.     UnsavableWorkspace labeled: ('Useful Expressions ', Date today printString) containing: self standardWorkspaceContents!
  54120. standardWorkspaceContents
  54121.     ^ self class firstCommentAt: #standardWorkspaceContents
  54122.  
  54123.     "Smalltalk recover: 5000.
  54124. (FileStream oldFileNamed: 'DryRot.cs') edit.
  54125. (FileStream oldFileNamed: 'change.cs') fileIn
  54126. ChangeList browseFile: 'Elvis.st'
  54127.  
  54128. TextStyle default fontAt: 7 put: (StrikeFont new readMacFontHex: 'Cairo 18')
  54129.  
  54130. InputState browseAllAccessesTo: 'deltaTime'.
  54131. StandardSystemView doCacheBits  ""restore fast windows mode""
  54132.  
  54133. Symbol selectorsContaining: 'rsCon'.
  54134. Smalltalk browseMethodsWhoseNamesContain: 'screen'.
  54135.  
  54136. Browser newOnClass: Utilities.
  54137. BrowserView browseFullForClass: ControlManager.
  54138.  
  54139. FormView allInstances inspect.
  54140. ScrollController someInstance inspect
  54141.  
  54142. SystemOrganization categoryOfElement: #Controller. 
  54143. Component organization categoryOfElement: #contentView .
  54144.  
  54145. ChangeList browseRecentLog.
  54146. ChangeList browseRecent: 2000.
  54147.  
  54148. StringHolderView openSystemWorkspace. ""edit shared sys workspace""
  54149. Cursor wait showWhile: [Sensor waitButton].
  54150.  
  54151. Smalltalk spaceLeft.
  54152. Symbol instanceCount. 
  54153. Time millisecondsToRun:
  54154.     [Smalltalk allCallsOn: #asOop]
  54155. MessageTally spyOn: [Smalltalk allCallsOn: #asOop].
  54156.  
  54157. "! !
  54158.  
  54159. !Utilities class methodsFor: 'user interface'!
  54160. garbageCollectReportString
  54161.     "Utilities garbageCollectReportString"
  54162.  
  54163.     ^ Smalltalk bytesLeft asStringWithCommas, ' bytes available'
  54164.     !
  54165. informUntilClick: aString  
  54166.     "Present aString to the user, and keep it on screen until user clicks the mouse.  1/22/96 sw"
  54167.  
  54168.     "Utilities informUntilClick: 'Note how this works'"
  54169.     self informUser: aString while: [Sensor anyButtonPressed not]!
  54170. informUser: aString during: aBlock
  54171.     "Put a message above (or below if insufficient room) the cursor.
  54172.      Like informUser:while:, but end when aBlock ends.  9/1/96 di"
  54173.  
  54174.     (PopUpMenu labels: '') displayAt: Sensor cursorPoint
  54175.         withCaption: aString during: [aBlock value]!
  54176. informUser: aString while: aBlock
  54177.     "Put a message above (or below if insufficient room) the cursor.
  54178.      1/22/96 sw"
  54179.  
  54180.     "Utilities informUser: 'How do you do' while: [Sensor anyButtonPressed not]"
  54181.     | cp  |
  54182.     cp _ Sensor cursorPoint.
  54183.     (PopUpMenu labels: '') displayAt: cp
  54184.                 withCaption: aString
  54185.                 during: [[aBlock value] whileTrue]!
  54186. logToUser: aMessage
  54187.     "For now, we just show in the Smalltalk transcript, but when/if we have a permanent user control panel, we could divert such messages to that panel.  sw"
  54188.     self showInTranscript: aMessage.
  54189.     Transcript cr! !
  54190.  
  54191. !Utilities class methodsFor: 'miscellaneous'!
  54192. awaitMouseUpIn: box repeating: doBlock ifSucceed: succBlock
  54193.     "The mouse has gone down in box; track the mouse, inverting the box while it's within, and if, on mouse up, the cursor was still within the box, execute succBlock.  While waiting for the mouse to come up, repeatedly execute doBlock. 5/11/96 sw
  54194.     6/10/96 sw: call new method that adds extra feature"
  54195.  
  54196.     ^ self awaitMouseUpIn: box whileMouseDownDo: doBlock whileMouseDownInsideDo: [] ifSucceed: succBlock!
  54197. awaitMouseUpIn: box whileMouseDownDo: doBlock1 whileMouseDownInsideDo: doBlock2 ifSucceed: succBlock
  54198.     "The mouse has gone down in box; track the mouse, inverting the box while it's within, and if, on mouse up, the cursor was still within the box, execute succBlock.  While waiting for the mouse to come up, repeatedly execute doBlock1, and also, if the cursor is within the box, execute doBlock2.  6/10/96 sw"
  54199.  
  54200.     | p inside lightForm darkForm |
  54201.  
  54202.     p _ Sensor cursorPoint.
  54203.     inside _ box insetBy: 1.
  54204.     lightForm _ Form fromDisplay: inside.
  54205.     darkForm _ lightForm deepCopy reverse.
  54206.     [Sensor anyButtonPressed] whileTrue:
  54207.         [doBlock1 value.
  54208.         (box containsPoint: (p _ Sensor cursorPoint))
  54209.             ifTrue: [doBlock2 value..
  54210.                     darkForm displayAt: inside origin]
  54211.             ifFalse: [lightForm displayAt: inside origin]].
  54212.     (box containsPoint: p)
  54213.         ifTrue: [lightForm displayAt: inside origin.
  54214.                 ^ succBlock value]
  54215. !
  54216. basicMacPatterns
  54217.     ^ #()!
  54218. emergencyCollapse
  54219.     ScheduledControllers screenController emergencyCollapse!
  54220. isObject: anObject memberOfOneOf: aCollectionOfClassnames
  54221.     aCollectionOfClassnames do:
  54222.         [:classname | (anObject isMemberOf: (Smalltalk at: classname)) ifTrue: [^ true]].
  54223.     ^ false!
  54224. keyLike: aString satisfying: aBlock
  54225.     "Return a key like aString that satisfies aBlock.  The block should provide a test for acceptability -- typically the test is about whether the key is already in use.  aBlock should return a boolean.  8/11/96 sw"
  54226.  
  54227.     | stemAndSuffix suffix stem newKey |
  54228.     (aBlock value: aString) ifTrue: [^ aString].
  54229.     stemAndSuffix _ aString stemAndNumericSuffix.
  54230.     suffix _ stemAndSuffix last + 1.
  54231.     stem _ stemAndSuffix first.
  54232.     [aBlock value: (newKey _ stem, suffix printString)]
  54233.         whileFalse:
  54234.             [suffix _ suffix + 1].
  54235.     ^ newKey
  54236. !
  54237. keyLike: aString withTrailing: trailerString satisfying: aBlock
  54238.     "Return a key like (aString, trailerString) that satisfies aBlock.  The block should provide a test for acceptability -- typically the test is about whether the key is already in use.  aBlock should return a boolean.  8/11/96 sw"
  54239.  
  54240.     | stemAndSuffix suffix stem composite |
  54241.     composite _ aString, trailerString.
  54242.     (aBlock value: composite) ifTrue: [^ composite].
  54243.     stemAndSuffix _ aString stemAndNumericSuffix.
  54244.     suffix _ stemAndSuffix last + 1.
  54245.     stem _ stemAndSuffix first.
  54246.     [aBlock value: (composite _ stem, suffix printString, trailerString)]
  54247.         whileFalse:
  54248.             [suffix _ suffix + 1].
  54249.     ^ composite
  54250. !
  54251. nextClockwiseSideAfter: aSide
  54252.      aSide == #left ifTrue:
  54253.         [^ #top].
  54254.     aSide == #right ifTrue:
  54255.         [^ #bottom].
  54256.     aSide == #top ifTrue:
  54257.         [^ #right].
  54258.     ^ #left!
  54259. oppositeCornerFrom: aCorner
  54260.     "Answer the corner diagonally opposite to aCorner.  6/27/96 sw"
  54261.  
  54262.     aCorner == #topLeft
  54263.         ifTrue:
  54264.             [^ #bottomRight].
  54265.     aCorner == #topRight
  54266.         ifTrue:
  54267.             [^ #bottomLeft].
  54268.     aCorner == #bottomLeft
  54269.         ifTrue:
  54270.             [^ #topRight].
  54271.     ^ #topLeft!
  54272. oppositeModeTo: aMode
  54273.      aMode == #readOnly ifTrue: [^ #writeOnly].
  54274.     aMode == #writeOnly ifTrue: [^ #readOnly].
  54275.     ^ aMode!
  54276. oppositeSideTo: aSide
  54277.      aSide == #left ifTrue:
  54278.         [^ #right].
  54279.     aSide == #right ifTrue:
  54280.         [^ #left].
  54281.     aSide == #top ifTrue:
  54282.         [^ #bottom].
  54283.     ^ #top!
  54284. setClassAndSelectorFrom: messageIDString in: csBlock
  54285.     "Decode strings of the form <className> [class] <selectorName>.  Derived from method setClassAndSelectorIn: of class MessageSet.  6/28/96 sw"
  54286.  
  54287.     | aStream aClass maybeClass sel |
  54288.     aStream _ ReadStream on: messageIDString.
  54289.     aClass _ Smalltalk at: (aStream upTo: $ ) asSymbol.
  54290.     maybeClass _ aStream upTo: $ .
  54291.     sel _ aStream upTo: $ .
  54292.     (maybeClass = 'class') & (sel size ~= 0)
  54293.         ifFalse: [csBlock value: aClass value: maybeClass asSymbol]
  54294.         ifTrue: [csBlock value: aClass class value: sel asSymbol]
  54295.  
  54296. "
  54297. Utilities setClassAndSelectorFrom: 'Utilities class oppositeModeTo:' in: [:aClass :aSelector | Transcript cr; show: 'Class = ', aClass name printString, ' selector = ', aSelector printString].
  54298.  
  54299. Utilities setClassAndSelectorFrom: 'MessageSet setClassAndSelectorIn:' in: [:aClass :aSelector | Transcript cr; show: 'Class = ', aClass name printString, ' selector = ', aSelector printString].
  54300. "
  54301. ! !
  54302.  
  54303. !Utilities class methodsFor: 'common requests'!
  54304. editCommonRequestStrings
  54305.     "Let the user edit the common request strings.  2/1/96 sw"
  54306.  
  54307.     StringHolderView open: CommonRequestStrings label: 'Common Request Strings'!
  54308. evaluate: aString in: aContext to: aReceiver
  54309.     "evaluate aString in the given context, and return the result.  2/2/96 sw"
  54310.     | result |
  54311.     result _ Compiler new
  54312.                 evaluate: aString
  54313.                 in: aContext
  54314.                 to: aReceiver
  54315.                 notifying: nil
  54316.                 ifFail: [^ #failedDoit].
  54317.     ^ result!
  54318. initialize
  54319.     "Initialize the class variables.  5/16/96 sw"
  54320.     self initializeCommonRequestStrings.
  54321.     RecentSubmissions _ OrderedCollection new!
  54322. initializeCommonRequestStrings
  54323.     "Initialize an array of common request strings.  2/1/96 sw
  54324.      5/10/96 sw: converted over to new format of StringHolder"
  54325.  
  54326.     CommonRequestStrings _ StringHolder new contents: 
  54327. 'Sensor keyboard
  54328. Curor normal show
  54329. Transcript cr; show: ''testing''
  54330. Smalltalk sendersOf: #hot
  54331. Utilities emergencyCollapse
  54332. CharRecog reinitializeCharacterDictionary'
  54333.  
  54334. "Utilities initializeCommonRequestStrings"!
  54335. offerCommonRequests
  54336.     "Offer up the common-requests menu.  If the user chooses one, then evaluate it, and -- provided the value is anumber or string -- show it in the Transcript.  Revised technique 5/10/96 sw as per a suggestion from JM
  54337.     6/6/96 sw: bug fix: if no choice, don't treat it as if the first item was chosen"
  54338.  
  54339.     "Utilities offerCommonRequests"
  54340.  
  54341.     | reply result aMenu index normalItemCount strings |
  54342.  
  54343.     (CommonRequestStrings == nil or: [CommonRequestStrings isKindOf: Array])
  54344.         ifTrue:
  54345.             [self initializeCommonRequestStrings].
  54346.     strings _ CommonRequestStrings contents.
  54347.     normalItemCount _ strings lineCount.
  54348.     aMenu _ PopUpMenu labels: (strings, '
  54349. edit this menu') lines: (Array with: normalItemCount).
  54350.  
  54351.     index _ aMenu startUp.
  54352.     index == 0 ifTrue: [^ self].
  54353.     reply _ aMenu labelString lineNumber: index.
  54354.     reply size == 0 ifTrue: [^ self].
  54355.     index > normalItemCount ifTrue:
  54356.         [^ self editCommonRequestStrings].
  54357.  
  54358.     result _ self evaluate: reply in: nil to: nil.
  54359.     (result isKindOf: Number) | (result isKindOf: String)
  54360.         ifTrue:
  54361.             [Transcript cr; nextPutAll: result printString]! !
  54362.  
  54363. !Utilities class methodsFor: 'recent method submissions'!
  54364. browseRecentSubmissions
  54365.     "Open up a browser on the most recent methods submitted in the image.  5/96 sw.
  54366.     5/29/96 sw: fixed so the browser doesn't go all wonkie after you submit more code"
  54367.  
  54368.     "Utilities browseRecentSubmissions"
  54369.     | count |
  54370.     (count _ self recentMethodSubmissions size) == 0 ifTrue:
  54371.         [^ self notify: 'There are no recent submissions'].
  54372.     
  54373.     Smalltalk browseMessageList: RecentSubmissions copy name: 'Recently submitted methods -- oldest first' autoSelect: nil !
  54374. noteMethodSubmission: selectorName forClass: className
  54375.     | aSubmission |
  54376.     aSubmission _ className asString, ' ', selectorName.
  54377.     (self recentMethodSubmissions includes: aSubmission)
  54378.         ifTrue:
  54379.             [RecentSubmissions remove: aSubmission]
  54380.         ifFalse:
  54381.             [(RecentSubmissions size >= self numberOfRecentSubmissionsToStore) 
  54382.                 ifTrue: [RecentSubmissions removeFirst]].
  54383.     RecentSubmissions addLast: aSubmission!
  54384. numberOfRecentSubmissionsToStore
  54385.     "Answer how many methods back the 'recent method submissions' history should store.  5/16/96 sw"
  54386.  
  54387.     ^ 20!
  54388. recentMethodSubmissions
  54389.     "Answer the list of recent method submissions, in order.  5/16/96 sw"
  54390.  
  54391.     RecentSubmissions == nil ifTrue: [RecentSubmissions _ OrderedCollection new].
  54392.     ^ RecentSubmissions! !
  54393.  
  54394. !Utilities class methodsFor: 'graphical support'!
  54395. showFormsAcrossTopOfScreen: aFormList
  54396.     "Display the given array of forms across the top of the screen, wrapping to subsequent lines if needed.    Useful for example for looking at sets of rotations and animations.  6/10/96 sw"
  54397.  
  54398.     | position maxHeight screenBox ceiling |
  54399.  
  54400.     position _ 20.
  54401.     maxHeight _ 0.
  54402.     ceiling _ 0.
  54403.     screenBox _ Display boundingBox.
  54404.     aFormList do:
  54405.         [:elem | elem displayAt: (position @ ceiling).
  54406.             maxHeight _ maxHeight max: elem boundingBox height.
  54407.             position _ position + elem boundingBox width + 5.
  54408.             position > (screenBox right - 100) ifTrue:
  54409.                 [position _ 20.
  54410.                 ceiling _ ceiling + maxHeight + 10.
  54411.                 maxHeight _ 0]]!
  54412. showFormsDictAcrossTopOfScreen: formDict
  54413.     "Display the given Dictionary of forms across the top of the screen, wrapping to subsequent lines if needed.  Beneath each, put the name of the associated key."
  54414.  
  54415.     "Utilities showFormsDictAcrossTopOfScreen: HaloIcons"
  54416.  
  54417.     | position maxHeight screenBox ceiling elem box h labelWidth keyString |
  54418.  
  54419.     position _ 20.
  54420.     maxHeight _ 0.
  54421.     ceiling _ 0.
  54422.     screenBox _ Display boundingBox.
  54423.     formDict associationsDo:
  54424.         [:assoc | (elem _ assoc value) displayAt: (position @ ceiling).
  54425.             box _ elem boundingBox.
  54426.             h _ box height.
  54427.             keyString _ (assoc key isKindOf: String) ifTrue: [assoc key] ifFalse: [assoc key printString].
  54428.             keyString displayAt: (position @ (ceiling + h)).
  54429.             labelWidth _ keyString asDisplayText boundingBox width.
  54430.             maxHeight _ maxHeight max: h.
  54431.             position _ position + (box width max: labelWidth) + 5.
  54432.             position > (screenBox right - 100) ifTrue:
  54433.                 [position _ 20.
  54434.                 ceiling _ ceiling + maxHeight + 15.
  54435.                 maxHeight _ 0]]! !
  54436.  
  54437. Utilities initialize!
  54438. LeafNode subclass: #VariableNode
  54439.     instanceVariableNames: 'name isArg '
  54440.     classVariableNames: ''
  54441.     poolDictionaries: ''
  54442.     category: 'System-Compiler'!
  54443. VariableNode comment:
  54444. 'I am a parse tree leaf representing a variable. Note that my name and key are different for pool variables: the key is the Object Reference.'!
  54445.  
  54446. !VariableNode methodsFor: 'initialize-release'!
  54447. asStorableNode: encoder
  54448.     ^ self!
  54449. isArg: aBoolean
  54450.  
  54451.     isArg _ aBoolean!
  54452. name: varName index: i type: type
  54453.  
  54454.     self name: varName
  54455.         key: varName
  54456.         index: i
  54457.         type: type!
  54458. name: string key: object code: byte
  54459.  
  54460.     name _ string.
  54461.     key _ object.
  54462.     code _ byte!
  54463. name: varName key: objRef index: i type: type
  54464.  
  54465.     name _ varName.
  54466.     self key: objRef
  54467.         index: i
  54468.         type: type! !
  54469.  
  54470. !VariableNode methodsFor: 'testing'!
  54471. assignmentCheck: encoder at: location
  54472.  
  54473.     ((encoder cantStoreInto: name) or: [self isArg])
  54474.         ifTrue: [^location].
  54475.     ^-1
  54476. !
  54477. canBeSpecialArgument
  54478.     "Can I be an argument of (e.g.) ifTrue:?"
  54479.  
  54480.     ^code < LdNil!
  54481. isArg
  54482.  
  54483.     ^self isTemp and: [isArg==true]!
  54484. isSelfPsuedoVariable
  54485.     "Answer if this ParseNode represents the 'self' psuedo-variable."
  54486.  
  54487.     ^key = 'self'!
  54488. isTemp
  54489.     "Answer true if this describes a temporary variable."
  54490.  
  54491.     code < 0 
  54492.         ifTrue: [^code = LdTempType negated].
  54493.     code > 255
  54494.         ifTrue: [^code 
  54495.                     between: LdTempType * 256 
  54496.                     and: LdTempType * 256 + 255].
  54497.     ^code 
  54498.         between: (CodeBases at: 2)
  54499.         and: (CodeBases at: 2) + (CodeLimits at: 2) - 1!
  54500. isVariableReference
  54501.  
  54502.     ^true! !
  54503.  
  54504. !VariableNode methodsFor: 'code generation'!
  54505. emitForReturn: stack on: strm
  54506.  
  54507.     (code >= LdSelf and: [code <= LdNil])
  54508.         ifTrue: 
  54509.             ["short returns"
  54510.             strm nextPut: EndMethod - 4 + (code - LdSelf).
  54511.             stack push: 1 "doesnt seem right"]
  54512.         ifFalse: 
  54513.             [super emitForReturn: stack on: strm]!
  54514. emitForValue: stack on: strm
  54515.  
  54516.     code < 256
  54517.         ifTrue: 
  54518.             [strm nextPut: (code = LdSuper ifTrue: [LdSelf] ifFalse: [code]).
  54519.             stack push: 1]
  54520.         ifFalse: 
  54521.             [self emitLong: LdInstLong on: strm.
  54522.             stack push: 1]!
  54523. emitStore: stack on: strm
  54524.  
  54525.     self emitLong: Store on: strm!
  54526. emitStorePop: stack on: strm
  54527.  
  54528.     (code between: 0 and: 7)
  54529.         ifTrue: 
  54530.             [strm nextPut: ShortStoP + code "short stopop inst"]
  54531.         ifFalse:
  54532.             [(code between: 16 and: 23)
  54533.                 ifTrue: [strm nextPut: ShortStoP + 8 + code - 16 "short stopop temp"]
  54534.                 ifFalse: [self emitLong: StorePop on: strm]].
  54535.     stack pop: 1!
  54536. sizeForReturn: encoder
  54537.  
  54538.     (code >= LdSelf and: [code <= LdNil])
  54539.         ifTrue: ["short returns" ^1].
  54540.     ^super sizeForReturn: encoder!
  54541. sizeForStore: encoder
  54542.  
  54543.     self reserve: encoder.
  54544.     ^2!
  54545. sizeForStorePop: encoder
  54546.  
  54547.     self reserve: encoder.
  54548.     (code < 24 and: [code noMask: 8])
  54549.         ifTrue: [^1].
  54550.     ^2! !
  54551.  
  54552. !VariableNode methodsFor: 'printing'!
  54553. printOn: aStream indent: level
  54554.  
  54555.     aStream nextPutAll: name! !
  54556.  
  54557. !VariableNode methodsFor: 'equation translation'!
  54558. collectVariables
  54559.     ^Array with: self key!
  54560. copyReplacingVariables: varDict 
  54561.     (key isMemberOf: Symbol)
  54562.         ifTrue: [^(varDict at: key ifAbsent: [^self copy])
  54563.                 copyReplacingVariables: Dictionary new]
  54564.         ifFalse: [^self copy]!
  54565. match: aTree using: matchDict 
  54566.     (key isMemberOf: Symbol)
  54567.         ifTrue: [(matchDict at: key
  54568.                 ifAbsent: 
  54569.                     [matchDict at: key put: aTree.
  54570.                     ^true])
  54571.                 match: aTree using: Dictionary new]
  54572.         ifFalse: [^name = aTree name]!
  54573. moveVariableToFarLeft: aVariable
  54574.     ^self! !
  54575.  
  54576. !VariableNode methodsFor: 'C translation'! !
  54577. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  54578.  
  54579. VariableNode class
  54580.     instanceVariableNames: ''!
  54581.  
  54582. !VariableNode class methodsFor: 'class initialization'!
  54583. initialize
  54584.  
  54585.     | encoder |
  54586.     encoder _ Encoder new.
  54587.     StdVariables _ Dictionary new: 16.
  54588.     encoder
  54589.         fillDict: StdVariables
  54590.         with: VariableNode
  54591.         mapping: #('self' 'thisContext' 'super' 'nil' 'false' 'true' )
  54592.         to: (Array with: LdSelf with: LdThisContext with: LdSuper)
  54593.                 , (Array with: LdNil with: LdFalse with: LdTrue).
  54594.     StdSelectors _ Dictionary new: 64.
  54595.     encoder
  54596.         fillDict: StdSelectors
  54597.         with: SelectorNode
  54598.         mapping: ((1 to: Smalltalk specialSelectorSize) collect: 
  54599.                             [:i | Smalltalk specialSelectorAt: i])
  54600.         to: (SendPlus to: SendPlus + 31).
  54601.     StdLiterals _ LiteralDictionary new: 16.
  54602.     encoder
  54603.         fillDict: StdLiterals
  54604.         with: LiteralNode
  54605.         mapping: #(-1 0 1 2 )
  54606.         to: (LdMinus1 to: LdMinus1 + 3).
  54607.     encoder initScopeAndLiteralTables.
  54608.     self initialize2: encoder
  54609.  
  54610.     "VariableNode initialize. Decompiler initialize"!
  54611. initialize2: encoder 
  54612.  
  54613.     NodeNil _ encoder encodeVariable: 'nil'.
  54614.     NodeTrue _ encoder encodeVariable: 'true'.
  54615.     NodeFalse _ encoder encodeVariable: 'false'.
  54616.     NodeSelf _ encoder encodeVariable: 'self'.
  54617.     NodeThisContext _ encoder encodeVariable: 'thisContext'.
  54618.     NodeSuper _ encoder encodeVariable: 'super'
  54619.  
  54620.     "VariableNode initialize"! !
  54621.  
  54622. VariableNode initialize!
  54623. Object subclass: #View
  54624.     instanceVariableNames: 'model controller superView subViews transformation viewport window displayTransformation insetDisplayBox borderWidth borderColor insideColor boundingBox '
  54625.     classVariableNames: ''
  54626.     poolDictionaries: ''
  54627.     category: 'Interface-Framework'!
  54628. View comment:
  54629. 'My instances are intended to be components in a structured picture. Each View in the structured picture can contain other Views as sub-components. These sub-components are called subViews. A View can be a subView of only one View. This View is called its superView. The set of Views in a structured picture forms a hierarchy. The one View in the hierarchy that has no superView is called the topView of the structured picture. A View in a structured picture with no subViews is called a bottom View. A View and all of its subViews, and all of their subViews and so on, are treated as a unit in many operations on the View. For example, if a View is displayed, all of its subViews are displayed as well. There are several categories of operations that can be performed on a View. Among these are the following:
  54630.     
  54631.     1.    Adding subViews to a View.
  54632.     2.    Positioning subViews within a View.
  54633.     3.    Deleting subViews from a View.
  54634.     4.    Transforming a View.
  54635.     5.    Displaying a View.
  54636.     
  54637. Each View has its own coordinate system. In order to change from one coordinate system to another, each View has two transformations associated with it. The local transformation is a WindowingTransformation that maps objects in the coordinate system of the View to objects in the coordinate system of the superView of the View. The displayTransformation is a WindowingTransformation that maps objects in the coordinate system of the View to objects in the display screen coordinate system.
  54638.     
  54639. The part of the space that is to be made visible is represented by the window of the View. The window of a View is a Rectangle expressed in the coordinate system of the View. The area occupied by a View in the coordinate system of its superView is called its viewport. The viewport of a View is its window transformed by its local transformation. The region of the display screen occupied by a View is called its displayBox. The display box of a View can include a border. The width of the border expressed in display screen coordinates is called the border width of the View. The color of the border is called the border color. The region of the display box of a View excluding the border is called the inset display box. The color of the inset display box is called the inside color of the View.'!
  54640.  
  54641. !View methodsFor: 'initialize-release'!
  54642. initialize
  54643.     "Initialize the state of the receiver. Subclasses should include 'super 
  54644.     initialize' when redefining this message to insure proper initialization."
  54645.  
  54646.     self resetSubViews.
  54647.     transformation _ WindowingTransformation identity.
  54648.     self borderWidth: 0!
  54649. release
  54650.     "Remove the receiver from its model's list of dependents (if the model
  54651.     exists), and release all of its subViews. It is used to break possible cycles
  54652.     in the receiver and should be sent when the receiver is no longer needed.
  54653.     Subclasses should include 'super release.' when redefining release."
  54654.  
  54655.     model removeDependent: self.
  54656.     model _ nil.
  54657.     controller release.
  54658.     controller _ nil.
  54659.     subViews ~~ nil ifTrue: [subViews do: [:aView | aView release]].
  54660.     subViews _ nil.
  54661.     superView _ nil!
  54662. setDefaultBackgroundColor
  54663.     "Obtain the background color from the receiver's model, unless the #uniformWindowColors preference is set to true, in which case obtain it from generic Object; and install it as the receiver's background color.  5/1/96 sw"
  54664.  
  54665.     | colorToUse |
  54666.     colorToUse _ Preferences uniformWindowColors
  54667.         ifTrue:
  54668.             [Object new defaultBackgroundColor]
  54669.         ifFalse:
  54670.             [model defaultBackgroundColor].
  54671.     self backgroundColor: colorToUse! !
  54672.  
  54673. !View methodsFor: 'testing'!
  54674. containsPoint: aPoint 
  54675.     "Answer whether aPoint is within the receiver's display box. It is sent to 
  54676.     a View's subViews by View|subViewAt: in order to determine which 
  54677.     subView contains the cursor point (so that, for example, control can be 
  54678.     pass down to that subView's controller).
  54679.     1/24/96 sw: use insetDisplayBox, so border doesn't count"
  54680.  
  54681.     ^ self insetDisplayBox containsPoint: aPoint!
  54682. isObscured
  54683.  
  54684.     | topController displayRect |
  54685.     (topController _ self topView controller)
  54686.         == ScheduledControllers activeController
  54687.             ifTrue: [^false].
  54688.     displayRect _ self insetDisplayBox.
  54689.     ScheduledControllers scheduledControllers do: [:ctrlr |
  54690.         ctrlr == topController ifTrue: [^false].
  54691.         (displayRect intersects: ctrlr view insetDisplayBox)
  54692.             ifTrue: [^true]].
  54693.     self error: 'not in ScheduledControllers'.
  54694.     ^false! !
  54695.  
  54696. !View methodsFor: 'model access'!
  54697. model
  54698.     "Answer the receiver's model."
  54699.  
  54700.     ^model!
  54701. model: aModel 
  54702.     "Set the receiver's model to aModel. The model of the receiver's controller 
  54703.     is also set to aModel."
  54704.  
  54705.     self model: aModel controller: controller! !
  54706.  
  54707. !View methodsFor: 'superView access'!
  54708. isTopView
  54709.     "Answer whether the receiver is a top view, that is, if it has no 
  54710.     superView."
  54711.  
  54712.     ^superView == nil!
  54713. superView
  54714.     "Answer the superView of the receiver."
  54715.  
  54716.     ^superView!
  54717. topView
  54718.     "Answer the root of the tree of Views in which the receiver is a node. 
  54719.     The root of the tree is found by going up the superView path until 
  54720.     reaching a View whose superView is nil."
  54721.  
  54722.     superView == nil
  54723.         ifTrue: [^self]
  54724.         ifFalse: [^superView topView]! !
  54725.  
  54726. !View methodsFor: 'subView access'!
  54727. firstSubView
  54728.     "Answer the first subView in the receiver's list of subViews if it is not 
  54729.     empty, else nil."
  54730.  
  54731.     subViews isEmpty
  54732.         ifTrue: [^nil]
  54733.         ifFalse: [^subViews first]!
  54734. lastSubView
  54735.     "Answer the last subView in the receiver's list of subViews if it is not 
  54736.     empty, else nil."
  54737.  
  54738.     subViews isEmpty
  54739.         ifTrue: [^nil]
  54740.         ifFalse: [^subViews last]!
  54741. resetSubViews
  54742.     "Set the list of subviews to an empty collection."
  54743.     
  54744.     subViews _ OrderedCollection new!
  54745. subViewContaining: aPoint 
  54746.     "Answer the first subView that contains aPoint within its window and 
  54747.     answer nil, otherwise. It is typically sent from a Controller in order to 
  54748.     determine where to pass control (usually to the Controller of the View 
  54749.     returned by View|subViewContaining:)."
  54750.  
  54751.     subViews reverseDo: 
  54752.         [:aSubView | 
  54753.         (aSubView displayBox containsPoint: aPoint) ifTrue: [^aSubView]].
  54754.     ^nil!
  54755. subViews
  54756.     "Answer the receiver's collection of subViews."
  54757.  
  54758.     ^subViews!
  54759. subViewSatisfying: aBlock
  54760.     "Return the first subview that satisfies aBlock, or nil if none does.  1/31/96 sw"
  54761.  
  54762.     ^ subViews detect: [:aView | aBlock value: aView] ifNone: [nil]!
  54763. textEditorView
  54764.     "Return the first view in the receiver whose controller is a ParagraphEdior, or nil if none.  1/31/96 sw"
  54765.  
  54766.     (controller isKindOf: ParagraphEditor) ifTrue: [^ self].
  54767.     ^ self subViewSatisfying:
  54768.         [:v | v textEditorView ~~ nil]! !
  54769.  
  54770. !View methodsFor: 'controller access'!
  54771. controller
  54772.     "If the receiver's controller is nil (the default case), answer an initialized 
  54773.     instance of the receiver's default controller. If the receiver does not 
  54774.     allow a controller, answer the symbol #NoControllerAllowed."
  54775.  
  54776.     controller == nil ifTrue: [self controller: self defaultController].
  54777.     ^controller!
  54778. controller: aController 
  54779.     "Set the receiver's controller to aController. #NoControllerAllowed can be 
  54780.     specified to indicate that the receiver will not have a controller. The 
  54781.     model of aController is set to the receiver's model."
  54782.  
  54783.     self model: model controller: aController!
  54784. defaultController
  54785.     "Answer an initialized instance of the receiver's default controller. 
  54786.     Subclasses should redefine this message only if the default controller 
  54787.     instances need to be initialized in a nonstandard way."
  54788.  
  54789.     ^self defaultControllerClass new!
  54790. defaultControllerClass
  54791.     "Answer the class of the default controller for the receiver. Subclasses 
  54792.     should redefine View|defaultControllerClass if the class of the default 
  54793.     controller is not Controller."
  54794.  
  54795.     ^Controller!
  54796. model: aModel controller: aController 
  54797.     "Set the receiver's model to aModel, add the receiver to aModel's list of 
  54798.     dependents, and set the receiver's controller to aController. Subsequent 
  54799.     changes to aModel (see Model|change) will result in View|update: 
  54800.     messages being sent to the receiver. #NoControllerAllowed for the value 
  54801.     of aController indicates that no default controller is available; nil for the 
  54802.     value of aController indicates that the default controller is to be used 
  54803.     when needed. If aController is neither #NoControllerAllowed nor nil, its 
  54804.     view is set to the receiver and its model is set to aModel."
  54805.  
  54806.     model ~~ nil & (model ~~ aModel)
  54807.         ifTrue: [model removeDependent: self].
  54808.     aModel ~~ nil & (aModel ~~ model)
  54809.         ifTrue: [aModel addDependent: self].
  54810.     model _ aModel.
  54811.     aController ~~ nil
  54812.         ifTrue: 
  54813.             [aController view: self.
  54814.             aController model: aModel].
  54815.     controller _ aController! !
  54816.  
  54817. !View methodsFor: 'basic control sequence'!
  54818. subViewWantingControl
  54819.     "Answer the first subView that has a controller that now wants control."
  54820.  
  54821.     subViews reverseDo: 
  54822.         [:aSubView | aSubView controller isControlWanted ifTrue: [^aSubView]].
  54823.     ^nil! !
  54824.  
  54825. !View methodsFor: 'window access'!
  54826. defaultWindow
  54827.     "Build the minimum Rectangle that encloses all the windows of the 
  54828.     receiver's subViews. The answer is a Rectangle obtained by expanding 
  54829.     this minimal Rectangle by the borderWidth of the receiver. If the 
  54830.     receiver has no subViews, then a Rectangle enclosing the entire display 
  54831.     screen is answered. It is used internally by View methods if no window 
  54832.     has been specified for the View. Specialized subclasses of View should 
  54833.     redefine View|defaultWindow to handle the default case for instances 
  54834.     that have no subViews."
  54835.  
  54836.     | aRectangle |
  54837.     subViews isEmpty ifTrue: [^DisplayScreen boundingBox].
  54838.     aRectangle _ self firstSubView viewport.
  54839.     subViews do: [:aView | aRectangle _ aRectangle merge: aView viewport].
  54840.     ^aRectangle expandBy: borderWidth!
  54841. insetWindow
  54842.     "Answer a Rectangle that is obtained by insetting the receiver's window 
  54843.     rectangle by the border width."
  54844.  
  54845.     ^self getWindow insetBy: borderWidth!
  54846. window
  54847.     "Answer a copy of the receiver's window."
  54848.  
  54849.     ^self getWindow copy!
  54850. window: aWindow 
  54851.     "Set the receiver's window to a copy of aWindow."
  54852.  
  54853.     self setWindow: aWindow copy! !
  54854.  
  54855. !View methodsFor: 'viewport access'!
  54856. viewport
  54857.     "Answer a copy of the receiver's viewport."
  54858.  
  54859.     ^self getViewport copy! !
  54860.  
  54861. !View methodsFor: 'display box access'!
  54862. apparentDisplayBox
  54863.     ^self insetDisplayBox expandBy: 2 @ 2!
  54864. boundingBox
  54865.     "Answer the bounding box which for the default case is the rectangular 
  54866.     area surrounding the bounding boxes of all the subViews."
  54867.  
  54868.     boundingBox ~~ nil
  54869.         ifTrue: [^boundingBox]
  54870.         ifFalse: [^self computeBoundingBox]!
  54871. computeBoundingBox
  54872.     "Answer the minimum Rectangle that encloses the bounding boxes of the 
  54873.     receiver's subViews. If the receiver has no subViews, then the bounding 
  54874.     box is the receiver's window. Subclasses should redefine 
  54875.     View|boundingBox if a more suitable default for the case of no subViews 
  54876.     is available."
  54877.  
  54878.     | aRectangle |
  54879.     subViews isEmpty ifTrue: [^self getWindow].
  54880.     aRectangle _ self firstSubView transform: self firstSubView boundingBox.
  54881.     subViews do: 
  54882.         [:aView | 
  54883.         aRectangle _ aRectangle merge: (aView transform: aView boundingBox).].
  54884.     ^aRectangle expandBy: borderWidth!
  54885. displayBox
  54886.     "Answer the receiver's inset display box (see View|insetDisplayBox) 
  54887.     expanded by the borderWidth. The display box represents the region of 
  54888.     the display screen in which the receiver (including the border) is 
  54889.     displayed. If the receiver is totally clipped by the display screen and its 
  54890.     superView, the resulting Rectangle will be invalid."
  54891.  
  54892.     ^self insetDisplayBox expandBy: borderWidth!
  54893. insetDisplayBox
  54894.     "Answer the receiver's inset display box. The inset display box is the 
  54895.     intersection of the receiver's window, tranformed to display coordinates, 
  54896.     and the inset display box of the superView, inset by the border width. 
  54897.     The inset display box represents the region of the display screen in 
  54898.     which the inside of the receiver (all except the border) is displayed. If 
  54899.     the receiver is totally clipped by the display screen and its superView, 
  54900.     the resulting Rectangle will be invalid."
  54901.  
  54902.     insetDisplayBox == nil ifTrue: [insetDisplayBox _ self computeInsetDisplayBox].
  54903.     ^insetDisplayBox! !
  54904.  
  54905. !View methodsFor: 'lock access'!
  54906. isLocked
  54907.     "Answer whether the receiver is locked. A View is 'locked' if its display 
  54908.     transformation and inset display box are defined. If these are undefined, 
  54909.     the View is 'unlocked'. The display transformation and inset display box 
  54910.     become undefined when the transformation of the View (or the 
  54911.     transformation of a View in its superView chain) is changed, or when 
  54912.     the superView of the View is changed, or any other change to the View 
  54913.     that affects the display screen coordinates of the View. The locking and 
  54914.     unlocking of a View is handled automatically by the internal methods of 
  54915.     the View, but can also be done explicitly if desired (see View|lock, and 
  54916.     View|unlock)."
  54917.  
  54918.     displayTransformation == nil | (insetDisplayBox == nil)
  54919.         ifTrue: [^false]
  54920.         ifFalse: [^true]!
  54921. isUnlocked
  54922.     "Answer whether the receiver is unlocked. See comment in 
  54923.     View|isLocked."
  54924.  
  54925.     ^displayTransformation == nil & (insetDisplayBox == nil)!
  54926. lock
  54927.     "'Lock' the receiver and all of its subViews (see View|isLocked). This has 
  54928.     the effect of computing and storing the display transformation (see 
  54929.     View|displayTransformation) and inset display box (see 
  54930.     View|insetDisplayBox) of the receiver and all its subViews. The locking 
  54931.     and unlocking of a View is handled automatically by the internal 
  54932.     methods of the View, but can also be done explicitly if desired."
  54933.  
  54934.     self isLocked ifTrue: [^self].
  54935.     displayTransformation _ self computeDisplayTransformation.
  54936.     insetDisplayBox _ self computeInsetDisplayBox.
  54937.     subViews do: [:aSubView | aSubView lock]!
  54938. unlock
  54939.     "Unlock the receiver and all of its subViews (see View|isUnlocked). This 
  54940.     has the effect of forcing the display transformation (see 
  54941.     View|displayTransformation) and inset display box (see 
  54942.     View|insetDisplayBox) of the receiver and all its subViews to be 
  54943.     recomputed the next time they are referenced. The locking and 
  54944.     unlocking of a View is handled automatically by the internal methods of 
  54945.     the View, but can also be done explicitly if desired."
  54946.  
  54947.     self isUnlocked ifTrue: [^self].
  54948.     displayTransformation _ nil.
  54949.     insetDisplayBox _ nil.
  54950.     subViews do: [:aSubView | aSubView unlock]! !
  54951.  
  54952. !View methodsFor: 'subView inserting'!
  54953. addSubView: aView 
  54954.     "Remove aView from the tree of Views it is in (if any) and adds it to the 
  54955.     rear of the list of subViews of the receiver. Set the superView of aView 
  54956.     to be the receiver. It is typically used to build up a hierarchy of Views 
  54957.     (a structured picture). An error notification is generated if aView is the 
  54958.     same as the receiver or its superView, and so on."
  54959.  
  54960.     self addSubView: aView ifCyclic: [self error: 'cycle in subView structure.']!
  54961. addSubView: aSubView above: lowerView
  54962.     "Adds aView (see View|addSubView:) so that it lies above topView."
  54963.  
  54964.     self addSubView: aSubView
  54965.         align: aSubView viewport bottomLeft
  54966.         with: lowerView viewport topLeft!
  54967. addSubView: aSubView align: aPoint1 with: aPoint2 
  54968.     "Add aView to the receiver's list of subViews (see View|addSubView:) 
  54969.     and translate aView so that aPoint1 coincides with aPoint2. It is typically 
  54970.     used to build up a hierarchy of Views (a structured picture). Normally, 
  54971.     aPoint1 is a point on aView's viewport (e.g. aView viewport topLeft), 
  54972.     and aPoint2 is either an arbitrary point in the receiver's coordinate 
  54973.     system or a point on the receiver's window (e.g., self window topRight)."
  54974.  
  54975.     self addSubView: aSubView.
  54976.     aSubView align: aPoint1 with: aPoint2!
  54977. addSubView: aSubView below: lowerView
  54978.     "Add the argument, aSubView, (see View|addSubView:) so that it lies 
  54979.     below the view, topView."
  54980.  
  54981.     self addSubView: aSubView
  54982.         align: aSubView viewport topLeft
  54983.         with: lowerView viewport bottomLeft!
  54984. addSubView: aView ifCyclic: exceptionBlock 
  54985.     "Remove aView from the tree of Views it is in (if any) and add it to the 
  54986.     rear of the list of subViews of the receiver. Set the superView of aView 
  54987.     to be the receiver. It is typically used to build up a hierarchy of Views 
  54988.     (a structured picture). An error notification is generated if aView is the 
  54989.     same as the receiver or its superView, and so on."
  54990.  
  54991.     (self isCyclic: aView)
  54992.         ifTrue: [exceptionBlock value]
  54993.         ifFalse: 
  54994.             [aView removeFromSuperView.
  54995.             subViews addLast: aView.
  54996.             aView superView: self]!
  54997. addSubView: aSubView toLeftOf: rightView
  54998.     "Adds aView (see addSubView:) so that it lies to the right of rightView."
  54999.  
  55000.     self addSubView: aSubView
  55001.         align: aSubView viewport topRight
  55002.         with:  rightView viewport topLeft!
  55003. addSubView: aSubView toRightOf: leftView
  55004.     "Add the argument, aSubView, (see View|addSubView:) so that it lies to 
  55005.     the right of the view, leftView."
  55006.  
  55007.     self addSubView: aSubView
  55008.         align: aSubView viewport topLeft
  55009.         with: leftView viewport topRight!
  55010. addSubView: aView viewport: aViewport 
  55011.     "Add aView to the receiver's list of subViews (see View|addSubView:) and 
  55012.     applies to aView a scale and translation computed from its window and 
  55013.     aViewport (such that its window fills aViewport)."
  55014.  
  55015.     self addSubView: aView.
  55016.     aView window: aView window viewport: aViewport!
  55017. addSubView: aView window: aWindow viewport: aViewport 
  55018.     "Add aView to the receiver's list of subViews (see View|addSubView:) 
  55019.     and applies to aView a scale and translation computed from aWindow 
  55020.     and aViewport (such that aWindow fills aViewport)."
  55021.  
  55022.     self addSubView: aView.
  55023.     aView window: aWindow viewport: aViewport! !
  55024.  
  55025. !View methodsFor: 'subView removing'!
  55026. releaseSubView: aView 
  55027.     "Delete aView from the receiver's list of subViews and send it the 
  55028.     message 'release' (so that it can break up cycles with subViews, etc.)."
  55029.  
  55030.     self removeSubView: aView.
  55031.     aView release!
  55032. releaseSubViews
  55033.     "Release (see View|releaseSubView:) all subViews in the receiver's list of 
  55034.     subViews."
  55035.  
  55036.     subViews do: [:aView | aView release].
  55037.     self resetSubViews!
  55038. removeFromSuperView
  55039.     "Delete the receiver from its superView's collection of subViews."
  55040.  
  55041.     superView ~= nil ifTrue: [superView removeSubView: self]!
  55042. removeSubView: aView 
  55043.     "Delete aView from the receiver's list of subViews. If the list of subViews 
  55044.     does not contain aView, create an error notification."
  55045.  
  55046.     subViews remove: aView.
  55047.     aView superView: nil.
  55048.     aView unlock!
  55049. removeSubViews
  55050.     "Delete all the receiver's subViews."
  55051.  
  55052.     subViews do: 
  55053.         [:aView | 
  55054.         aView superView: nil.
  55055.         aView unlock].
  55056.     self resetSubViews! !
  55057.  
  55058. !View methodsFor: 'displaying'!
  55059. clippingTo: rect do: aBlock
  55060.  
  55061.     superView clippingTo: rect do: aBlock!
  55062. display
  55063.     "Display the receiver's border, display the receiver, then display the 
  55064.     subViews of the receiver. Can be sent to the top View of a structured 
  55065.     picture in order to display the entire structure, or to any particular View 
  55066.     in the structure in order to display that View and its subViews. It is 
  55067.     typically sent in response to an update request to a View."
  55068.  
  55069.     self displayBorder.
  55070.     self displayView.
  55071.     self displaySubViews!
  55072. displayBorder
  55073.     "Display the receiver's border (using the receiver's borderColor)."
  55074.  
  55075.     borderWidth = 0
  55076.         ifTrue:
  55077.             [insideColor == nil
  55078.                 ifFalse: 
  55079.                     [Display fill: self displayBox fillColor: self backgroundColor]]
  55080.         ifFalse:
  55081.             [Display
  55082.                 border: self displayBox
  55083.                 widthRectangle: borderWidth
  55084.                 rule: Form over
  55085.                 fillColor: self foregroundColor.
  55086.             insideColor == nil ifFalse:
  55087.                 [Display fill: self insetDisplayBox fillColor: self backgroundColor]]!
  55088. displayClippingTo: rect
  55089.  
  55090.     | bigRect |
  55091.     bigRect _ rect insetBy: -1.
  55092.     self clippingTo: bigRect do: [Display clippingTo: bigRect do: [self display]]
  55093. !
  55094. displayDeEmphasized
  55095.     self display; deEmphasize!
  55096. displaySubViews
  55097.     "Display all the subViews of the receiver."
  55098.  
  55099.     subViews do: [:aSubView | aSubView display]!
  55100. displayView
  55101.     "Subclasses should redefine View|displayView in order to display 
  55102.     particular objects associated with the View such as labels, lines, and 
  55103.     boxes."
  55104.  
  55105.     ^self!
  55106. displayViewDeEmphasized
  55107.     self displayView; deEmphasizeView!
  55108. inspectFirstSubView
  55109.     subViews notNil ifTrue:
  55110.         [subViews size > 0 ifTrue:
  55111.             [(subViews at: 1) inspect]]!
  55112. inspectModel
  55113.     model notNil
  55114.         ifTrue: [^ model inspect]
  55115.         ifFalse: [self flash]!
  55116. inspectView
  55117.     ^self inspect!
  55118. maximumSize
  55119.     "Answer the maximum size of the receiver."
  55120.  
  55121.     ^ 10000 @ 10000
  55122.     !
  55123. minimumSize
  55124.     "Answer the minimum size of the receiver."
  55125.     ^ 10 @ 10
  55126.     ! !
  55127.  
  55128. !View methodsFor: 'deEmphasizing'!
  55129. deEmphasize
  55130.     "Modify the emphasis (highlighting, special tabs) of the receiver. This 
  55131.     includes objects such as labels, lines, and boxes. Typically used so that 
  55132.     the receiver is not presented as active. Do this for the receiver and then 
  55133.     for each of the receiver's subViews."
  55134.  
  55135.     self deEmphasizeView.
  55136.     self deEmphasizeSubViews!
  55137. deEmphasizeSubViews
  55138.     "Send the deEmphasize message to each of the receiver's subviews."
  55139.  
  55140.     subViews do: [:aSubView | aSubView deEmphasize]!
  55141. deEmphasizeView
  55142.     "Subclasses should redefine View|deEmphasizeView in order to modify 
  55143.     the emphasis (highlighting, special tabs) of particular objects associated 
  55144.     with the View such as labels, lines, and boxes."
  55145.  
  55146.     ^self!
  55147. emphasize
  55148.     "Modify the emphasis (highlighting, special tabs) of the receiver. This 
  55149.     includes objects such as labels, lines, and boxes. Typically used so that 
  55150.     the receiver is presented as active. Do this for the receiver and then 
  55151.     for each of the receiver's subViews."
  55152.  
  55153.     self emphasizeView.
  55154.     self emphasizeSubViews!
  55155. emphasizeSubViews
  55156.     "Send the emphasize message to each of the receiver's subviews."
  55157.  
  55158.     subViews do: [:aSubView | aSubView emphasize]!
  55159. emphasizeView
  55160.     "Subclasses should redefine View|emphasizeView in order to modify 
  55161.     the emphasis (highlighting, special tabs) of particular objects associated 
  55162.     with the View such as labels, lines, and boxes."
  55163.  
  55164.     ^self! !
  55165.  
  55166. !View methodsFor: 'display transformation'!
  55167. displayTransform: anObject 
  55168.     "Apply the display transformation of the receiver to anObject (see 
  55169.     View|displayTransformation) and answer the resulting scaled, translated 
  55170.     object. It is normally applied to Rectangles, Points, and other objects with 
  55171.     coordinates defined in the View's local coordinate system in order to get 
  55172.     a corresponding object in display coordinates."
  55173.  
  55174.     ^(self displayTransformation applyTo: anObject) rounded!
  55175. displayTransformation
  55176.     "Answer a WindowingTransformation that is the result of composing all 
  55177.     local transformations in the receiver's superView chain with the 
  55178.     receiver's own local transformation. The resulting transformation 
  55179.     transforms objects in the receiver's coordinate system into objects in the 
  55180.     display screen coordinate system."
  55181.  
  55182.     displayTransformation == nil
  55183.         ifTrue: [displayTransformation _ self computeDisplayTransformation].
  55184.     ^displayTransformation!
  55185. inverseDisplayTransform: aPoint 
  55186.     "Answer a Point that is obtained from the argument, aPoint, by applying 
  55187.     to it the inverse of the receiver's display transformation. It is typically 
  55188.     used by the Controller of the receiver in order to convert a point in 
  55189.     display coordinates, such as the cursor point, to the local coordinate 
  55190.     system of the receiver."
  55191.  
  55192.     ^self displayTransformation applyInverseTo: aPoint! !
  55193.  
  55194. !View methodsFor: 'transforming'!
  55195. align: aPoint1 with: aPoint2 
  55196.     "Add a translation of (aPoint2 - aPoint1) to the receiver's local 
  55197.     transformation. The point in the receiver's coordinate system that 
  55198.     previously was transformed to aPoint1 in the superView's coordinate 
  55199.     system will now be transformed to aPoint2 in the superView's coordinate 
  55200.     system. Other points will be translated by the same amount. It is 
  55201.     normally used when adding subViews to their superView in order to 
  55202.     line up the Viewport of one subView with that of another subView (see 
  55203.     View|addSubView:align:with:). aPoint1 and aPoint2 are usually points on 
  55204.     the viewports that are to be aligned. For example, 'subView2 align: 
  55205.     subView2 viewport topLeft with: subView1 viewport topRight' would be 
  55206.     used to place the viewport of subView2 next to the viewport of 
  55207.     subView1 with the topLeft and topRight corners, respectively, 
  55208.     coinciding. It is also possible to align the viewport of a subView with 
  55209.     the window of the superView, e.g., 'subView align: subView viewport 
  55210.     center with: superView window center'. View|align:with: assumes that 
  55211.     the view has been properly scaled, if necessary, to match its superView 
  55212.     (see View|scaleBy:). Typically, the coordinate systems of the receiver 
  55213.     and its superView will differ only by a translation offset so that no 
  55214.     scaling is necessary."
  55215.  
  55216.     self setTransformation: (transformation align: aPoint1 with: aPoint2)!
  55217. scale: aScale translation: aTranslation 
  55218.     "The x component of aScale (a Point) specifies the scale (translation) in 
  55219.     the x direction; the y component specifies the scale (translation) in the y 
  55220.     direction. aScale can optionally be an instance of Integer or Float in 
  55221.     order to specify uniform scaling in both directions. Create a new local 
  55222.     transformation for the receiver with a scale factor of aScale and a 
  55223.     translation offset of aTranslation. When the transformation is applied (see 
  55224.     View|transform:), the scale is applied first, followed by the translation. It 
  55225.     is typically used when building a superView from its subViews in order 
  55226.     to line up the viewports of the subViews in the desired way. If no 
  55227.     scaling is required between subView and superView, then 
  55228.     View|align:with: is often more convenient to use."
  55229.  
  55230.     self setTransformation:
  55231.         (WindowingTransformation scale: aScale translation: aTranslation)!
  55232. scaleBy: aScale 
  55233.     "The x component of aScale (a Point) specifies the scale in the x 
  55234.     direction; the y component specifies the scale in the y direction. aScale 
  55235.     can, optionally, be an instance of Integer or Float in order to specify 
  55236.     uniform scaling in both directions. Scales the View by aScale. The scale 
  55237.     is concatenated with the current transformation of the receiver and is 
  55238.     applied when View|transform is sent. This happens automatically in the 
  55239.     process of displaying the receiver, for example."
  55240.  
  55241.     self setTransformation: (transformation scaleBy: aScale)!
  55242. transform: anObject 
  55243.     "Apply the local transformation of the receiver to anObject and answer 
  55244.     the resulting transformation. It is used to get the superView coordinates 
  55245.     of an object. For example, the viewport is equal to the window 
  55246.     transformed."
  55247.  
  55248.     ^transformation applyTo: anObject!
  55249. transformation
  55250.     "Answer a copy of the receiver's local transformation."
  55251.  
  55252.     ^transformation copy!
  55253. transformation: aTransformation 
  55254.     "Set the receiver's local transformation to a copy of aTransformation, 
  55255.     unlock the receiver (see View|unlock) and set the viewport to undefined 
  55256.     (this forces it to be recomputed when needed)."
  55257.  
  55258.     self setTransformation: aTransformation copy!
  55259. translateBy: aPoint 
  55260.     "Translate the receiver by aPoint. The translation is concatenated with 
  55261.     the current transformation of the receiver and is applied when 
  55262.     View|transform is sent. This happens automatically in the process of 
  55263.     displaying the receiver."
  55264.  
  55265.     self setTransformation: (transformation translateBy: aPoint)!
  55266. window: aWindow viewport: aViewport 
  55267.     "Set the receiver's window to aWindow, set its viewport to aViewport, and 
  55268.     create a new local transformation for the receiver based on aWindow and 
  55269.     aViewport. The receiver is scaled and translated so that aWindow, when 
  55270.     transformed, coincides with aViewport. It is used to position a subView's 
  55271.     window within some specific region of its superView's area. For example, 
  55272.     'subView window: aRectangle1 viewport: aRectangle2' sets subView's 
  55273.     window to aRectangle1, its viewport to aRectangle2, and its local 
  55274.     transformation to one that transforms aRectangle1 to aRectange2."
  55275.  
  55276.     self window: aWindow.
  55277.     self setTransformation:
  55278.         (WindowingTransformation window: aWindow viewport: aViewport).
  55279.     self getViewport! !
  55280.  
  55281. !View methodsFor: 'bordering'!
  55282. backgroundColor
  55283.     insideColor == nil ifFalse:
  55284.         [(insideColor isMemberOf: Symbol) ifTrue:
  55285.             [^ Color perform: insideColor].
  55286.         ^ insideColor].
  55287.     superView == nil ifFalse: [^ superView backgroundColor].
  55288.     ^ Display white!
  55289. backgroundColor: aColor
  55290.     insideColor _ aColor!
  55291. borderWidth
  55292.     "Answer either 0, indicating no border, or a Rectangle whose left value is 
  55293.     the width in display coordinates of the receiver's left border. Right, top, 
  55294.     and bottom widths are analogous. The border width is initially 0. A 
  55295.     View with a border width of 0 will not have any border displayed."
  55296.  
  55297.     ^borderWidth!
  55298. borderWidth: anInteger
  55299.     "Set the four border widths of the receiver to anInteger."
  55300.  
  55301.     self
  55302.         borderWidthLeft: anInteger
  55303.         right: anInteger
  55304.         top: anInteger
  55305.         bottom: anInteger!
  55306. borderWidthLeft: anInteger1 right: anInteger2 top: anInteger3 bottom: anInteger4
  55307.     "Set the border widths of the receiver. These arguments represent the left, 
  55308.     right, top, and bottom border widths."
  55309.  
  55310.     borderWidth _
  55311.             Rectangle
  55312.                 left: anInteger1
  55313.                 right: anInteger2
  55314.                 top: anInteger3
  55315.                 bottom: anInteger4.
  55316.     self unlock!
  55317. foregroundColor
  55318.     borderColor == nil ifFalse:
  55319.         [(borderColor isMemberOf: Symbol) ifTrue:
  55320.             [^ Color perform: borderColor].
  55321.         ^ borderColor].
  55322.     superView == nil ifFalse: [^ superView foregroundColor].
  55323.     ^ Display black!
  55324. foregroundColor: aColor
  55325.     borderColor _ aColor!
  55326. insideColor: aColor 
  55327.     ^ self backgroundColor: aColor! !
  55328.  
  55329. !View methodsFor: 'scrolling'!
  55330. scrollBy: aPoint 
  55331.     "The x component of aPoint specifies the amount of scrolling in the x 
  55332.     direction; the y component specifies the amount of scrolling in the y 
  55333.     direction. The amounts are specified in the receiver's local coordinate 
  55334.     system. Scroll the receiver up or down, left or right. The window of the 
  55335.     receiver is kept stationary and the subViews and other objects in the 
  55336.     receiver are translated relative to it. Scrolling doesn't change the 
  55337.     insetDisplayBox or the viewport since the change in the transformation 
  55338.     is canceled by the change in the window. In other words, all display 
  55339.     objects in the view, except the window, are translated by the scrolling 
  55340.     operation.
  55341.     Note: subclasses may override to return false if no scrolling takes place."
  55342.  
  55343.     | aRectangle |
  55344.     aRectangle _ insetDisplayBox.
  55345.     transformation _ transformation scrollBy: aPoint.
  55346.     window _ self getWindow translateBy: aPoint x negated @ aPoint y negated.
  55347.     self unlock.
  55348.     insetDisplayBox _ aRectangle.
  55349.     ^ true! !
  55350.  
  55351. !View methodsFor: 'clearing'!
  55352. clear
  55353.     "Use the border color to paint the display box (including the border, see 
  55354.     View|displayBox) of the receiver."
  55355.  
  55356.     borderColor ~= nil ifTrue: [self clear: Display black]!
  55357. clear: aColor 
  55358.     "Use aColor to paint the display box (including the border, see 
  55359.     View|displayBox) of the receiver."
  55360.  
  55361.     aColor ~= nil ifTrue: [Display fill: self displayBox fillColor: aColor]!
  55362. clearInside
  55363.     "Use the inside color to paint the inset display box (excluding the border, 
  55364.     see View|insetDisplayBox) of the receiver."
  55365.  
  55366.     self clearInside: self backgroundColor!
  55367. clearInside: aColor 
  55368.     "Use aColor to paint the inset display box (excluding the border, see 
  55369.     View|insetDisplayBox) of the receiver."
  55370.  
  55371.     aColor ~~ nil ifTrue: [Display fill: self insetDisplayBox fillColor: aColor]! !
  55372.  
  55373. !View methodsFor: 'indicating'!
  55374. flash
  55375.     "Cause the inset display box (the display box excluding the border, see 
  55376.     View|insetDisplayBox) of the receiver to complement twice in succession."
  55377.  
  55378.     Display flash: self insetDisplayBox!
  55379. highlight
  55380.     "Cause the inset display box (the display box excluding the border, see 
  55381.     View|insetDisplayBox) of the receiver to complement."
  55382.  
  55383.     Display reverse: self insetDisplayBox! !
  55384.  
  55385. !View methodsFor: 'updating'!
  55386. update
  55387.     "Normally sent by the receiver's model in order to notify the receiver of 
  55388.     a change in the model's state. Subclasses implement this message to do 
  55389.     particular update actions. A typical action that might be required is to 
  55390.     redisplay the receiver."
  55391.  
  55392.     self update: self!
  55393. update: aParameter 
  55394.     "Normally sent by the receiver's model in order to notify the receiver of 
  55395.     a change in the model's state. Subclasses implement this message to do 
  55396.     particular update actions. A typical action that might be required is to 
  55397.     redisplay the receiver."
  55398.  
  55399.     ^self! !
  55400.  
  55401. !View methodsFor: 'private'!
  55402. computeDisplayTransformation
  55403.     "Answer a WindowingTransformation that transforms the coordinate 
  55404.     system of the View into that of the display screen. The transformation is 
  55405.     computed by composing the View's transformation with all transformations 
  55406.     along its superView chain. It is sent by View|displayTransformation when
  55407.     the View is unlocked (see View|unlock)."
  55408.  
  55409.     self isTopView
  55410.         ifTrue: [^transformation]
  55411.         ifFalse: [^superView displayTransformation compose: transformation]!
  55412. computeInsetDisplayBox
  55413.     "Compute the View's inset display box by intersecting the superView's
  55414.     inset display box with the View's window transformed to display
  55415.     coordinates and then inseting the result by the border width. It is sent by 
  55416.     View|insetDisplayBox if the inset display box is nil.
  55417.  
  55418.     The insetDisplayBox points are truncated to prevent sending floating point numbers to QuickDraw which will die."
  55419.  
  55420.     self isTopView
  55421.         ifTrue:
  55422.             [^((self displayTransform: self getWindow) insetBy: borderWidth) truncated]
  55423.         ifFalse:
  55424.             [^(superView insetDisplayBox
  55425.                 intersect: (self displayTransform: self getWindow)) truncated
  55426.                         insetBy: borderWidth]!
  55427. getController
  55428.     "Answer the View's controller if one exists. nil indicates that the default
  55429.     controller is to be used."
  55430.  
  55431.     ^controller!
  55432. getViewport
  55433.     "Answer the Rectangle representing the View's viewport (in the
  55434.     coordinate system of the superclass). If no viewport has been specified,
  55435.     the View's window transformed into the superView's coordinate system is
  55436.     saved and returned. It should be used by methods of View and subclasses
  55437.     (instead of directly referring to the viewport) unless it is known that a
  55438.     viewport actually exists. It should not be used outside of View or
  55439.     subclasses because the viewport is not sharable."
  55440.  
  55441.     viewport == nil ifTrue: [viewport _ (self transform: self getWindow) truncated].
  55442.     ^viewport!
  55443. getWindow
  55444.     "Answer the Rectangle that represents the window of this View. If no
  55445.     window has been specified, a default window (see View|defaultWindow)
  55446.     is created, saved, and returned. Should be used by methods of View and
  55447.     subclasses to access the View window instead of directly accessing the
  55448.     field unless it is known that a window actually exists. It is not to be used
  55449.     outside of View (or subclasses) because the window is not sharable.
  55450.     View|window should be used for outside access to the window."
  55451.  
  55452.     window == nil ifTrue: [self setWindow: self defaultWindow].
  55453.     ^window!
  55454. isCyclic: aView 
  55455.     "Answer true if aView is the same as this View or its superView, false 
  55456.     otherwise."
  55457.  
  55458.     self == aView ifTrue: [^true].
  55459.     self isTopView ifTrue: [^false].
  55460.     ^superView isCyclic: aView!
  55461. setTransformation: aTransformation 
  55462.     "Set the View's local transformation to aTransformation, unlock the View 
  55463.     (see View|unlock), and set the viewport to undefined (this forces it to be 
  55464.     recomputed when needed). Should be used instead of setting the 
  55465.     transformation directly."
  55466.  
  55467.     transformation _ aTransformation.
  55468.     self unlock.
  55469.     viewport _ nil!
  55470. setWindow: aWindow 
  55471.     "Set the View's window to aWindow and unlock the View (see
  55472.     View|unlock). View|setWindow should be used by methods of View and
  55473.     subclasses to set the View window (rather than directly setting the
  55474.     instance variable) to insure that the View is unlocked."
  55475.  
  55476.     window _ aWindow.
  55477.     viewport _ nil.
  55478.     self unlock!
  55479. superView: aView 
  55480.     "Set the View's superView to aView and unlock the View (see
  55481.     View|unlock). It is sent by View|addSubView: in order to properly set all
  55482.     the links."
  55483.  
  55484.     superView _ aView.
  55485.     self unlock! !
  55486.  
  55487. !View methodsFor: 'miscellaneous'!
  55488. accepted
  55489.     "The user has told the receiver's controller to accept the current contents.  Take appropriate action if desired.  This place-holder provides a mechanism for intercepting the user's 'accept' request.  7/16/96 sw"!
  55490. clipRect
  55491.     ^ superView clipRect!
  55492. clipRect: r
  55493.     superView clipRect: r!
  55494. grid: aPoint
  55495.     ^ superView grid: aPoint!
  55496. gridSpacing
  55497.     ^ superView gridSpacing!
  55498. nestedViewport
  55499.  
  55500.     "The viewport size used to control scaling of nested user views."
  55501.  
  55502.     ^ (0@0 extent: self viewport extent)
  55503.             insetBy: 16 @ 16!
  55504. printViewSpecOn: strm nested: level
  55505.     "Print window and viewport specs
  55506.     of this and all nested views."
  55507.     strm crtab: level; nextPutAll: self class name.
  55508.     strm crtab: level; nextPutAll: 'window: '; print: self window.
  55509.     strm crtab: level; nextPutAll: 'viewport: '; print: self viewport.
  55510.     strm crtab: level; nextPutAll: 'displayBox: '; print: self displayBox.
  55511.     strm crtab: level; nextPutAll: 'border: '; print: self borderWidth.
  55512.     subViews do: [:v | v printViewSpecOn: strm nested: level+1]! !
  55513. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  55514.  
  55515. View class
  55516.     instanceVariableNames: ''!
  55517.  
  55518. !View class methodsFor: 'instance creation'!
  55519. identityTransformation
  55520.     "Answer an instance of me with no translation and unity scaling."
  55521.  
  55522.     ^WindowingTransformation identity!
  55523. new
  55524.     "Answer an initialized instance of me. The transformation is an identity 
  55525.     transformation, the borderWidth is 0, the borderColor is black, and the 
  55526.     insideColor is transparent."
  55527.  
  55528.     ^super new initialize! !BitBlt subclass: #WarpBlt
  55529.     instanceVariableNames: 'p1x p1y p1z p2x p2y p2z p3x p3y p3z p4x p4y p4z '
  55530.     classVariableNames: ''
  55531.     poolDictionaries: ''
  55532.     category: 'Graphics-Support'!
  55533. WarpBlt comment:
  55534. 'WarpBlt is a little warp-drive added on to BitBlt.  It takes a quadrilateral as its source specification, while its destination is traversed and combined just like any other call to copyBits.
  55535.  
  55536. The source quadrilateral is specified as an array of points starting with the corner that wants to end up in the topLeft, and proceding to the successive points that want to follow CCW around the destination rectangle.  Note that in specifying a plain old rectangle source, its non topLeft points must be actual pixels, not outside by 1, as with rectangle bottmRight, eg.  See the method Rectangle asQuad.
  55537.  
  55538. WarpBlt does a fast job of rotation, reflection and scaling, and it can even produce a semblance of perspective.  Depth parameters are included for future improvements in this direction. but the primitve does not support this yet.'!
  55539.  
  55540. !WarpBlt methodsFor: 'as yet unclassified'!
  55541. copyQuad: pts toRect: aRectangle
  55542.     | fixedPt1 |
  55543.     sourceX _ sourceY _ 0.
  55544.     self destRect: aRectangle.
  55545.     fixedPt1 _ (pts at: 1) x isInteger ifTrue: [16384] ifFalse: [16384.0].
  55546.     p1x _ ((pts at: 1) x * fixedPt1) asInteger.
  55547.     p2x _ ((pts at: 2) x * fixedPt1) asInteger.
  55548.     p3x _ ((pts at: 3) x * fixedPt1) asInteger.
  55549.     p4x _ ((pts at: 4) x * fixedPt1) asInteger.
  55550.     p1y _ ((pts at: 1) y * fixedPt1) asInteger.
  55551.     p2y _ ((pts at: 2) y * fixedPt1) asInteger.
  55552.     p3y _ ((pts at: 3) y * fixedPt1) asInteger.
  55553.     p4y _ ((pts at: 4) y * fixedPt1) asInteger.
  55554.     p1z _ p2z _ p3z _ p4z _ 16384.  "z-warp ignored for now"
  55555.     self warpBits!
  55556. warpBits
  55557.     | deltaP12x deltaP12y deltaP43x deltaP43y pAx pAy pBx pBy deltaPABx deltaPABy sx sy bb fixedPt1 d |
  55558.     <primitive: 147>
  55559.     fixedPt1 _ 16384.  "1.0 in fixed-pt representation"
  55560.     d _ height-1 max: 1.
  55561.     deltaP12x _ p2x - p1x // d.
  55562.     deltaP12y _ p2y - p1y // d.
  55563.     deltaP43x _ p3x - p4x // d.
  55564.     deltaP43y _ p3y - p4y // d.
  55565.     pAx _ p1x.
  55566.     pAy _ p1y.
  55567.     pBx _ p4x.
  55568.     pBy _ p4y.
  55569.     d _ width-1 max: 1.
  55570.     bb _ BitBlt destForm: destForm sourceForm: sourceForm halftoneForm: nil
  55571.         combinationRule: combinationRule destOrigin: 0@0 sourceOrigin: 0@0
  55572.         extent: 1@1 clipRect: self clipRect.
  55573.     destY to: destY+height-1 do:
  55574.         [:y |
  55575.         sx _ pAx.
  55576.         sy _ pAy.
  55577.         deltaPABx _ pBx - pAx // d.
  55578.         deltaPABy _ pBy - pAy // d.
  55579.         destX to: destX+width-1 do:
  55580.             [:x | bb sourceOrigin: (sx//fixedPt1)@(sy//fixedPt1);
  55581.                     destOrigin: x@y;
  55582.                     copyBits.
  55583.             sx _ sx + deltaPABx.
  55584.             sy _ sy + deltaPABy.
  55585.             ].
  55586.         pAx _ pAx + deltaP12x.
  55587.         pAy _ pAy + deltaP12y.
  55588.         pBx _ pBx + deltaP43x.
  55589.         pBy _ pBy + deltaP43y.
  55590.         ]!
  55591. warpBits: pts
  55592.     | fixedPt1 |
  55593.     fixedPt1 _ (pts at: 1) x isInteger ifTrue: [16384] ifFalse: [16384.0].
  55594.     p1x _ ((pts at: 1) x * fixedPt1) asInteger.
  55595.     p2x _ ((pts at: 2) x * fixedPt1) asInteger.
  55596.     p3x _ ((pts at: 3) x * fixedPt1) asInteger.
  55597.     p4x _ ((pts at: 4) x * fixedPt1) asInteger.
  55598.     p1y _ ((pts at: 1) y * fixedPt1) asInteger.
  55599.     p2y _ ((pts at: 2) y * fixedPt1) asInteger.
  55600.     p3y _ ((pts at: 3) y * fixedPt1) asInteger.
  55601.     p4y _ ((pts at: 4) y * fixedPt1) asInteger.
  55602.     p1z _ p2z _ p3z _ p4z _ 16384.  "z-warp ignored for now"
  55603.     sourceX _ sourceY _ 0.
  55604.     self warpBits! !
  55605. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  55606.  
  55607. WarpBlt class
  55608.     instanceVariableNames: ''!
  55609.  
  55610. !WarpBlt class methodsFor: 'as yet unclassified'!
  55611. test1   "Display restoreAfter: [WarpBlt test1]"
  55612.     "Demonstrates variable to scale and rotate"
  55613.     | warp pts r1 p0 p ext |
  55614.     Utilities informUser: 'Choose a rectangle with interesting stuff'
  55615.         during: [r1 _ Rectangle originFromUser: 50@50.
  55616.                 Sensor waitNoButton].
  55617.     Utilities informUser: 'Now click and move the mouse around'
  55618.         during: [p0 _ Sensor waitClickButton.
  55619.                 (Form dotOfSize: 8) displayAt: p0].
  55620.     warp _ (WarpBlt toForm: Display)
  55621.         clipRect: (0@0 extent: r1 extent*5);
  55622.         sourceForm: Display;
  55623.         combinationRule: Form over.
  55624.     [Sensor anyButtonPressed] whileFalse:
  55625.         [p _ Sensor cursorPoint.
  55626.         pts _ {r1 topLeft. r1 bottomLeft. r1 bottomRight. r1 topRight}
  55627.             collect: [:pt | pt rotateBy: (p-p0) theta about: r1 center].
  55628.         ext _ (r1 extent*((p-p0) r / 20.0 max: 0.1)) asIntegerPoint.
  55629.         warp copyQuad: pts toRect: (r1 extent*5-ext//2 extent: ext)]!
  55630. test2   "Display restoreAfter: [WarpBlt test2]"
  55631.     "Magnifying demonstration of WarpBlt's ability to scale and deform"
  55632.     | s nineRects rm nineQuads warp cp cursorQuads |
  55633.     s _ 50.
  55634.     nineRects _ (1 to: 9) collect:
  55635.         [:i | (i-1\\3*s) @ (i-1//3*s) extent: s@s].
  55636.     rm _ (nineRects at: 5) insetBy: s//3.
  55637.     nineQuads _ nineRects collect: [:r | r corners].
  55638.     nineQuads do:
  55639.         [:q | (nineRects at: 5) corners doWithIndex:
  55640.             [:c :i | 1 to: 4 do:
  55641.                 [:j | (q at: j) = c ifTrue:
  55642.                     [q at: j put: (rm corners at: i)]]]].
  55643.     warp _ (WarpBlt toForm: Display)
  55644.         clipRect: (nineRects first topLeft corner: nineRects last bottomRight);
  55645.         sourceForm: Display;
  55646.         combinationRule: Form over.
  55647.     [Sensor anyButtonPressed] whileFalse:
  55648.         [cp _ Sensor cursorPoint-(s asPoint*3//2).
  55649.         cursorQuads _ nineQuads collect:
  55650.             [:q | q collect: [:p | p translateBy: cp]].
  55651.         cursorQuads with: nineRects do:
  55652.             [:q :r | warp copyQuad: q toRect: r]]! !AbstractSound subclass: #WaveTableSound
  55653.     instanceVariableNames: 'waveTable waveTableSize initialCount count initialAmplitude amplitude decayRate increment index '
  55654.     classVariableNames: 'SineTable '
  55655.     poolDictionaries: ''
  55656.     category: 'Sound'!
  55657.  
  55658. !WaveTableSound methodsFor: 'initialization'!
  55659. setPitch: p dur: d loudness: l
  55660.     "((WaveTableSound pitch: 880.0 dur: 1.5 loudness: 500) decayRate: 0.94) play"
  55661.  
  55662.     waveTable _ SineTable.
  55663.     waveTableSize _ waveTable size.
  55664.     self pitch: p.
  55665.     initialCount _ (d * self samplingRate asFloat) rounded.
  55666.     initialAmplitude _ l rounded.
  55667.     decayRate _ 1.0.  "no decay"
  55668.     self reset.! !
  55669.  
  55670. !WaveTableSound methodsFor: 'accessing'!
  55671. decayRate
  55672.  
  55673.     ^ decayRate!
  55674. decayRate: rate
  55675.  
  55676.     decayRate _ rate.!
  55677. loudness
  55678.  
  55679.     ^ amplitude!
  55680. loudness: l
  55681.  
  55682.     initialAmplitude _ l rounded.
  55683.     amplitude _ initialAmplitude.
  55684. !
  55685. pitch
  55686.  
  55687.     ^ (self samplingRate * increment) asFloat / waveTableSize!
  55688. pitch: p
  55689.  
  55690.     increment _ (p asFloat * waveTableSize asFloat) // self samplingRate asFloat.
  55691.     increment _ (increment max: 1) min: ((waveTableSize // 2) - 1).
  55692. ! !
  55693.  
  55694. !WaveTableSound methodsFor: 'sound generation'!
  55695. doControl
  55696.  
  55697.     decayRate ~= 1.0 ifTrue: [
  55698.         amplitude _ (decayRate * amplitude asFloat) asInteger.
  55699.     ].
  55700. !
  55701. mixSampleCount: n into: aSoundBuffer startingAt: startIndex pan: pan
  55702.     "Play samples from a wave table by stepping a fixed amount throught the table on every sample. The decay parameter may be used to make the sound fade away, but its default value of 1.0 produces a sustained sound, like a flute. The abrupt start and stops of this sound result in transient clicks; it would benefit greatly from a simple attack-sustain-decay envelope."
  55703.     "(WaveTableSound pitch: 440.0 dur: 1.0 loudness: 200) play"
  55704.  
  55705.     | lastIndex i mySample channelIndex sample |
  55706.     <primitive: 176>
  55707.     self var: #aSoundBuffer declareC: 'short int *aSoundBuffer'.
  55708.     self var: #waveTable declareC: 'short int *waveTable'.
  55709.  
  55710.     lastIndex _ (startIndex + n) - 1.
  55711.     startIndex to: lastIndex do: [ :i |
  55712.         mySample _ (amplitude * (waveTable at: index)) // 1000.
  55713.         pan > 0 ifTrue: [
  55714.             channelIndex _ 2 * i.
  55715.             sample _ (aSoundBuffer at: channelIndex) + ((mySample * pan) // 1000).
  55716.             sample >  32767 ifTrue: [ sample _  32767 ].  "clipping!!"
  55717.             sample < -32767 ifTrue: [ sample _ -32767 ].  "clipping!!"
  55718.             aSoundBuffer at: channelIndex put: sample.
  55719.         ].
  55720.         pan < 1000 ifTrue: [
  55721.             channelIndex _ (2 * i) - 1.
  55722.             sample _ (aSoundBuffer at: channelIndex) + ((mySample * (1000 - pan)) // 1000).
  55723.             sample >  32767 ifTrue: [ sample _  32767 ].  "clipping!!"
  55724.             sample < -32767 ifTrue: [ sample _ -32767 ].  "clipping!!"
  55725.             aSoundBuffer at: channelIndex put: sample.
  55726.         ].
  55727.  
  55728.         index _ index + increment.
  55729.         index > waveTableSize ifTrue: [
  55730.             index _ index - waveTableSize.
  55731.         ].
  55732.     ].
  55733.     count _ count - n.
  55734. !
  55735. reset
  55736.  
  55737.     super reset.
  55738.     amplitude _ initialAmplitude.
  55739.     count _ initialCount.
  55740.     index _ 1.
  55741. !
  55742. samplesRemaining
  55743.  
  55744.     ^ count! !
  55745. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  55746.  
  55747. WaveTableSound class
  55748.     instanceVariableNames: ''!
  55749.  
  55750. !WaveTableSound class methodsFor: 'class initialization'!
  55751. initialize
  55752.     "Build a sine wave table."
  55753.     "WaveTableSound initialize"
  55754.  
  55755.     | radiansPerStep scale |
  55756.     SineTable _ SoundBuffer new: 10000.
  55757.     radiansPerStep _ (2.0 * Float pi) / SineTable size asFloat.
  55758.     scale _ ((1 bitShift: 15) - 1) asFloat.  "range is +/- (2^15 - 1)"
  55759.     1 to: SineTable size do: [ :i |
  55760.         SineTable at: i put:
  55761.             (scale * (radiansPerStep * i) sin) rounded.
  55762.     ].
  55763. ! !
  55764.  
  55765. WaveTableSound initialize!
  55766. Object subclass: #WindowingTransformation
  55767.     instanceVariableNames: 'scale translation '
  55768.     classVariableNames: ''
  55769.     poolDictionaries: ''
  55770.     category: 'Interface-Framework'!
  55771. WindowingTransformation comment:
  55772. 'My instances are used to transform objects from a source coordinate system to a destination coordinate system. Each instance contains a scale and a translation which can be applied to objects that respond to scaleBy: and translateBy:. It can be created with a default identity scale and translation, or with a specified scale and translation, or with a scale and translation computed from a window (a Rectangle in the source coordinate system) and a viewport (a Rectangle in the destination coordinate system). In applying a WindowingTransformation to an object, the object is first scaled (around the origin of the source coordinate system) and then translated. WindowingTransformations can be composed to form a single compound transformation.'!
  55773.  
  55774. !WindowingTransformation methodsFor: 'scrolling'!
  55775. scrollBy: aPoint 
  55776.     "Answer a WindowingTransformation with the same scale as the receiver 
  55777.     and with a translation of the current translation plus aPoint scaled by 
  55778.     the current scale. It is used when the translation is known in source 
  55779.     coordinates, rather than scaled source coordinates (see 
  55780.     WindowingTransformation|translateBy:). An example is that of scrolling 
  55781.     objects with respect to a stationary window in the source coordinate 
  55782.     system. If no scaling is in effect (scale = nil), then 
  55783.     WindowingTransformation|translateBy: and 
  55784.     WindowingTransformation|scrollBy: are equivalent."
  55785.  
  55786.     | newTranslation |
  55787.     scale == nil
  55788.         ifTrue: [newTranslation _ aPoint]
  55789.         ifFalse: [newTranslation _ scale * aPoint].
  55790.     ^self translateBy: newTranslation! !
  55791.  
  55792. !WindowingTransformation methodsFor: 'transforming'!
  55793. align: point1 with: point2 
  55794.     "Answer a WindowingTransformation with the same scale as the receiver 
  55795.     and with a translation of (aPoint2 - aPoint1). It is normally used when 
  55796.     the source and destination coordinate systems are scaled the same (that 
  55797.     is, there is no scaling between them), and is then a convenient way of 
  55798.     specifying a translation, given two points that are intended to coincide."
  55799.  
  55800.     ^self translateBy: point2 - point1!
  55801. noScale
  55802.     "Answer true if the identity scale is in effect; answer false, otherwise."
  55803.  
  55804.     ^scale == nil!
  55805. scale
  55806.     "Answer a copy of the point that represents the current scale of the 
  55807.     receiver."
  55808.  
  55809.     scale == nil
  55810.         ifTrue: [^1.0 @ 1.0]
  55811.         ifFalse: [^scale copy]!
  55812. scaleBy: aScale 
  55813.     "Answer a WindowingTransformation with the scale and translation of 
  55814.     the receiver both scaled by aScale."
  55815.  
  55816.     | checkedScale newScale newTranslation |
  55817.     aScale == nil
  55818.         ifTrue: 
  55819.             [newScale _ scale.
  55820.             newTranslation _ translation]
  55821.         ifFalse: 
  55822.             [checkedScale _ self checkScale: aScale.
  55823.             scale == nil
  55824.                 ifTrue: [newScale _ checkedScale]
  55825.                 ifFalse: [newScale _ scale * checkedScale].
  55826.             newTranslation _ checkedScale * translation].
  55827.     ^WindowingTransformation scale: newScale translation: newTranslation!
  55828. translateBy: aPoint 
  55829.     "Answer a WindowingTransformation with the same scale as the receiver 
  55830.     and with a translation of the current translation plus aPoint. It is used 
  55831.     when the translation is known in scaled source coordinates, rather than 
  55832.     source coordinates (see WindowingTransformation|scrollBy:). If no scaling 
  55833.     is in effect (scale = nil), then WindowingTransformation|translateBy: and 
  55834.     WindowingTransformation|scrollBy: are equivalent."
  55835.  
  55836.     ^WindowingTransformation scale: scale translation: translation + aPoint!
  55837. translation
  55838.     "Answer a copy of the receiver's translation."
  55839.  
  55840.     ^translation copy! !
  55841.  
  55842. !WindowingTransformation methodsFor: 'applying transform'!
  55843. applyInverseTo: anObject 
  55844.     "Apply the inverse of the receiver to anObject and answer the result. 
  55845.     Used to map some object in destination coordinates to one in source 
  55846.     coordinates."
  55847.  
  55848.     | transformedObject |
  55849.     transformedObject _ anObject translateBy: translation x negated @ translation y negated.
  55850.     scale == nil
  55851.         ifFalse: [transformedObject _ transformedObject scaleBy: 1.0 / scale x @ (1.0 / scale y)].
  55852.     ^transformedObject!
  55853. applyTo: anObject 
  55854.     "Apply the receiver to anObject and answer the result. Used to map some 
  55855.     object in source coordinates to one in destination coordinates."
  55856.  
  55857.     | transformedObject |
  55858.     scale == nil
  55859.         ifTrue: [transformedObject _ anObject]
  55860.         ifFalse: [transformedObject _ anObject scaleBy: scale].
  55861.     transformedObject _ transformedObject translateBy: translation.
  55862.     ^transformedObject!
  55863. compose: aTransformation 
  55864.     "Answer a WindowingTransformation that is the composition of the 
  55865.     receiver and aTransformation. The effect of applying the resulting 
  55866.     WindowingTransformation to an object is the same as that of first 
  55867.     applying aTransformation to the object and then applying the receiver to 
  55868.     its result."
  55869.  
  55870.     | aTransformationScale newScale newTranslation |
  55871.     aTransformationScale _ aTransformation scale.
  55872.     scale == nil
  55873.         ifTrue: 
  55874.             [aTransformation noScale
  55875.                 ifTrue: [newScale _ nil]
  55876.                 ifFalse: [newScale _ aTransformationScale].
  55877.             newTranslation _ translation + aTransformation translation]
  55878.         ifFalse: 
  55879.             [aTransformation noScale
  55880.                 ifTrue: [newScale _ scale]
  55881.                 ifFalse: [newScale _ scale * aTransformationScale].
  55882.             newTranslation _ translation + (scale * aTransformation translation)].
  55883.     ^WindowingTransformation scale: newScale translation: newTranslation! !
  55884.  
  55885. !WindowingTransformation methodsFor: 'printing'!
  55886. printOn: aStream 
  55887.     "Refer to the comment in Object|printOn:."
  55888.  
  55889.     aStream nextPutAll: self class name, ' scale: ';
  55890.         print: scale; nextPutAll: ' translation: ';
  55891.         print: translation! !
  55892.  
  55893. !WindowingTransformation methodsFor: 'private'!
  55894. checkScale: aScale
  55895.     "Convert aScale to the internal format of a floating-point Point."
  55896.  
  55897.      | checkedScale |
  55898.     checkedScale _ aScale asPoint.
  55899.     ^checkedScale x asFloat @ checkedScale y asFloat!
  55900. setScale: aScale translation: aTranslation 
  55901.     "Sets the scale to aScale and the translation to aTranslation."
  55902.  
  55903.     scale _ aScale.
  55904.     translation _ aTranslation! !
  55905. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  55906.  
  55907. WindowingTransformation class
  55908.     instanceVariableNames: ''!
  55909.  
  55910. !WindowingTransformation class methodsFor: 'instance creation'!
  55911. identity
  55912.     "Answer an instance of me with no scaling (nil) and no translation 
  55913.     (0@0)."
  55914.  
  55915.     ^self new setScale: nil translation: 0 @ 0!
  55916. scale: aScale translation: aTranslation 
  55917.     "Answer an instance of me with a scale factor of aScale and a translation 
  55918.     offset of aTranslation. When the transformation is applied (see 
  55919.     WindowingTransformation|apply:), the scale is applied first, followed by 
  55920.     the translation."
  55921.  
  55922.     ^self new setScale: aScale translation: aTranslation!
  55923. window: aWindow viewport: aViewport 
  55924.     "Answer an instance of me with a scale and translation based on 
  55925.     aWindow and aViewport. The scale and translation are computed such 
  55926.     that aWindow, when transformed, coincides with aViewport."
  55927.  
  55928.     | scale translation |
  55929.     aViewport width = aWindow width & (aViewport height = aWindow height)
  55930.         ifTrue:
  55931.             [scale _ nil]
  55932.         ifFalse:
  55933.             [scale _ aViewport width asFloat / aWindow width asFloat
  55934.                         @ (aViewport height asFloat / aWindow height asFloat)].
  55935.     scale == nil
  55936.         ifTrue: [translation _ aViewport left - aWindow left
  55937.                                 @ (aViewport top - aWindow top)]
  55938.         ifFalse: [translation _ aViewport left - (scale x * aWindow left)
  55939.                                 @ (aViewport top - (scale y * aWindow top))].
  55940.     ^self new setScale: scale translation: translation! !StringHolder subclass: #Workspace
  55941.     instanceVariableNames: 'bindings '
  55942.     classVariableNames: ''
  55943.     poolDictionaries: ''
  55944.     category: 'Interface-Support'!
  55945.  
  55946. !Workspace methodsFor: 'binding'!
  55947. bindingOf: aString
  55948.     bindings isNil
  55949.         ifTrue: [bindings _ Dictionary new].
  55950.     (bindings includesKey: aString)
  55951.         ifFalse: [bindings at: aString put: nil].
  55952.     ^bindings associationAt: aString! !PositionableStream subclass: #WriteStream
  55953.     instanceVariableNames: 'writeLimit '
  55954.     classVariableNames: ''
  55955.     poolDictionaries: ''
  55956.     category: 'Collections-Streams'!
  55957. WriteStream comment:
  55958. 'I represent an accessor for a sequence of objects that can only store objects in the sequence.'!
  55959.  
  55960. !WriteStream methodsFor: 'accessing'!
  55961. contents
  55962.  
  55963.     readLimit _ readLimit max: position.
  55964.     ^collection copyFrom: 1 to: position!
  55965. next
  55966.  
  55967.     self shouldNotImplement!
  55968. nextPut: anObject 
  55969.     "Primitive. Insert the argument at the next position in the Stream
  55970.     represented by the receiver. Fail if the collection of this stream is not an
  55971.     Array or a String. Fail if the stream is positioned at its end, or if the
  55972.     position is out of bounds in the collection. Fail if the argument is not
  55973.     of the right type for the collection. Optional. See Object documentation
  55974.     whatIsAPrimitive."
  55975.  
  55976.     <primitive: 66>
  55977.     position = writeLimit
  55978.         ifTrue: [^self pastEndPut: anObject]
  55979.         ifFalse: 
  55980.             [position _ position + 1.
  55981.             ^collection at: position put: anObject]!
  55982. size
  55983.  
  55984.     ^readLimit _ readLimit max: position! !
  55985.  
  55986. !WriteStream methodsFor: 'positioning'!
  55987. position: anInteger 
  55988.     "Refer to the comment in PositionableStream|position:."
  55989.  
  55990.     readLimit _ readLimit max: position.
  55991.     super position: anInteger!
  55992. reset 
  55993.     "Refer to the comment in PositionableStream|reset."
  55994.  
  55995.     readLimit _ readLimit max: position.
  55996.     position _ 0! !
  55997.  
  55998. !WriteStream methodsFor: 'character writing'!
  55999. cr
  56000.     "Append a return character to the receiver."
  56001.  
  56002.     self nextPut: Character cr!
  56003. crtab
  56004.     "Append a return character, followed by a single tab character, to the 
  56005.     receiver."
  56006.  
  56007.     self nextPut: Character cr.
  56008.     self nextPut: Character tab!
  56009. crtab: anInteger 
  56010.     "Append a return character, followed by anInteger tab characters, to the 
  56011.     receiver."
  56012.  
  56013.     self nextPut: Character cr.
  56014.     anInteger timesRepeat: [self nextPut: Character tab]!
  56015. emphasis: ignored
  56016.     "Allows compatibility with streams which carry emphasis."!
  56017. space
  56018.     "Append a space character to the receiver."
  56019.  
  56020.     self nextPut: Character space!
  56021. tab
  56022.     "Append a tab character to the receiver."
  56023.  
  56024.     self nextPut: Character tab! !
  56025.  
  56026. !WriteStream methodsFor: 'fileIn/Out'!
  56027. nextChunkPut: aString
  56028.     "Append the argument, aString, to the receiver, doubling embedded terminators."
  56029.  
  56030.     | i remainder terminator |
  56031.     terminator _ $!!.
  56032.     remainder _ aString.
  56033.     [(i _ remainder indexOf: terminator) = 0] whileFalse:
  56034.         [self nextPutAll: (remainder copyFrom: 1 to: i).
  56035.         self nextPut: terminator.  "double imbedded terminators"
  56036.         remainder _ remainder copyFrom: i+1 to: remainder size].
  56037.     self nextPutAll: remainder; nextPut: terminator! !
  56038.  
  56039. !WriteStream methodsFor: 'printing'!
  56040. print: anObject 
  56041.     "Have anObject print on the receiver."
  56042.  
  56043.     anObject printOn: self!
  56044. store: anObject 
  56045.     "Have anObject print on the receiver for purposes of rereading."
  56046.  
  56047.     anObject storeOn: self! !
  56048.  
  56049. !WriteStream methodsFor: 'private'!
  56050. on: aCollection
  56051.  
  56052.     super on: aCollection.
  56053.     readLimit _ 0.
  56054.     writeLimit _ aCollection size!
  56055. on: aCollection from: firstIndex to: lastIndex
  56056.  
  56057.     | len |
  56058.     collection _ aCollection.
  56059.     readLimit _ 
  56060.         writeLimit _ lastIndex > (len _ collection size)
  56061.                         ifTrue: [len]
  56062.                         ifFalse: [lastIndex].
  56063.     position _ firstIndex <= 1
  56064.                 ifTrue: [0]
  56065.                 ifFalse: [firstIndex - 1]!
  56066. pastEndPut: anObject
  56067.     collection _ collection ,
  56068.         (collection class new: ((collection size max: 20) min: 5000)).
  56069.     writeLimit _ collection size.
  56070.     collection at: (position _ position + 1) put: anObject!
  56071. with: aCollection
  56072.  
  56073.     super on: aCollection.
  56074.     position _ readLimit _ writeLimit _ aCollection size! !
  56075. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  56076.  
  56077. WriteStream class
  56078.     instanceVariableNames: ''!
  56079.  
  56080. !WriteStream class methodsFor: 'instance creation'!
  56081. on: aCollection from: firstIndex to: lastIndex 
  56082.     "Answer an instance of me on a copy of the argument, aCollection, 
  56083.     determined by the indices firstIndex and lastIndex. Position the instance 
  56084.     at the beginning of the collection."
  56085.  
  56086.     ^self basicNew
  56087.         on: aCollection
  56088.         from: firstIndex
  56089.         to: lastIndex!
  56090. with: aCollection 
  56091.     "Answer an instance of me on the argument, aCollection, positioned to 
  56092.     store objects at the end of aCollection."
  56093.  
  56094.     ^self basicNew with: aCollection!
  56095. with: aCollection from: firstIndex to: lastIndex 
  56096.     "Answer an instance of me on the subcollection of the argument, 
  56097.     aCollection, determined by the indices firstIndex and lastIndex. Position 
  56098.     the instance to store at the end of the subcollection."
  56099.  
  56100.     ^self basicNew with: (aCollection copyFrom: firstIndex to: lastIndex)! !